-
Notifications
You must be signed in to change notification settings - Fork 18.4k
Description
Open this issue to discuss pdqsort behavior. cc @randall77 , please take a look, thanks!
- Why in CL 371574 we need to use
{{GreaterOrEqual}}
instead of!{{Less}}
After we used go run gen_sort_variants.go -generic
to generate code for package slices
, we found that the slices test will fail in float64 slice(slices/sort_test.go:TestSortFloat64Slice
).
The reason for this error is that in pdqsort we use if a > 0 && !{{Less "data" "a-1" "pivot"}}
to detect if we selected the same pivot twice for partition, which is fine in most cases. But in slices/zsortordered.go
(generated codes), this line will be if a > 0 && !(data[a-1]<data[pivot])
, when data[pivot]
or data[a-1]
is NaN, !(data[a-1]<data[pivot])
is always true, resulting in incorrect algorithm behavior(mistakenly believe that data[a-1]
equals data[pivot]
).
The fix is PatchSet18 at CL 371574, we can see the diff in https://go-review.googlesource.com/c/go/+/371574/17..18. In this patch, we use {{GreaterOrEqual}}
instead of !{{Less}}
, for other files, {{GreaterOrEqual}}
is !{{Less}}
(keep the same as before), for slices/zsortordered.go
, the generated code will be if a > 0 && (data[a-1]>=data[pivot])
, which can solve the problem. This change should only work for zsortordered.go:pdqsort
, but it still changes StableSort's code due to global replacement, so we need to fix this in the new CL.
The reason for these problems is that we use if a > 0 && !{{Less "data" "a-1" "pivot"}}
in pdqsort to determine whether there are duplicate pivot selections (data [a-1]
must be less than or equal to pivot if exists). If this mechanism is removed, we can use !Less
instead of {{GreaterOrEqual}}
in all cases. I'm still not sure if there is a better way to implement this mechanism.
BTW, if we use different maxInsertion
in sort and slices as discussed earlier, it will also lead to inconsistent algorithm behavior, does this mean that we can't use different maxInsertion
in different versions?