Skip to content

Commit

Permalink
union-types: use insertion (stable) sort instead of qsort
Browse files Browse the repository at this point in the history
Different platforms implement qsort differently, leading to
platform-specific errors. This is a quick port of the ml_matches
algorithm for use instead. For small unions (almost always), this should
also be slightly faster, though insignificant.

Refs #45874
  • Loading branch information
vtjnash committed Jul 1, 2022
1 parent bd7bd5e commit cfe770a
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 12 deletions.
8 changes: 6 additions & 2 deletions base/sort.jl
Original file line number Diff line number Diff line change
Expand Up @@ -515,8 +515,12 @@ function sort!(v::AbstractVector, lo::Integer, hi::Integer, ::InsertionSortAlg,
@inbounds for i = lo+1:hi
j = i
x = v[i]
while j > lo && lt(o, x, v[j-1])
v[j] = v[j-1]
while j > lo
y = v[j-1]
if !lt(o, x, y)
break
end
v[j] = y
j -= 1
end
v[j] = x
Expand Down
35 changes: 25 additions & 10 deletions src/jltypes.c
Original file line number Diff line number Diff line change
Expand Up @@ -420,10 +420,8 @@ static int datatype_name_cmp(jl_value_t *a, jl_value_t *b) JL_NOTSAFEPOINT

// sort singletons first, then DataTypes, then UnionAlls,
// ties broken alphabetically including module name & type parameters
static int union_sort_cmp(const void *ap, const void *bp) JL_NOTSAFEPOINT
static int union_sort_cmp(jl_value_t *a, jl_value_t *b) JL_NOTSAFEPOINT
{
jl_value_t *a = *(jl_value_t**)ap;
jl_value_t *b = *(jl_value_t**)bp;
if (a == NULL)
return b == NULL ? 0 : 1;
if (b == NULL)
Expand Down Expand Up @@ -458,16 +456,33 @@ static int union_sort_cmp(const void *ap, const void *bp) JL_NOTSAFEPOINT
}
}

static void isort_union(jl_value_t **a, size_t len) JL_NOTSAFEPOINT
{
size_t i, j;
for (i = 1; i < len; i++) {
jl_value_t *x = a[i];
for (j = i; j > 0; j--) {
jl_value_t *y = a[j - 1];
if (!(union_sort_cmp(x, y) < 0))
break;
a[j] = y;
}
a[j] = x;
}
}

JL_DLLEXPORT jl_value_t *jl_type_union(jl_value_t **ts, size_t n)
{
if (n == 0) return (jl_value_t*)jl_bottom_type;
if (n == 0)
return (jl_value_t*)jl_bottom_type;
size_t i;
for(i=0; i < n; i++) {
for (i = 0; i < n; i++) {
jl_value_t *pi = ts[i];
if (!(jl_is_type(pi) || jl_is_typevar(pi)))
jl_type_error("Union", (jl_value_t*)jl_type_type, pi);
}
if (n == 1) return ts[0];
if (n == 1)
return ts[0];

size_t nt = count_union_components(ts, n);
jl_value_t **temp;
Expand All @@ -476,9 +491,9 @@ JL_DLLEXPORT jl_value_t *jl_type_union(jl_value_t **ts, size_t n)
flatten_type_union(ts, n, temp, &count);
assert(count == nt);
size_t j;
for(i=0; i < nt; i++) {
int has_free = temp[i]!=NULL && jl_has_free_typevars(temp[i]);
for(j=0; j < nt; j++) {
for (i = 0; i < nt; i++) {
int has_free = temp[i] != NULL && jl_has_free_typevars(temp[i]);
for (j = 0; j < nt; j++) {
if (j != i && temp[i] && temp[j]) {
if (temp[i] == jl_bottom_type ||
temp[j] == (jl_value_t*)jl_any_type ||
Expand All @@ -490,7 +505,7 @@ JL_DLLEXPORT jl_value_t *jl_type_union(jl_value_t **ts, size_t n)
}
}
}
qsort(temp, nt, sizeof(jl_value_t*), union_sort_cmp);
isort_union(temp, nt);
jl_value_t **ptu = &temp[nt];
*ptu = jl_bottom_type;
int k;
Expand Down

0 comments on commit cfe770a

Please sign in to comment.