Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
dragonwell8_jdk
提交
29ca4456
D
dragonwell8_jdk
项目概览
openanolis
/
dragonwell8_jdk
通知
4
Star
2
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
D
dragonwell8_jdk
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
29ca4456
编写于
7月 01, 2010
作者:
A
alanb
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
6947216: Even more Dual-pivot quicksort improvements
Reviewed-by: jjb Contributed-by: vladimir.yaroslavskiy@sun.com
上级
d6b9303f
变更
2
显示空白变更内容
内联
并排
Showing
2 changed file
with
2173 addition
and
1394 deletion
+2173
-1394
src/share/classes/java/util/DualPivotQuicksort.java
src/share/classes/java/util/DualPivotQuicksort.java
+1733
-1274
test/java/util/Arrays/Sorting.java
test/java/util/Arrays/Sorting.java
+440
-120
未找到文件。
src/share/classes/java/util/DualPivotQuicksort.java
浏览文件 @
29ca4456
/*
/*
* Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2009,
2010,
Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
*
* This code is free software; you can redistribute it and/or modify it
* This code is free software; you can redistribute it and/or modify it
...
@@ -27,7 +27,7 @@ package java.util;
...
@@ -27,7 +27,7 @@ package java.util;
/**
/**
* This class implements the Dual-Pivot Quicksort algorithm by
* This class implements the Dual-Pivot Quicksort algorithm by
* Vladimir Yaroslavskiy, Jon Bentley, and Josh
ua
Bloch. The algorithm
* Vladimir Yaroslavskiy, Jon Bentley, and Josh Bloch. The algorithm
* offers O(n log(n)) performance on many data sets that cause other
* offers O(n log(n)) performance on many data sets that cause other
* quicksorts to degrade to quadratic performance, and is typically
* quicksorts to degrade to quadratic performance, and is typically
* faster than traditional (one-pivot) Quicksort implementations.
* faster than traditional (one-pivot) Quicksort implementations.
...
@@ -36,7 +36,8 @@ package java.util;
...
@@ -36,7 +36,8 @@ package java.util;
* @author Jon Bentley
* @author Jon Bentley
* @author Josh Bloch
* @author Josh Bloch
*
*
* @version 2009.11.29 m765.827.12i
* @version 2010.06.21 m765.827.12i:5\7
* @since 1.7
*/
*/
final
class
DualPivotQuicksort
{
final
class
DualPivotQuicksort
{
...
@@ -68,7 +69,7 @@ final class DualPivotQuicksort {
...
@@ -68,7 +69,7 @@ final class DualPivotQuicksort {
private
static
final
int
COUNTING_SORT_THRESHOLD_FOR_SHORT_OR_CHAR
=
32768
;
private
static
final
int
COUNTING_SORT_THRESHOLD_FOR_SHORT_OR_CHAR
=
32768
;
/*
/*
* Sorting methods for
7
primitive types.
* Sorting methods for
seven
primitive types.
*/
*/
/**
/**
...
@@ -77,7 +78,7 @@ final class DualPivotQuicksort {
...
@@ -77,7 +78,7 @@ final class DualPivotQuicksort {
* @param a the array to be sorted
* @param a the array to be sorted
*/
*/
public
static
void
sort
(
int
[]
a
)
{
public
static
void
sort
(
int
[]
a
)
{
doSort
(
a
,
0
,
a
.
length
-
1
);
sort
(
a
,
0
,
a
.
length
-
1
,
true
);
}
}
/**
/**
...
@@ -95,95 +96,129 @@ final class DualPivotQuicksort {
...
@@ -95,95 +96,129 @@ final class DualPivotQuicksort {
*/
*/
public
static
void
sort
(
int
[]
a
,
int
fromIndex
,
int
toIndex
)
{
public
static
void
sort
(
int
[]
a
,
int
fromIndex
,
int
toIndex
)
{
rangeCheck
(
a
.
length
,
fromIndex
,
toIndex
);
rangeCheck
(
a
.
length
,
fromIndex
,
toIndex
);
doSort
(
a
,
fromIndex
,
toIndex
-
1
);
sort
(
a
,
fromIndex
,
toIndex
-
1
,
true
);
}
}
/**
/**
* Sorts the specified range of the array into ascending order. This
* Sorts the specified range of the array into ascending order by the
* method differs from the public {@code sort} method in that the
* Dual-Pivot Quicksort algorithm. This method differs from the public
* {@code right} index is inclusive, and it does no range checking
* {@code sort} method in that the {@code right} index is inclusive,
* on {@code left} or {@code right}.
* it does no range checking on {@code left} or {@code right}, and has
* boolean flag whether insertion sort with sentinel is used or not.
*
*
* @param a the array to be sorted
* @param a the array to be sorted
* @param left the index of the first element, inclusive, to be sorted
* @param left the index of the first element, inclusive, to be sorted
* @param right the index of the last element, inclusive, to be sorted
* @param right the index of the last element, inclusive, to be sorted
* @param leftmost indicates if the part is the most left in the range
*/
*/
private
static
void
doSort
(
int
[]
a
,
int
left
,
int
right
)
{
private
static
void
sort
(
int
[]
a
,
int
left
,
int
right
,
boolean
leftmost
)
{
int
length
=
right
-
left
+
1
;
// Use insertion sort on tiny arrays
// Use insertion sort on tiny arrays
if
(
right
-
left
+
1
<
INSERTION_SORT_THRESHOLD
)
{
if
(
length
<
INSERTION_SORT_THRESHOLD
)
{
for
(
int
i
=
left
+
1
;
i
<=
right
;
i
++)
{
if
(!
leftmost
)
{
/*
* Every element in adjoining part plays the role
* of sentinel, therefore this allows us to avoid
* the j >= left check on each iteration.
*/
for
(
int
j
,
i
=
left
+
1
;
i
<=
right
;
i
++)
{
int
ai
=
a
[
i
];
int
ai
=
a
[
i
];
int
j
;
for
(
j
=
i
-
1
;
ai
<
a
[
j
];
j
--)
{
for
(
j
=
i
-
1
;
j
>=
left
&&
ai
<
a
[
j
];
j
--)
{
// assert j >= left;
a
[
j
+
1
]
=
a
[
j
];
}
a
[
j
+
1
]
=
ai
;
}
}
else
{
/*
* For case of leftmost part traditional (without a sentinel)
* insertion sort, optimized for server JVM, is used.
*/
for
(
int
i
=
left
,
j
=
i
;
i
<
right
;
j
=
++
i
)
{
int
ai
=
a
[
i
+
1
];
while
(
ai
<
a
[
j
])
{
a
[
j
+
1
]
=
a
[
j
];
a
[
j
+
1
]
=
a
[
j
];
if
(
j
--
==
left
)
{
break
;
}
}
}
a
[
j
+
1
]
=
ai
;
a
[
j
+
1
]
=
ai
;
}
}
}
else
{
// Use Dual-Pivot Quicksort on large arrays
dualPivotQuicksort
(
a
,
left
,
right
);
}
}
return
;
}
}
/**
// Inexpensive approximation of length / 7
* Sorts the specified range of the array into ascending order by the
int
seventh
=
(
length
>>>
3
)
+
(
length
>>>
6
)
+
1
;
* Dual-Pivot Quicksort algorithm.
*
/*
* @param a the array to be sorted
* Sort five evenly spaced elements around (and including) the
* @param left the index of the first element, inclusive, to be sorted
* center element in the range. These elements will be used for
* @param right the index of the last element, inclusive, to be sorted
* pivot selection as described below. The choice for spacing
* these elements was empirically determined to work well on
* a wide variety of inputs.
*/
*/
private
static
void
dualPivotQuicksort
(
int
[]
a
,
int
left
,
int
right
)
{
// Compute indices of five evenly spaced elements
int
sixth
=
(
right
-
left
+
1
)
/
6
;
int
e1
=
left
+
sixth
;
int
e5
=
right
-
sixth
;
int
e3
=
(
left
+
right
)
>>>
1
;
// The midpoint
int
e3
=
(
left
+
right
)
>>>
1
;
// The midpoint
int
e4
=
e3
+
sixth
;
int
e2
=
e3
-
seventh
;
int
e2
=
e3
-
sixth
;
int
e1
=
e2
-
seventh
;
int
e4
=
e3
+
seventh
;
int
e5
=
e4
+
seventh
;
// Sort these elements using
a 5-element sorting network
// Sort these elements using
insertion sort
i
nt
ae1
=
a
[
e1
],
ae2
=
a
[
e2
],
ae3
=
a
[
e3
],
ae4
=
a
[
e4
],
ae5
=
a
[
e5
];
i
f
(
a
[
e2
]
<
a
[
e1
])
{
int
t
=
a
[
e2
];
a
[
e2
]
=
a
[
e1
];
a
[
e1
]
=
t
;
}
if
(
ae1
>
ae2
)
{
int
t
=
ae1
;
ae1
=
ae2
;
ae2
=
t
;
}
if
(
a
[
e3
]
<
a
[
e2
])
{
int
t
=
a
[
e3
];
a
[
e3
]
=
a
[
e2
];
a
[
e2
]
=
t
;
if
(
ae4
>
ae5
)
{
int
t
=
ae4
;
ae4
=
ae5
;
ae5
=
t
;
}
if
(
t
<
a
[
e1
])
{
a
[
e2
]
=
a
[
e1
];
a
[
e1
]
=
t
;
}
if
(
ae1
>
ae3
)
{
int
t
=
ae1
;
ae1
=
ae3
;
ae3
=
t
;
}
}
if
(
ae2
>
ae3
)
{
int
t
=
ae2
;
ae2
=
ae3
;
ae3
=
t
;
}
if
(
a
[
e4
]
<
a
[
e3
])
{
int
t
=
a
[
e4
];
a
[
e4
]
=
a
[
e3
];
a
[
e3
]
=
t
;
if
(
ae1
>
ae4
)
{
int
t
=
ae1
;
ae1
=
ae4
;
ae4
=
t
;
}
if
(
t
<
a
[
e2
])
{
a
[
e3
]
=
a
[
e2
];
a
[
e2
]
=
t
;
if
(
ae3
>
ae4
)
{
int
t
=
ae3
;
ae3
=
ae4
;
ae4
=
t
;
}
if
(
t
<
a
[
e1
])
{
a
[
e2
]
=
a
[
e1
];
a
[
e1
]
=
t
;
}
if
(
ae2
>
ae5
)
{
int
t
=
ae2
;
ae2
=
ae5
;
ae5
=
t
;
}
}
if
(
ae2
>
ae3
)
{
int
t
=
ae2
;
ae2
=
ae3
;
ae3
=
t
;
}
}
if
(
ae4
>
ae5
)
{
int
t
=
ae4
;
ae4
=
ae5
;
ae5
=
t
;
}
if
(
a
[
e5
]
<
a
[
e4
])
{
int
t
=
a
[
e5
];
a
[
e5
]
=
a
[
e4
];
a
[
e4
]
=
t
;
if
(
t
<
a
[
e3
])
{
a
[
e4
]
=
a
[
e3
];
a
[
e3
]
=
t
;
a
[
e1
]
=
ae1
;
a
[
e3
]
=
ae3
;
a
[
e5
]
=
ae5
;
if
(
t
<
a
[
e2
])
{
a
[
e3
]
=
a
[
e2
];
a
[
e2
]
=
t
;
if
(
t
<
a
[
e1
])
{
a
[
e2
]
=
a
[
e1
];
a
[
e1
]
=
t
;
}
}
}
}
/*
/*
* Use the second and fourth of the five sorted elements as pivots.
* Use the second and fourth of the five sorted elements as pivots.
* These values are inexpensive approximations of the first and
* These values are inexpensive approximations of the first and
* second terciles of the array. Note that pivot1 <= pivot2.
* second terciles of the array. Note that pivot1 <= pivot2.
*
* The pivots are stored in local variables, and the first and
* the last of the elements to be sorted are moved to the locations
* formerly occupied by the pivots. When partitioning is complete,
* the pivots are swapped back into their final positions, and
* excluded from subsequent sorting.
*/
*/
int
pivot1
=
a
e2
;
a
[
e2
]
=
a
[
left
];
int
pivot1
=
a
[
e2
];
int
pivot2
=
a
e4
;
a
[
e4
]
=
a
[
right
];
int
pivot2
=
a
[
e4
];
// Pointers
// Pointers
int
less
=
left
+
1
;
// The index of
first element of center part
int
less
=
left
;
// The index of the
first element of center part
int
great
=
right
-
1
;
// The index befor
e first element of right part
int
great
=
right
;
// The index before th
e first element of right part
boolean
pivotsDiffer
=
(
pivot1
!=
pivot2
);
if
(
pivot1
!=
pivot2
)
{
/*
* The first and the last elements to be sorted are moved to the
* locations formerly occupied by the pivots. When partitioning
* is complete, the pivots are swapped back into their final
* positions, and excluded from subsequent sorting.
*/
a
[
e2
]
=
a
[
left
];
a
[
e4
]
=
a
[
right
];
/*
* Skip elements, which are less or greater than pivot values.
*/
while
(
a
[++
less
]
<
pivot1
);
while
(
a
[--
great
]
>
pivot2
);
if
(
pivotsDiffer
)
{
/*
/*
* Partitioning:
* Partitioning:
*
*
* left part center part right part
* left part center part right part
* +------------------------------------------------------------+
* +------------------------------------------------------------
--
+
* | < pivot1 | pivot1 <= && <= pivot2 | ? | > pivot2 |
* | < pivot1 | pivot1 <= && <= pivot2 | ? | > pivot2 |
* +------------------------------------------------------------+
* +------------------------------------------------------------
--
+
* ^ ^ ^
* ^ ^ ^
* | | |
* | | |
* less k great
* less k great
...
@@ -194,16 +229,14 @@ final class DualPivotQuicksort {
...
@@ -194,16 +229,14 @@ final class DualPivotQuicksort {
* pivot1 <= all in [less, k) <= pivot2
* pivot1 <= all in [less, k) <= pivot2
* all in (great, right) > pivot2
* all in (great, right) > pivot2
*
*
* Pointer k is the first index of ?-part
* Pointer k is the first index of ?-part
.
*/
*/
outer:
outer:
for
(
int
k
=
less
;
k
<=
great
;
k
++)
{
for
(
int
k
=
less
;
k
<=
great
;
k
++)
{
int
ak
=
a
[
k
];
int
ak
=
a
[
k
];
if
(
ak
<
pivot1
)
{
// Move a[k] to left part
if
(
ak
<
pivot1
)
{
// Move a[k] to left part
if
(
k
!=
less
)
{
a
[
k
]
=
a
[
less
];
a
[
k
]
=
a
[
less
];
a
[
less
]
=
ak
;
a
[
less
]
=
ak
;
}
less
++;
less
++;
}
else
if
(
ak
>
pivot2
)
{
// Move a[k] to right part
}
else
if
(
ak
>
pivot2
)
{
// Move a[k] to right part
while
(
a
[
great
]
>
pivot2
)
{
while
(
a
[
great
]
>
pivot2
)
{
...
@@ -213,89 +246,32 @@ final class DualPivotQuicksort {
...
@@ -213,89 +246,32 @@ final class DualPivotQuicksort {
}
}
if
(
a
[
great
]
<
pivot1
)
{
if
(
a
[
great
]
<
pivot1
)
{
a
[
k
]
=
a
[
less
];
a
[
k
]
=
a
[
less
];
a
[
less
++
]
=
a
[
great
];
a
[
less
]
=
a
[
great
];
a
[
great
--]
=
ak
;
less
++
;
}
else
{
// pivot1 <= a[great] <= pivot2
}
else
{
// pivot1 <= a[great] <= pivot2
a
[
k
]
=
a
[
great
];
a
[
k
]
=
a
[
great
];
a
[
great
--]
=
ak
;
}
}
}
}
else
{
// Pivots are equal
/*
* Partition degenerates to the traditional 3-way,
* or "Dutch National Flag", partition:
*
* left part center part right part
* +----------------------------------------------+
* | < pivot | == pivot | ? | > pivot |
* +----------------------------------------------+
* ^ ^ ^
* | | |
* less k great
*
* Invariants:
*
* all in (left, less) < pivot
* all in [less, k) == pivot
* all in (great, right) > pivot
*
* Pointer k is the first index of ?-part
*/
for
(
int
k
=
less
;
k
<=
great
;
k
++)
{
int
ak
=
a
[
k
];
if
(
ak
==
pivot1
)
{
continue
;
}
if
(
ak
<
pivot1
)
{
// Move a[k] to left part
if
(
k
!=
less
)
{
a
[
k
]
=
a
[
less
];
a
[
less
]
=
ak
;
}
}
less
++;
a
[
great
]
=
ak
;
}
else
{
// (a[k] > pivot1) - Move a[k] to right part
/*
* We know that pivot1 == a[e3] == pivot2. Thus, we know
* that great will still be >= k when the following loop
* terminates, even though we don't test for it explicitly.
* In other words, a[e3] acts as a sentinel for great.
*/
while
(
a
[
great
]
>
pivot1
)
{
great
--;
great
--;
}
}
if
(
a
[
great
]
<
pivot1
)
{
a
[
k
]
=
a
[
less
];
a
[
less
++]
=
a
[
great
];
a
[
great
--]
=
ak
;
}
else
{
// a[great] == pivot1
a
[
k
]
=
pivot1
;
a
[
great
--]
=
ak
;
}
}
}
}
}
// Swap pivots into their final positions
// Swap pivots into their final positions
a
[
left
]
=
a
[
less
-
1
];
a
[
less
-
1
]
=
pivot1
;
a
[
left
]
=
a
[
less
-
1
];
a
[
less
-
1
]
=
pivot1
;
a
[
right
]
=
a
[
great
+
1
];
a
[
great
+
1
]
=
pivot2
;
a
[
right
]
=
a
[
great
+
1
];
a
[
great
+
1
]
=
pivot2
;
// Sort left and right parts recursively, excluding known pivot value
s
// Sort left and right parts recursively, excluding known pivot
s
doSort
(
a
,
left
,
less
-
2
);
sort
(
a
,
left
,
less
-
2
,
leftmost
);
doSort
(
a
,
great
+
2
,
right
);
sort
(
a
,
great
+
2
,
right
,
false
);
/*
/*
* If pivot1 == pivot2, all elements from center
* If center part is too large (comprises > 5/7 of the array),
* part are equal and, therefore, already sorted
* swap internal pivot values to ends.
*/
*/
if
(!
pivotsDiffer
)
{
if
(
less
<
e1
&&
e5
<
great
)
{
return
;
}
/*
/*
* If center part is too large (comprises > 2/3 of the array),
* Skip elements, which are equal to pivot values.
* swap internal pivot values to ends
*/
*/
if
(
less
<
e1
&&
great
>
e5
)
{
while
(
a
[
less
]
==
pivot1
)
{
while
(
a
[
less
]
==
pivot1
)
{
less
++;
less
++;
}
}
...
@@ -320,12 +296,16 @@ final class DualPivotQuicksort {
...
@@ -320,12 +296,16 @@ final class DualPivotQuicksort {
* pivot1 < all in [less, k) < pivot2
* pivot1 < all in [less, k) < pivot2
* all in (great, *) == pivot2
* all in (great, *) == pivot2
*
*
* Pointer k is the first index of ?-part
* Pointer k is the first index of ?-part.
*/
*/
outer:
outer:
for
(
int
k
=
less
;
k
<=
great
;
k
++)
{
for
(
int
k
=
less
;
k
<=
great
;
k
++)
{
int
ak
=
a
[
k
];
int
ak
=
a
[
k
];
if
(
ak
==
pivot2
)
{
// Move a[k] to right part
if
(
ak
==
pivot1
)
{
// Move a[k] to left part
a
[
k
]
=
a
[
less
];
a
[
less
]
=
ak
;
less
++;
}
else
if
(
ak
==
pivot2
)
{
// Move a[k] to right part
while
(
a
[
great
]
==
pivot2
)
{
while
(
a
[
great
]
==
pivot2
)
{
if
(
great
--
==
k
)
{
if
(
great
--
==
k
)
{
break
outer
;
break
outer
;
...
@@ -333,20 +313,94 @@ final class DualPivotQuicksort {
...
@@ -333,20 +313,94 @@ final class DualPivotQuicksort {
}
}
if
(
a
[
great
]
==
pivot1
)
{
if
(
a
[
great
]
==
pivot1
)
{
a
[
k
]
=
a
[
less
];
a
[
k
]
=
a
[
less
];
a
[
less
++]
=
pivot1
;
/*
* Even though a[great] equals to pivot1, the
* assignment a[less] = pivot1 may be incorrect,
* if a[great] and pivot1 are floating-point zeros
* of different signs. Therefore in float and
* double sorting methods we have to use more
* accurate assignment a[less] = a[great].
*/
a
[
less
]
=
pivot1
;
less
++;
}
else
{
// pivot1 < a[great] < pivot2
}
else
{
// pivot1 < a[great] < pivot2
a
[
k
]
=
a
[
great
];
a
[
k
]
=
a
[
great
];
}
}
a
[
great
--]
=
pivot2
;
a
[
great
]
=
ak
;
}
else
if
(
ak
==
pivot1
)
{
// Move a[k] to left part
great
--;
}
}
}
// Sort center part recursively
sort
(
a
,
less
,
great
,
false
);
}
else
{
// Pivots are equal
/*
* Partition degenerates to the traditional 3-way
* (or "Dutch National Flag") schema:
*
* left part center part right part
* +-------------------------------------------------+
* | < pivot | == pivot | ? | > pivot |
* +-------------------------------------------------+
* ^ ^ ^
* | | |
* less k great
*
* Invariants:
*
* all in (left, less) < pivot
* all in [less, k) == pivot
* all in (great, right) > pivot
*
* Pointer k is the first index of ?-part.
*/
for
(
int
k
=
left
;
k
<=
great
;
k
++)
{
if
(
a
[
k
]
==
pivot1
)
{
continue
;
}
int
ak
=
a
[
k
];
if
(
ak
<
pivot1
)
{
// Move a[k] to left part
a
[
k
]
=
a
[
less
];
a
[
less
]
=
ak
;
less
++;
}
else
{
// a[k] > pivot1 - Move a[k] to right part
/*
* We know that pivot1 == a[e3] == pivot2. Thus, we know
* that great will still be >= k when the following loop
* terminates, even though we don't test for it explicitly.
* In other words, a[e3] acts as a sentinel for great.
*/
while
(
a
[
great
]
>
pivot1
)
{
// assert great > k;
great
--;
}
if
(
a
[
great
]
<
pivot1
)
{
a
[
k
]
=
a
[
less
];
a
[
k
]
=
a
[
less
];
a
[
less
++]
=
pivot1
;
a
[
less
]
=
a
[
great
];
less
++;
}
else
{
// a[great] == pivot1
/*
* Even though a[great] equals to pivot1, the
* assignment a[k] = pivot1 may be incorrect,
* if a[great] and pivot1 are floating-point
* zeros of different signs. Therefore in float
* and double sorting methods we have to use
* more accurate assignment a[k] = a[great].
*/
a
[
k
]
=
pivot1
;
}
}
a
[
great
]
=
ak
;
great
--;
}
}
}
}
// Sort center part recursively, excluding known pivot values
// Sort left and right parts recursively
doSort
(
a
,
less
,
great
);
sort
(
a
,
left
,
less
-
1
,
leftmost
);
sort
(
a
,
great
+
1
,
right
,
false
);
}
}
}
/**
/**
...
@@ -355,7 +409,7 @@ final class DualPivotQuicksort {
...
@@ -355,7 +409,7 @@ final class DualPivotQuicksort {
* @param a the array to be sorted
* @param a the array to be sorted
*/
*/
public
static
void
sort
(
long
[]
a
)
{
public
static
void
sort
(
long
[]
a
)
{
doSort
(
a
,
0
,
a
.
length
-
1
);
sort
(
a
,
0
,
a
.
length
-
1
,
true
);
}
}
/**
/**
...
@@ -373,95 +427,129 @@ final class DualPivotQuicksort {
...
@@ -373,95 +427,129 @@ final class DualPivotQuicksort {
*/
*/
public
static
void
sort
(
long
[]
a
,
int
fromIndex
,
int
toIndex
)
{
public
static
void
sort
(
long
[]
a
,
int
fromIndex
,
int
toIndex
)
{
rangeCheck
(
a
.
length
,
fromIndex
,
toIndex
);
rangeCheck
(
a
.
length
,
fromIndex
,
toIndex
);
doSort
(
a
,
fromIndex
,
toIndex
-
1
);
sort
(
a
,
fromIndex
,
toIndex
-
1
,
true
);
}
}
/**
/**
* Sorts the specified range of the array into ascending order. This
* Sorts the specified range of the array into ascending order by the
* method differs from the public {@code sort} method in that the
* Dual-Pivot Quicksort algorithm. This method differs from the public
* {@code right} index is inclusive, and it does no range checking on
* {@code sort} method in that the {@code right} index is inclusive,
* {@code left} or {@code right}.
* it does no range checking on {@code left} or {@code right}, and has
* boolean flag whether insertion sort with sentinel is used or not.
*
*
* @param a the array to be sorted
* @param a the array to be sorted
* @param left the index of the first element, inclusive, to be sorted
* @param left the index of the first element, inclusive, to be sorted
* @param right the index of the last element, inclusive, to be sorted
* @param right the index of the last element, inclusive, to be sorted
* @param leftmost indicates if the part is the most left in the range
*/
*/
private
static
void
doSort
(
long
[]
a
,
int
left
,
int
right
)
{
private
static
void
sort
(
long
[]
a
,
int
left
,
int
right
,
boolean
leftmost
)
{
int
length
=
right
-
left
+
1
;
// Use insertion sort on tiny arrays
// Use insertion sort on tiny arrays
if
(
right
-
left
+
1
<
INSERTION_SORT_THRESHOLD
)
{
if
(
length
<
INSERTION_SORT_THRESHOLD
)
{
for
(
int
i
=
left
+
1
;
i
<=
right
;
i
++)
{
if
(!
leftmost
)
{
/*
* Every element in adjoining part plays the role
* of sentinel, therefore this allows us to avoid
* the j >= left check on each iteration.
*/
for
(
int
j
,
i
=
left
+
1
;
i
<=
right
;
i
++)
{
long
ai
=
a
[
i
];
long
ai
=
a
[
i
];
int
j
;
for
(
j
=
i
-
1
;
ai
<
a
[
j
];
j
--)
{
for
(
j
=
i
-
1
;
j
>=
left
&&
ai
<
a
[
j
];
j
--)
{
// assert j >= left;
a
[
j
+
1
]
=
a
[
j
];
}
a
[
j
+
1
]
=
ai
;
}
}
else
{
/*
* For case of leftmost part traditional (without a sentinel)
* insertion sort, optimized for server JVM, is used.
*/
for
(
int
i
=
left
,
j
=
i
;
i
<
right
;
j
=
++
i
)
{
long
ai
=
a
[
i
+
1
];
while
(
ai
<
a
[
j
])
{
a
[
j
+
1
]
=
a
[
j
];
a
[
j
+
1
]
=
a
[
j
];
if
(
j
--
==
left
)
{
break
;
}
}
}
a
[
j
+
1
]
=
ai
;
a
[
j
+
1
]
=
ai
;
}
}
}
else
{
// Use Dual-Pivot Quicksort on large arrays
dualPivotQuicksort
(
a
,
left
,
right
);
}
}
return
;
}
}
/**
// Inexpensive approximation of length / 7
* Sorts the specified range of the array into ascending order by the
int
seventh
=
(
length
>>>
3
)
+
(
length
>>>
6
)
+
1
;
* Dual-Pivot Quicksort algorithm.
*
/*
* @param a the array to be sorted
* Sort five evenly spaced elements around (and including) the
* @param left the index of the first element, inclusive, to be sorted
* center element in the range. These elements will be used for
* @param right the index of the last element, inclusive, to be sorted
* pivot selection as described below. The choice for spacing
* these elements was empirically determined to work well on
* a wide variety of inputs.
*/
*/
private
static
void
dualPivotQuicksort
(
long
[]
a
,
int
left
,
int
right
)
{
// Compute indices of five evenly spaced elements
int
sixth
=
(
right
-
left
+
1
)
/
6
;
int
e1
=
left
+
sixth
;
int
e5
=
right
-
sixth
;
int
e3
=
(
left
+
right
)
>>>
1
;
// The midpoint
int
e3
=
(
left
+
right
)
>>>
1
;
// The midpoint
int
e4
=
e3
+
sixth
;
int
e2
=
e3
-
seventh
;
int
e2
=
e3
-
sixth
;
int
e1
=
e2
-
seventh
;
int
e4
=
e3
+
seventh
;
// Sort these elements using a 5-element sorting network
int
e5
=
e4
+
seventh
;
long
ae1
=
a
[
e1
],
ae2
=
a
[
e2
],
ae3
=
a
[
e3
],
ae4
=
a
[
e4
],
ae5
=
a
[
e5
];
if
(
ae1
>
ae2
)
{
long
t
=
ae1
;
ae1
=
ae2
;
ae2
=
t
;
}
// Sort these elements using insertion sort
if
(
ae4
>
ae5
)
{
long
t
=
ae4
;
ae4
=
ae5
;
ae5
=
t
;
}
if
(
a
[
e2
]
<
a
[
e1
])
{
long
t
=
a
[
e2
];
a
[
e2
]
=
a
[
e1
];
a
[
e1
]
=
t
;
}
if
(
ae1
>
ae3
)
{
long
t
=
ae1
;
ae1
=
ae3
;
ae3
=
t
;
}
if
(
ae2
>
ae3
)
{
long
t
=
ae2
;
ae2
=
ae3
;
ae3
=
t
;
}
if
(
ae1
>
ae4
)
{
long
t
=
ae1
;
ae1
=
ae4
;
ae4
=
t
;
}
if
(
ae3
>
ae4
)
{
long
t
=
ae3
;
ae3
=
ae4
;
ae4
=
t
;
}
if
(
ae2
>
ae5
)
{
long
t
=
ae2
;
ae2
=
ae5
;
ae5
=
t
;
}
if
(
ae2
>
ae3
)
{
long
t
=
ae2
;
ae2
=
ae3
;
ae3
=
t
;
}
if
(
ae4
>
ae5
)
{
long
t
=
ae4
;
ae4
=
ae5
;
ae5
=
t
;
}
a
[
e1
]
=
ae1
;
a
[
e3
]
=
ae3
;
a
[
e5
]
=
ae5
;
if
(
a
[
e3
]
<
a
[
e2
])
{
long
t
=
a
[
e3
];
a
[
e3
]
=
a
[
e2
];
a
[
e2
]
=
t
;
if
(
t
<
a
[
e1
])
{
a
[
e2
]
=
a
[
e1
];
a
[
e1
]
=
t
;
}
}
if
(
a
[
e4
]
<
a
[
e3
])
{
long
t
=
a
[
e4
];
a
[
e4
]
=
a
[
e3
];
a
[
e3
]
=
t
;
if
(
t
<
a
[
e2
])
{
a
[
e3
]
=
a
[
e2
];
a
[
e2
]
=
t
;
if
(
t
<
a
[
e1
])
{
a
[
e2
]
=
a
[
e1
];
a
[
e1
]
=
t
;
}
}
}
if
(
a
[
e5
]
<
a
[
e4
])
{
long
t
=
a
[
e5
];
a
[
e5
]
=
a
[
e4
];
a
[
e4
]
=
t
;
if
(
t
<
a
[
e3
])
{
a
[
e4
]
=
a
[
e3
];
a
[
e3
]
=
t
;
if
(
t
<
a
[
e2
])
{
a
[
e3
]
=
a
[
e2
];
a
[
e2
]
=
t
;
if
(
t
<
a
[
e1
])
{
a
[
e2
]
=
a
[
e1
];
a
[
e1
]
=
t
;
}
}
}
}
/*
/*
* Use the second and fourth of the five sorted elements as pivots.
* Use the second and fourth of the five sorted elements as pivots.
* These values are inexpensive approximations of the first and
* These values are inexpensive approximations of the first and
* second terciles of the array. Note that pivot1 <= pivot2.
* second terciles of the array. Note that pivot1 <= pivot2.
*
* The pivots are stored in local variables, and the first and
* the last of the elements to be sorted are moved to the locations
* formerly occupied by the pivots. When partitioning is complete,
* the pivots are swapped back into their final positions, and
* excluded from subsequent sorting.
*/
*/
long
pivot1
=
a
e2
;
a
[
e2
]
=
a
[
left
];
long
pivot1
=
a
[
e2
];
long
pivot2
=
a
e4
;
a
[
e4
]
=
a
[
right
];
long
pivot2
=
a
[
e4
];
// Pointers
// Pointers
int
less
=
left
+
1
;
// The index of first element of center part
int
less
=
left
;
// The index of the first element of center part
int
great
=
right
-
1
;
// The index before first element of right part
int
great
=
right
;
// The index before the first element of right part
if
(
pivot1
!=
pivot2
)
{
/*
* The first and the last elements to be sorted are moved to the
* locations formerly occupied by the pivots. When partitioning
* is complete, the pivots are swapped back into their final
* positions, and excluded from subsequent sorting.
*/
a
[
e2
]
=
a
[
left
];
a
[
e4
]
=
a
[
right
];
boolean
pivotsDiffer
=
(
pivot1
!=
pivot2
);
/*
* Skip elements, which are less or greater than pivot values.
*/
while
(
a
[++
less
]
<
pivot1
);
while
(
a
[--
great
]
>
pivot2
);
if
(
pivotsDiffer
)
{
/*
/*
* Partitioning:
* Partitioning:
*
*
* left part center part right part
* left part center part right part
* +------------------------------------------------------------+
* +------------------------------------------------------------
--
+
* | < pivot1 | pivot1 <= && <= pivot2 | ? | > pivot2 |
* | < pivot1 | pivot1 <= && <= pivot2 | ? | > pivot2 |
* +------------------------------------------------------------+
* +------------------------------------------------------------
--
+
* ^ ^ ^
* ^ ^ ^
* | | |
* | | |
* less k great
* less k great
...
@@ -472,16 +560,14 @@ final class DualPivotQuicksort {
...
@@ -472,16 +560,14 @@ final class DualPivotQuicksort {
* pivot1 <= all in [less, k) <= pivot2
* pivot1 <= all in [less, k) <= pivot2
* all in (great, right) > pivot2
* all in (great, right) > pivot2
*
*
* Pointer k is the first index of ?-part
* Pointer k is the first index of ?-part
.
*/
*/
outer:
outer:
for
(
int
k
=
less
;
k
<=
great
;
k
++)
{
for
(
int
k
=
less
;
k
<=
great
;
k
++)
{
long
ak
=
a
[
k
];
long
ak
=
a
[
k
];
if
(
ak
<
pivot1
)
{
// Move a[k] to left part
if
(
ak
<
pivot1
)
{
// Move a[k] to left part
if
(
k
!=
less
)
{
a
[
k
]
=
a
[
less
];
a
[
k
]
=
a
[
less
];
a
[
less
]
=
ak
;
a
[
less
]
=
ak
;
}
less
++;
less
++;
}
else
if
(
ak
>
pivot2
)
{
// Move a[k] to right part
}
else
if
(
ak
>
pivot2
)
{
// Move a[k] to right part
while
(
a
[
great
]
>
pivot2
)
{
while
(
a
[
great
]
>
pivot2
)
{
...
@@ -491,89 +577,32 @@ final class DualPivotQuicksort {
...
@@ -491,89 +577,32 @@ final class DualPivotQuicksort {
}
}
if
(
a
[
great
]
<
pivot1
)
{
if
(
a
[
great
]
<
pivot1
)
{
a
[
k
]
=
a
[
less
];
a
[
k
]
=
a
[
less
];
a
[
less
++
]
=
a
[
great
];
a
[
less
]
=
a
[
great
];
a
[
great
--]
=
ak
;
less
++
;
}
else
{
// pivot1 <= a[great] <= pivot2
}
else
{
// pivot1 <= a[great] <= pivot2
a
[
k
]
=
a
[
great
];
a
[
k
]
=
a
[
great
];
a
[
great
--]
=
ak
;
}
}
}
}
else
{
// Pivots are equal
/*
* Partition degenerates to the traditional 3-way,
* or "Dutch National Flag", partition:
*
* left part center part right part
* +----------------------------------------------+
* | < pivot | == pivot | ? | > pivot |
* +----------------------------------------------+
* ^ ^ ^
* | | |
* less k great
*
* Invariants:
*
* all in (left, less) < pivot
* all in [less, k) == pivot
* all in (great, right) > pivot
*
* Pointer k is the first index of ?-part
*/
for
(
int
k
=
less
;
k
<=
great
;
k
++)
{
long
ak
=
a
[
k
];
if
(
ak
==
pivot1
)
{
continue
;
}
if
(
ak
<
pivot1
)
{
// Move a[k] to left part
if
(
k
!=
less
)
{
a
[
k
]
=
a
[
less
];
a
[
less
]
=
ak
;
}
}
less
++;
a
[
great
]
=
ak
;
}
else
{
// (a[k] > pivot1) - Move a[k] to right part
/*
* We know that pivot1 == a[e3] == pivot2. Thus, we know
* that great will still be >= k when the following loop
* terminates, even though we don't test for it explicitly.
* In other words, a[e3] acts as a sentinel for great.
*/
while
(
a
[
great
]
>
pivot1
)
{
great
--;
great
--;
}
}
if
(
a
[
great
]
<
pivot1
)
{
a
[
k
]
=
a
[
less
];
a
[
less
++]
=
a
[
great
];
a
[
great
--]
=
ak
;
}
else
{
// a[great] == pivot1
a
[
k
]
=
pivot1
;
a
[
great
--]
=
ak
;
}
}
}
}
}
// Swap pivots into their final positions
// Swap pivots into their final positions
a
[
left
]
=
a
[
less
-
1
];
a
[
less
-
1
]
=
pivot1
;
a
[
left
]
=
a
[
less
-
1
];
a
[
less
-
1
]
=
pivot1
;
a
[
right
]
=
a
[
great
+
1
];
a
[
great
+
1
]
=
pivot2
;
a
[
right
]
=
a
[
great
+
1
];
a
[
great
+
1
]
=
pivot2
;
// Sort left and right parts recursively, excluding known pivot value
s
// Sort left and right parts recursively, excluding known pivot
s
doSort
(
a
,
left
,
less
-
2
);
sort
(
a
,
left
,
less
-
2
,
leftmost
);
doSort
(
a
,
great
+
2
,
right
);
sort
(
a
,
great
+
2
,
right
,
false
);
/*
/*
* If pivot1 == pivot2, all elements from center
* If center part is too large (comprises > 5/7 of the array),
* part are equal and, therefore, already sorted
* swap internal pivot values to ends.
*/
*/
if
(!
pivotsDiffer
)
{
if
(
less
<
e1
&&
e5
<
great
)
{
return
;
}
/*
/*
* If center part is too large (comprises > 2/3 of the array),
* Skip elements, which are equal to pivot values.
* swap internal pivot values to ends
*/
*/
if
(
less
<
e1
&&
great
>
e5
)
{
while
(
a
[
less
]
==
pivot1
)
{
while
(
a
[
less
]
==
pivot1
)
{
less
++;
less
++;
}
}
...
@@ -598,12 +627,16 @@ final class DualPivotQuicksort {
...
@@ -598,12 +627,16 @@ final class DualPivotQuicksort {
* pivot1 < all in [less, k) < pivot2
* pivot1 < all in [less, k) < pivot2
* all in (great, *) == pivot2
* all in (great, *) == pivot2
*
*
* Pointer k is the first index of ?-part
* Pointer k is the first index of ?-part.
*/
*/
outer:
outer:
for
(
int
k
=
less
;
k
<=
great
;
k
++)
{
for
(
int
k
=
less
;
k
<=
great
;
k
++)
{
long
ak
=
a
[
k
];
long
ak
=
a
[
k
];
if
(
ak
==
pivot2
)
{
// Move a[k] to right part
if
(
ak
==
pivot1
)
{
// Move a[k] to left part
a
[
k
]
=
a
[
less
];
a
[
less
]
=
ak
;
less
++;
}
else
if
(
ak
==
pivot2
)
{
// Move a[k] to right part
while
(
a
[
great
]
==
pivot2
)
{
while
(
a
[
great
]
==
pivot2
)
{
if
(
great
--
==
k
)
{
if
(
great
--
==
k
)
{
break
outer
;
break
outer
;
...
@@ -611,152 +644,281 @@ final class DualPivotQuicksort {
...
@@ -611,152 +644,281 @@ final class DualPivotQuicksort {
}
}
if
(
a
[
great
]
==
pivot1
)
{
if
(
a
[
great
]
==
pivot1
)
{
a
[
k
]
=
a
[
less
];
a
[
k
]
=
a
[
less
];
a
[
less
++]
=
pivot1
;
/*
* Even though a[great] equals to pivot1, the
* assignment a[less] = pivot1 may be incorrect,
* if a[great] and pivot1 are floating-point zeros
* of different signs. Therefore in float and
* double sorting methods we have to use more
* accurate assignment a[less] = a[great].
*/
a
[
less
]
=
pivot1
;
less
++;
}
else
{
// pivot1 < a[great] < pivot2
}
else
{
// pivot1 < a[great] < pivot2
a
[
k
]
=
a
[
great
];
a
[
k
]
=
a
[
great
];
}
}
a
[
great
--]
=
pivot2
;
a
[
great
]
=
ak
;
}
else
if
(
ak
==
pivot1
)
{
// Move a[k] to left part
great
--;
a
[
k
]
=
a
[
less
];
a
[
less
++]
=
pivot1
;
}
}
}
}
}
}
// Sort center part recursively, excluding known pivot values
// Sort center part recursively
doSort
(
a
,
less
,
great
);
sort
(
a
,
less
,
great
,
false
);
}
/**
}
else
{
// Pivots are equal
* Sorts the specified array into ascending numerical order.
/*
* Partition degenerates to the traditional 3-way
* (or "Dutch National Flag") schema:
*
*
* @param a the array to be sorted
* left part center part right part
*/
* +-------------------------------------------------+
public
static
void
sort
(
short
[]
a
)
{
* | < pivot | == pivot | ? | > pivot |
doSort
(
a
,
0
,
a
.
length
-
1
);
* +-------------------------------------------------+
}
* ^ ^ ^
* | | |
/**
* less k great
* Sorts the specified range of the array into ascending order. The range
* to be sorted extends from the index {@code fromIndex}, inclusive, to
* the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
* the range to be sorted is empty (and the call is a no-op).
*
*
* @param a the array to be sorted
* Invariants:
* @param fromIndex the index of the first element, inclusive, to be sorted
*
* @param toIndex the index of the last element, exclusive, to be sorted
* all in (left, less) < pivot
* @throws IllegalArgumentException if {@code fromIndex > toIndex}
* all in [less, k) == pivot
* @throws ArrayIndexOutOfBoundsException
* all in (great, right) > pivot
* if {@code fromIndex < 0} or {@code toIndex > a.length}
*
* Pointer k is the first index of ?-part.
*/
*/
public
static
void
sort
(
short
[]
a
,
int
fromIndex
,
int
toIndex
)
{
for
(
int
k
=
left
;
k
<=
great
;
k
++)
{
rangeCheck
(
a
.
length
,
fromIndex
,
toIndex
);
if
(
a
[
k
]
==
pivot1
)
{
doSort
(
a
,
fromIndex
,
toIndex
-
1
);
continue
;
}
long
ak
=
a
[
k
];
if
(
ak
<
pivot1
)
{
// Move a[k] to left part
a
[
k
]
=
a
[
less
];
a
[
less
]
=
ak
;
less
++;
}
else
{
// a[k] > pivot1 - Move a[k] to right part
/*
* We know that pivot1 == a[e3] == pivot2. Thus, we know
* that great will still be >= k when the following loop
* terminates, even though we don't test for it explicitly.
* In other words, a[e3] acts as a sentinel for great.
*/
while
(
a
[
great
]
>
pivot1
)
{
// assert great > k;
great
--;
}
if
(
a
[
great
]
<
pivot1
)
{
a
[
k
]
=
a
[
less
];
a
[
less
]
=
a
[
great
];
less
++;
}
else
{
// a[great] == pivot1
/*
* Even though a[great] equals to pivot1, the
* assignment a[k] = pivot1 may be incorrect,
* if a[great] and pivot1 are floating-point
* zeros of different signs. Therefore in float
* and double sorting methods we have to use
* more accurate assignment a[k] = a[great].
*/
a
[
k
]
=
pivot1
;
}
a
[
great
]
=
ak
;
great
--;
}
}
// Sort left and right parts recursively
sort
(
a
,
left
,
less
-
1
,
leftmost
);
sort
(
a
,
great
+
1
,
right
,
false
);
}
}
}
/** The number of distinct short values. */
private
static
final
int
NUM_SHORT_VALUES
=
1
<<
16
;
/**
/**
* Sorts the specified range of the array into ascending order. This
* Sorts the specified array into ascending numerical order.
* method differs from the public {@code sort} method in that the
* {@code right} index is inclusive, and it does no range checking on
* {@code left} or {@code right}.
*
*
* @param a the array to be sorted
* @param a the array to be sorted
* @param left the index of the first element, inclusive, to be sorted
* @param right the index of the last element, inclusive, to be sorted
*/
*/
private
static
void
doSort
(
short
[]
a
,
int
left
,
int
right
)
{
public
static
void
sort
(
short
[]
a
)
{
// Use insertion sort on tiny arrays
if
(
a
.
length
>
COUNTING_SORT_THRESHOLD_FOR_SHORT_OR_CHAR
)
{
if
(
right
-
left
+
1
<
INSERTION_SORT_THRESHOLD
)
{
countingSort
(
a
,
0
,
a
.
length
-
1
);
for
(
int
i
=
left
+
1
;
i
<=
right
;
i
++)
{
}
else
{
short
ai
=
a
[
i
];
sort
(
a
,
0
,
a
.
length
-
1
,
true
);
int
j
;
for
(
j
=
i
-
1
;
j
>=
left
&&
ai
<
a
[
j
];
j
--)
{
a
[
j
+
1
]
=
a
[
j
];
}
}
a
[
j
+
1
]
=
ai
;
}
}
}
else
if
(
right
-
left
+
1
>
COUNTING_SORT_THRESHOLD_FOR_SHORT_OR_CHAR
)
{
// Use counting sort on huge arrays
/**
* Sorts the specified range of the array into ascending order. The range
* to be sorted extends from the index {@code fromIndex}, inclusive, to
* the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
* the range to be sorted is empty (and the call is a no-op).
*
* @param a the array to be sorted
* @param fromIndex the index of the first element, inclusive, to be sorted
* @param toIndex the index of the last element, exclusive, to be sorted
* @throws IllegalArgumentException if {@code fromIndex > toIndex}
* @throws ArrayIndexOutOfBoundsException
* if {@code fromIndex < 0} or {@code toIndex > a.length}
*/
public
static
void
sort
(
short
[]
a
,
int
fromIndex
,
int
toIndex
)
{
rangeCheck
(
a
.
length
,
fromIndex
,
toIndex
);
if
(
toIndex
-
fromIndex
>
COUNTING_SORT_THRESHOLD_FOR_SHORT_OR_CHAR
)
{
countingSort
(
a
,
fromIndex
,
toIndex
-
1
);
}
else
{
sort
(
a
,
fromIndex
,
toIndex
-
1
,
true
);
}
}
/** The number of distinct short values. */
private
static
final
int
NUM_SHORT_VALUES
=
1
<<
16
;
/**
* Sorts the specified range of the array by counting sort.
*
* @param a the array to be sorted
* @param left the index of the first element, inclusive, to be sorted
* @param right the index of the last element, inclusive, to be sorted
*/
private
static
void
countingSort
(
short
[]
a
,
int
left
,
int
right
)
{
int
[]
count
=
new
int
[
NUM_SHORT_VALUES
];
int
[]
count
=
new
int
[
NUM_SHORT_VALUES
];
for
(
int
i
=
left
;
i
<=
right
;
i
++)
{
for
(
int
i
=
left
;
i
<=
right
;
i
++)
{
count
[
a
[
i
]
-
Short
.
MIN_VALUE
]++;
count
[
a
[
i
]
-
Short
.
MIN_VALUE
]++;
}
}
for
(
int
i
=
0
,
k
=
left
;
i
<
count
.
length
&&
k
<=
right
;
i
++)
{
for
(
int
i
=
NUM_SHORT_VALUES
-
1
,
k
=
right
;
k
>=
left
;
i
--)
{
while
(
count
[
i
]
==
0
)
{
i
--;
}
short
value
=
(
short
)
(
i
+
Short
.
MIN_VALUE
);
short
value
=
(
short
)
(
i
+
Short
.
MIN_VALUE
);
int
s
=
count
[
i
];
for
(
int
s
=
count
[
i
];
s
>
0
;
s
--)
{
do
{
a
[
k
++]
=
value
;
a
[
k
--]
=
value
;
}
}
while
(--
s
>
0
);
}
}
else
{
// Use Dual-Pivot Quicksort on large arrays
dualPivotQuicksort
(
a
,
left
,
right
);
}
}
}
}
/**
/**
* Sorts the specified range of the array into ascending order by the
* Sorts the specified range of the array into ascending order by the
* Dual-Pivot Quicksort algorithm.
* Dual-Pivot Quicksort algorithm. This method differs from the public
* {@code sort} method in that the {@code right} index is inclusive,
* it does no range checking on {@code left} or {@code right}, and has
* boolean flag whether insertion sort with sentinel is used or not.
*
*
* @param a the array to be sorted
* @param a the array to be sorted
* @param left the index of the first element, inclusive, to be sorted
* @param left the index of the first element, inclusive, to be sorted
* @param right the index of the last element, inclusive, to be sorted
* @param right the index of the last element, inclusive, to be sorted
* @param leftmost indicates if the part is the most left in the range
*/
*/
private
static
void
dualPivotQuicksort
(
short
[]
a
,
int
left
,
int
right
)
{
private
static
void
sort
(
short
[]
a
,
int
left
,
int
right
,
boolean
leftmost
)
{
// Compute indices of five evenly spaced elements
int
length
=
right
-
left
+
1
;
int
sixth
=
(
right
-
left
+
1
)
/
6
;
int
e1
=
left
+
sixth
;
// Use insertion sort on tiny arrays
int
e5
=
right
-
sixth
;
if
(
length
<
INSERTION_SORT_THRESHOLD
)
{
int
e3
=
(
left
+
right
)
>>>
1
;
// The midpoint
if
(!
leftmost
)
{
int
e4
=
e3
+
sixth
;
/*
int
e2
=
e3
-
sixth
;
* Every element in adjoining part plays the role
* of sentinel, therefore this allows us to avoid
* the j >= left check on each iteration.
*/
for
(
int
j
,
i
=
left
+
1
;
i
<=
right
;
i
++)
{
short
ai
=
a
[
i
];
for
(
j
=
i
-
1
;
ai
<
a
[
j
];
j
--)
{
// assert j >= left;
a
[
j
+
1
]
=
a
[
j
];
}
a
[
j
+
1
]
=
ai
;
}
}
else
{
/*
* For case of leftmost part traditional (without a sentinel)
* insertion sort, optimized for server JVM, is used.
*/
for
(
int
i
=
left
,
j
=
i
;
i
<
right
;
j
=
++
i
)
{
short
ai
=
a
[
i
+
1
];
while
(
ai
<
a
[
j
])
{
a
[
j
+
1
]
=
a
[
j
];
if
(
j
--
==
left
)
{
break
;
}
}
a
[
j
+
1
]
=
ai
;
}
}
return
;
}
//
Sort these elements using a 5-element sorting network
//
Inexpensive approximation of length / 7
short
ae1
=
a
[
e1
],
ae2
=
a
[
e2
],
ae3
=
a
[
e3
],
ae4
=
a
[
e4
],
ae5
=
a
[
e5
]
;
int
seventh
=
(
length
>>>
3
)
+
(
length
>>>
6
)
+
1
;
if
(
ae1
>
ae2
)
{
short
t
=
ae1
;
ae1
=
ae2
;
ae2
=
t
;
}
/*
if
(
ae4
>
ae5
)
{
short
t
=
ae4
;
ae4
=
ae5
;
ae5
=
t
;
}
* Sort five evenly spaced elements around (and including) the
if
(
ae1
>
ae3
)
{
short
t
=
ae1
;
ae1
=
ae3
;
ae3
=
t
;
}
* center element in the range. These elements will be used for
if
(
ae2
>
ae3
)
{
short
t
=
ae2
;
ae2
=
ae3
;
ae3
=
t
;
}
* pivot selection as described below. The choice for spacing
if
(
ae1
>
ae4
)
{
short
t
=
ae1
;
ae1
=
ae4
;
ae4
=
t
;
}
* these elements was empirically determined to work well on
if
(
ae3
>
ae4
)
{
short
t
=
ae3
;
ae3
=
ae4
;
ae4
=
t
;
}
* a wide variety of inputs.
if
(
ae2
>
ae5
)
{
short
t
=
ae2
;
ae2
=
ae5
;
ae5
=
t
;
}
*/
if
(
ae2
>
ae3
)
{
short
t
=
ae2
;
ae2
=
ae3
;
ae3
=
t
;
}
int
e3
=
(
left
+
right
)
>>>
1
;
// The midpoint
if
(
ae4
>
ae5
)
{
short
t
=
ae4
;
ae4
=
ae5
;
ae5
=
t
;
}
int
e2
=
e3
-
seventh
;
int
e1
=
e2
-
seventh
;
int
e4
=
e3
+
seventh
;
int
e5
=
e4
+
seventh
;
// Sort these elements using insertion sort
if
(
a
[
e2
]
<
a
[
e1
])
{
short
t
=
a
[
e2
];
a
[
e2
]
=
a
[
e1
];
a
[
e1
]
=
t
;
}
a
[
e1
]
=
ae1
;
a
[
e3
]
=
ae3
;
a
[
e5
]
=
ae5
;
if
(
a
[
e3
]
<
a
[
e2
])
{
short
t
=
a
[
e3
];
a
[
e3
]
=
a
[
e2
];
a
[
e2
]
=
t
;
if
(
t
<
a
[
e1
])
{
a
[
e2
]
=
a
[
e1
];
a
[
e1
]
=
t
;
}
}
if
(
a
[
e4
]
<
a
[
e3
])
{
short
t
=
a
[
e4
];
a
[
e4
]
=
a
[
e3
];
a
[
e3
]
=
t
;
if
(
t
<
a
[
e2
])
{
a
[
e3
]
=
a
[
e2
];
a
[
e2
]
=
t
;
if
(
t
<
a
[
e1
])
{
a
[
e2
]
=
a
[
e1
];
a
[
e1
]
=
t
;
}
}
}
if
(
a
[
e5
]
<
a
[
e4
])
{
short
t
=
a
[
e5
];
a
[
e5
]
=
a
[
e4
];
a
[
e4
]
=
t
;
if
(
t
<
a
[
e3
])
{
a
[
e4
]
=
a
[
e3
];
a
[
e3
]
=
t
;
if
(
t
<
a
[
e2
])
{
a
[
e3
]
=
a
[
e2
];
a
[
e2
]
=
t
;
if
(
t
<
a
[
e1
])
{
a
[
e2
]
=
a
[
e1
];
a
[
e1
]
=
t
;
}
}
}
}
/*
/*
* Use the second and fourth of the five sorted elements as pivots.
* Use the second and fourth of the five sorted elements as pivots.
* These values are inexpensive approximations of the first and
* These values are inexpensive approximations of the first and
* second terciles of the array. Note that pivot1 <= pivot2.
* second terciles of the array. Note that pivot1 <= pivot2.
*
* The pivots are stored in local variables, and the first and
* the last of the elements to be sorted are moved to the locations
* formerly occupied by the pivots. When partitioning is complete,
* the pivots are swapped back into their final positions, and
* excluded from subsequent sorting.
*/
*/
short
pivot1
=
a
e2
;
a
[
e2
]
=
a
[
left
];
short
pivot1
=
a
[
e2
];
short
pivot2
=
a
e4
;
a
[
e4
]
=
a
[
right
];
short
pivot2
=
a
[
e4
];
// Pointers
// Pointers
int
less
=
left
+
1
;
// The index of
first element of center part
int
less
=
left
;
// The index of the
first element of center part
int
great
=
right
-
1
;
// The index befor
e first element of right part
int
great
=
right
;
// The index before th
e first element of right part
boolean
pivotsDiffer
=
(
pivot1
!=
pivot2
);
if
(
pivot1
!=
pivot2
)
{
/*
* The first and the last elements to be sorted are moved to the
* locations formerly occupied by the pivots. When partitioning
* is complete, the pivots are swapped back into their final
* positions, and excluded from subsequent sorting.
*/
a
[
e2
]
=
a
[
left
];
a
[
e4
]
=
a
[
right
];
/*
* Skip elements, which are less or greater than pivot values.
*/
while
(
a
[++
less
]
<
pivot1
);
while
(
a
[--
great
]
>
pivot2
);
if
(
pivotsDiffer
)
{
/*
/*
* Partitioning:
* Partitioning:
*
*
* left part center part right part
* left part center part right part
* +------------------------------------------------------------+
* +------------------------------------------------------------
--
+
* | < pivot1 | pivot1 <= && <= pivot2 | ? | > pivot2 |
* | < pivot1 | pivot1 <= && <= pivot2 | ? | > pivot2 |
* +------------------------------------------------------------+
* +------------------------------------------------------------
--
+
* ^ ^ ^
* ^ ^ ^
* | | |
* | | |
* less k great
* less k great
...
@@ -767,16 +929,14 @@ final class DualPivotQuicksort {
...
@@ -767,16 +929,14 @@ final class DualPivotQuicksort {
* pivot1 <= all in [less, k) <= pivot2
* pivot1 <= all in [less, k) <= pivot2
* all in (great, right) > pivot2
* all in (great, right) > pivot2
*
*
* Pointer k is the first index of ?-part
* Pointer k is the first index of ?-part
.
*/
*/
outer:
outer:
for
(
int
k
=
less
;
k
<=
great
;
k
++)
{
for
(
int
k
=
less
;
k
<=
great
;
k
++)
{
short
ak
=
a
[
k
];
short
ak
=
a
[
k
];
if
(
ak
<
pivot1
)
{
// Move a[k] to left part
if
(
ak
<
pivot1
)
{
// Move a[k] to left part
if
(
k
!=
less
)
{
a
[
k
]
=
a
[
less
];
a
[
k
]
=
a
[
less
];
a
[
less
]
=
ak
;
a
[
less
]
=
ak
;
}
less
++;
less
++;
}
else
if
(
ak
>
pivot2
)
{
// Move a[k] to right part
}
else
if
(
ak
>
pivot2
)
{
// Move a[k] to right part
while
(
a
[
great
]
>
pivot2
)
{
while
(
a
[
great
]
>
pivot2
)
{
...
@@ -786,89 +946,32 @@ final class DualPivotQuicksort {
...
@@ -786,89 +946,32 @@ final class DualPivotQuicksort {
}
}
if
(
a
[
great
]
<
pivot1
)
{
if
(
a
[
great
]
<
pivot1
)
{
a
[
k
]
=
a
[
less
];
a
[
k
]
=
a
[
less
];
a
[
less
++
]
=
a
[
great
];
a
[
less
]
=
a
[
great
];
a
[
great
--]
=
ak
;
less
++
;
}
else
{
// pivot1 <= a[great] <= pivot2
}
else
{
// pivot1 <= a[great] <= pivot2
a
[
k
]
=
a
[
great
];
a
[
k
]
=
a
[
great
];
a
[
great
--]
=
ak
;
}
}
}
a
[
great
]
=
ak
;
}
}
else
{
// Pivots are equal
/*
* Partition degenerates to the traditional 3-way,
* or "Dutch National Flag", partition:
*
* left part center part right part
* +----------------------------------------------+
* | < pivot | == pivot | ? | > pivot |
* +----------------------------------------------+
* ^ ^ ^
* | | |
* less k great
*
* Invariants:
*
* all in (left, less) < pivot
* all in [less, k) == pivot
* all in (great, right) > pivot
*
* Pointer k is the first index of ?-part
*/
for
(
int
k
=
less
;
k
<=
great
;
k
++)
{
short
ak
=
a
[
k
];
if
(
ak
==
pivot1
)
{
continue
;
}
if
(
ak
<
pivot1
)
{
// Move a[k] to left part
if
(
k
!=
less
)
{
a
[
k
]
=
a
[
less
];
a
[
less
]
=
ak
;
}
less
++;
}
else
{
// (a[k] > pivot1) - Move a[k] to right part
/*
* We know that pivot1 == a[e3] == pivot2. Thus, we know
* that great will still be >= k when the following loop
* terminates, even though we don't test for it explicitly.
* In other words, a[e3] acts as a sentinel for great.
*/
while
(
a
[
great
]
>
pivot1
)
{
great
--;
great
--;
}
}
if
(
a
[
great
]
<
pivot1
)
{
a
[
k
]
=
a
[
less
];
a
[
less
++]
=
a
[
great
];
a
[
great
--]
=
ak
;
}
else
{
// a[great] == pivot1
a
[
k
]
=
pivot1
;
a
[
great
--]
=
ak
;
}
}
}
}
}
// Swap pivots into their final positions
// Swap pivots into their final positions
a
[
left
]
=
a
[
less
-
1
];
a
[
less
-
1
]
=
pivot1
;
a
[
left
]
=
a
[
less
-
1
];
a
[
less
-
1
]
=
pivot1
;
a
[
right
]
=
a
[
great
+
1
];
a
[
great
+
1
]
=
pivot2
;
a
[
right
]
=
a
[
great
+
1
];
a
[
great
+
1
]
=
pivot2
;
// Sort left and right parts recursively, excluding known pivot value
s
// Sort left and right parts recursively, excluding known pivot
s
doSort
(
a
,
left
,
less
-
2
);
sort
(
a
,
left
,
less
-
2
,
leftmost
);
doSort
(
a
,
great
+
2
,
right
);
sort
(
a
,
great
+
2
,
right
,
false
);
/*
/*
* If pivot1 == pivot2, all elements from center
* If center part is too large (comprises > 5/7 of the array),
* part are equal and, therefore, already sorted
* swap internal pivot values to ends.
*/
*/
if
(!
pivotsDiffer
)
{
if
(
less
<
e1
&&
e5
<
great
)
{
return
;
}
/*
/*
* If center part is too large (comprises > 2/3 of the array),
* Skip elements, which are equal to pivot values.
* swap internal pivot values to ends
*/
*/
if
(
less
<
e1
&&
great
>
e5
)
{
while
(
a
[
less
]
==
pivot1
)
{
while
(
a
[
less
]
==
pivot1
)
{
less
++;
less
++;
}
}
...
@@ -893,12 +996,16 @@ final class DualPivotQuicksort {
...
@@ -893,12 +996,16 @@ final class DualPivotQuicksort {
* pivot1 < all in [less, k) < pivot2
* pivot1 < all in [less, k) < pivot2
* all in (great, *) == pivot2
* all in (great, *) == pivot2
*
*
* Pointer k is the first index of ?-part
* Pointer k is the first index of ?-part.
*/
*/
outer:
outer:
for
(
int
k
=
less
;
k
<=
great
;
k
++)
{
for
(
int
k
=
less
;
k
<=
great
;
k
++)
{
short
ak
=
a
[
k
];
short
ak
=
a
[
k
];
if
(
ak
==
pivot2
)
{
// Move a[k] to right part
if
(
ak
==
pivot1
)
{
// Move a[k] to left part
a
[
k
]
=
a
[
less
];
a
[
less
]
=
ak
;
less
++;
}
else
if
(
ak
==
pivot2
)
{
// Move a[k] to right part
while
(
a
[
great
]
==
pivot2
)
{
while
(
a
[
great
]
==
pivot2
)
{
if
(
great
--
==
k
)
{
if
(
great
--
==
k
)
{
break
outer
;
break
outer
;
...
@@ -906,20 +1013,94 @@ final class DualPivotQuicksort {
...
@@ -906,20 +1013,94 @@ final class DualPivotQuicksort {
}
}
if
(
a
[
great
]
==
pivot1
)
{
if
(
a
[
great
]
==
pivot1
)
{
a
[
k
]
=
a
[
less
];
a
[
k
]
=
a
[
less
];
a
[
less
++]
=
pivot1
;
/*
* Even though a[great] equals to pivot1, the
* assignment a[less] = pivot1 may be incorrect,
* if a[great] and pivot1 are floating-point zeros
* of different signs. Therefore in float and
* double sorting methods we have to use more
* accurate assignment a[less] = a[great].
*/
a
[
less
]
=
pivot1
;
less
++;
}
else
{
// pivot1 < a[great] < pivot2
}
else
{
// pivot1 < a[great] < pivot2
a
[
k
]
=
a
[
great
];
a
[
k
]
=
a
[
great
];
}
}
a
[
great
--]
=
pivot2
;
a
[
great
]
=
ak
;
}
else
if
(
ak
==
pivot1
)
{
// Move a[k] to left part
great
--;
}
}
}
// Sort center part recursively
sort
(
a
,
less
,
great
,
false
);
}
else
{
// Pivots are equal
/*
* Partition degenerates to the traditional 3-way
* (or "Dutch National Flag") schema:
*
* left part center part right part
* +-------------------------------------------------+
* | < pivot | == pivot | ? | > pivot |
* +-------------------------------------------------+
* ^ ^ ^
* | | |
* less k great
*
* Invariants:
*
* all in (left, less) < pivot
* all in [less, k) == pivot
* all in (great, right) > pivot
*
* Pointer k is the first index of ?-part.
*/
for
(
int
k
=
left
;
k
<=
great
;
k
++)
{
if
(
a
[
k
]
==
pivot1
)
{
continue
;
}
short
ak
=
a
[
k
];
if
(
ak
<
pivot1
)
{
// Move a[k] to left part
a
[
k
]
=
a
[
less
];
a
[
k
]
=
a
[
less
];
a
[
less
++]
=
pivot1
;
a
[
less
]
=
ak
;
less
++;
}
else
{
// a[k] > pivot1 - Move a[k] to right part
/*
* We know that pivot1 == a[e3] == pivot2. Thus, we know
* that great will still be >= k when the following loop
* terminates, even though we don't test for it explicitly.
* In other words, a[e3] acts as a sentinel for great.
*/
while
(
a
[
great
]
>
pivot1
)
{
// assert great > k;
great
--;
}
}
if
(
a
[
great
]
<
pivot1
)
{
a
[
k
]
=
a
[
less
];
a
[
less
]
=
a
[
great
];
less
++;
}
else
{
// a[great] == pivot1
/*
* Even though a[great] equals to pivot1, the
* assignment a[k] = pivot1 may be incorrect,
* if a[great] and pivot1 are floating-point
* zeros of different signs. Therefore in float
* and double sorting methods we have to use
* more accurate assignment a[k] = a[great].
*/
a
[
k
]
=
pivot1
;
}
a
[
great
]
=
ak
;
great
--;
}
}
}
}
// Sort center part recursively, excluding known pivot values
// Sort left and right parts recursively
doSort
(
a
,
less
,
great
);
sort
(
a
,
left
,
less
-
1
,
leftmost
);
sort
(
a
,
great
+
1
,
right
,
false
);
}
}
}
/**
/**
...
@@ -928,7 +1109,11 @@ final class DualPivotQuicksort {
...
@@ -928,7 +1109,11 @@ final class DualPivotQuicksort {
* @param a the array to be sorted
* @param a the array to be sorted
*/
*/
public
static
void
sort
(
char
[]
a
)
{
public
static
void
sort
(
char
[]
a
)
{
doSort
(
a
,
0
,
a
.
length
-
1
);
if
(
a
.
length
>
COUNTING_SORT_THRESHOLD_FOR_SHORT_OR_CHAR
)
{
countingSort
(
a
,
0
,
a
.
length
-
1
);
}
else
{
sort
(
a
,
0
,
a
.
length
-
1
,
true
);
}
}
}
/**
/**
...
@@ -946,110 +1131,163 @@ final class DualPivotQuicksort {
...
@@ -946,110 +1131,163 @@ final class DualPivotQuicksort {
*/
*/
public
static
void
sort
(
char
[]
a
,
int
fromIndex
,
int
toIndex
)
{
public
static
void
sort
(
char
[]
a
,
int
fromIndex
,
int
toIndex
)
{
rangeCheck
(
a
.
length
,
fromIndex
,
toIndex
);
rangeCheck
(
a
.
length
,
fromIndex
,
toIndex
);
doSort
(
a
,
fromIndex
,
toIndex
-
1
);
if
(
toIndex
-
fromIndex
>
COUNTING_SORT_THRESHOLD_FOR_SHORT_OR_CHAR
)
{
countingSort
(
a
,
fromIndex
,
toIndex
-
1
);
}
else
{
sort
(
a
,
fromIndex
,
toIndex
-
1
,
true
);
}
}
}
/** The number of distinct char values. */
/** The number of distinct char values. */
private
static
final
int
NUM_CHAR_VALUES
=
1
<<
16
;
private
static
final
int
NUM_CHAR_VALUES
=
1
<<
16
;
/**
/**
* Sorts the specified range of the array into ascending order. This
* Sorts the specified range of the array by counting sort.
* method differs from the public {@code sort} method in that the
* {@code right} index is inclusive, and it does no range checking on
* {@code left} or {@code right}.
*
*
* @param a the array to be sorted
* @param a the array to be sorted
* @param left the index of the first element, inclusive, to be sorted
* @param left the index of the first element, inclusive, to be sorted
* @param right the index of the last element, inclusive, to be sorted
* @param right the index of the last element, inclusive, to be sorted
*/
*/
private
static
void
doSort
(
char
[]
a
,
int
left
,
int
right
)
{
private
static
void
countingSort
(
char
[]
a
,
int
left
,
int
right
)
{
// Use insertion sort on tiny arrays
if
(
right
-
left
+
1
<
INSERTION_SORT_THRESHOLD
)
{
for
(
int
i
=
left
+
1
;
i
<=
right
;
i
++)
{
char
ai
=
a
[
i
];
int
j
;
for
(
j
=
i
-
1
;
j
>=
left
&&
ai
<
a
[
j
];
j
--)
{
a
[
j
+
1
]
=
a
[
j
];
}
a
[
j
+
1
]
=
ai
;
}
}
else
if
(
right
-
left
+
1
>
COUNTING_SORT_THRESHOLD_FOR_SHORT_OR_CHAR
)
{
// Use counting sort on huge arrays
int
[]
count
=
new
int
[
NUM_CHAR_VALUES
];
int
[]
count
=
new
int
[
NUM_CHAR_VALUES
];
for
(
int
i
=
left
;
i
<=
right
;
i
++)
{
for
(
int
i
=
left
;
i
<=
right
;
i
++)
{
count
[
a
[
i
]]++;
count
[
a
[
i
]]++;
}
}
for
(
int
i
=
0
,
k
=
left
;
i
<
count
.
length
&&
k
<=
right
;
i
++)
{
for
(
int
i
=
0
,
k
=
left
;
k
<=
right
;
i
++)
{
for
(
int
s
=
count
[
i
];
s
>
0
;
s
--)
{
while
(
count
[
i
]
==
0
)
{
a
[
k
++]
=
(
char
)
i
;
i
++;
}
}
}
}
else
{
// Use Dual-Pivot Quicksort on large arrays
char
value
=
(
char
)
i
;
dualPivotQuicksort
(
a
,
left
,
right
);
int
s
=
count
[
i
];
do
{
a
[
k
++]
=
value
;
}
while
(--
s
>
0
);
}
}
}
}
/**
/**
* Sorts the specified range of the array into ascending order by the
* Sorts the specified range of the array into ascending order by the
* Dual-Pivot Quicksort algorithm.
* Dual-Pivot Quicksort algorithm. This method differs from the public
* {@code sort} method in that the {@code right} index is inclusive,
* it does no range checking on {@code left} or {@code right}, and has
* boolean flag whether insertion sort with sentinel is used or not.
*
*
* @param a the array to be sorted
* @param a the array to be sorted
* @param left the index of the first element, inclusive, to be sorted
* @param left the index of the first element, inclusive, to be sorted
* @param right the index of the last element, inclusive, to be sorted
* @param right the index of the last element, inclusive, to be sorted
* @param leftmost indicates if the part is the most left in the range
*/
*/
private
static
void
dualPivotQuicksort
(
char
[]
a
,
int
left
,
int
right
)
{
private
static
void
sort
(
char
[]
a
,
int
left
,
int
right
,
boolean
leftmost
)
{
// Compute indices of five evenly spaced elements
int
length
=
right
-
left
+
1
;
int
sixth
=
(
right
-
left
+
1
)
/
6
;
int
e1
=
left
+
sixth
;
// Use insertion sort on tiny arrays
int
e5
=
right
-
sixth
;
if
(
length
<
INSERTION_SORT_THRESHOLD
)
{
int
e3
=
(
left
+
right
)
>>>
1
;
// The midpoint
if
(!
leftmost
)
{
int
e4
=
e3
+
sixth
;
/*
int
e2
=
e3
-
sixth
;
* Every element in adjoining part plays the role
* of sentinel, therefore this allows us to avoid
* the j >= left check on each iteration.
*/
for
(
int
j
,
i
=
left
+
1
;
i
<=
right
;
i
++)
{
char
ai
=
a
[
i
];
for
(
j
=
i
-
1
;
ai
<
a
[
j
];
j
--)
{
// assert j >= left;
a
[
j
+
1
]
=
a
[
j
];
}
a
[
j
+
1
]
=
ai
;
}
}
else
{
/*
* For case of leftmost part traditional (without a sentinel)
* insertion sort, optimized for server JVM, is used.
*/
for
(
int
i
=
left
,
j
=
i
;
i
<
right
;
j
=
++
i
)
{
char
ai
=
a
[
i
+
1
];
while
(
ai
<
a
[
j
])
{
a
[
j
+
1
]
=
a
[
j
];
if
(
j
--
==
left
)
{
break
;
}
}
a
[
j
+
1
]
=
ai
;
}
}
return
;
}
// Inexpensive approximation of length / 7
int
seventh
=
(
length
>>>
3
)
+
(
length
>>>
6
)
+
1
;
// Sort these elements using a 5-element sorting network
/*
char
ae1
=
a
[
e1
],
ae2
=
a
[
e2
],
ae3
=
a
[
e3
],
ae4
=
a
[
e4
],
ae5
=
a
[
e5
];
* Sort five evenly spaced elements around (and including) the
* center element in the range. These elements will be used for
* pivot selection as described below. The choice for spacing
* these elements was empirically determined to work well on
* a wide variety of inputs.
*/
int
e3
=
(
left
+
right
)
>>>
1
;
// The midpoint
int
e2
=
e3
-
seventh
;
int
e1
=
e2
-
seventh
;
int
e4
=
e3
+
seventh
;
int
e5
=
e4
+
seventh
;
if
(
ae1
>
ae2
)
{
char
t
=
ae1
;
ae1
=
ae2
;
ae2
=
t
;
}
// Sort these elements using insertion sort
if
(
ae4
>
ae5
)
{
char
t
=
ae4
;
ae4
=
ae5
;
ae5
=
t
;
}
if
(
a
[
e2
]
<
a
[
e1
])
{
char
t
=
a
[
e2
];
a
[
e2
]
=
a
[
e1
];
a
[
e1
]
=
t
;
}
if
(
ae1
>
ae3
)
{
char
t
=
ae1
;
ae1
=
ae3
;
ae3
=
t
;
}
if
(
ae2
>
ae3
)
{
char
t
=
ae2
;
ae2
=
ae3
;
ae3
=
t
;
}
if
(
ae1
>
ae4
)
{
char
t
=
ae1
;
ae1
=
ae4
;
ae4
=
t
;
}
if
(
ae3
>
ae4
)
{
char
t
=
ae3
;
ae3
=
ae4
;
ae4
=
t
;
}
if
(
ae2
>
ae5
)
{
char
t
=
ae2
;
ae2
=
ae5
;
ae5
=
t
;
}
if
(
ae2
>
ae3
)
{
char
t
=
ae2
;
ae2
=
ae3
;
ae3
=
t
;
}
if
(
ae4
>
ae5
)
{
char
t
=
ae4
;
ae4
=
ae5
;
ae5
=
t
;
}
a
[
e1
]
=
ae1
;
a
[
e3
]
=
ae3
;
a
[
e5
]
=
ae5
;
if
(
a
[
e3
]
<
a
[
e2
])
{
char
t
=
a
[
e3
];
a
[
e3
]
=
a
[
e2
];
a
[
e2
]
=
t
;
if
(
t
<
a
[
e1
])
{
a
[
e2
]
=
a
[
e1
];
a
[
e1
]
=
t
;
}
}
if
(
a
[
e4
]
<
a
[
e3
])
{
char
t
=
a
[
e4
];
a
[
e4
]
=
a
[
e3
];
a
[
e3
]
=
t
;
if
(
t
<
a
[
e2
])
{
a
[
e3
]
=
a
[
e2
];
a
[
e2
]
=
t
;
if
(
t
<
a
[
e1
])
{
a
[
e2
]
=
a
[
e1
];
a
[
e1
]
=
t
;
}
}
}
if
(
a
[
e5
]
<
a
[
e4
])
{
char
t
=
a
[
e5
];
a
[
e5
]
=
a
[
e4
];
a
[
e4
]
=
t
;
if
(
t
<
a
[
e3
])
{
a
[
e4
]
=
a
[
e3
];
a
[
e3
]
=
t
;
if
(
t
<
a
[
e2
])
{
a
[
e3
]
=
a
[
e2
];
a
[
e2
]
=
t
;
if
(
t
<
a
[
e1
])
{
a
[
e2
]
=
a
[
e1
];
a
[
e1
]
=
t
;
}
}
}
}
/*
/*
* Use the second and fourth of the five sorted elements as pivots.
* Use the second and fourth of the five sorted elements as pivots.
* These values are inexpensive approximations of the first and
* These values are inexpensive approximations of the first and
* second terciles of the array. Note that pivot1 <= pivot2.
* second terciles of the array. Note that pivot1 <= pivot2.
*
* The pivots are stored in local variables, and the first and
* the last of the elements to be sorted are moved to the locations
* formerly occupied by the pivots. When partitioning is complete,
* the pivots are swapped back into their final positions, and
* excluded from subsequent sorting.
*/
*/
char
pivot1
=
a
e2
;
a
[
e2
]
=
a
[
left
];
char
pivot1
=
a
[
e2
];
char
pivot2
=
a
e4
;
a
[
e4
]
=
a
[
right
];
char
pivot2
=
a
[
e4
];
// Pointers
// Pointers
int
less
=
left
+
1
;
// The index of
first element of center part
int
less
=
left
;
// The index of the
first element of center part
int
great
=
right
-
1
;
// The index befor
e first element of right part
int
great
=
right
;
// The index before th
e first element of right part
boolean
pivotsDiffer
=
(
pivot1
!=
pivot2
);
if
(
pivot1
!=
pivot2
)
{
/*
* The first and the last elements to be sorted are moved to the
* locations formerly occupied by the pivots. When partitioning
* is complete, the pivots are swapped back into their final
* positions, and excluded from subsequent sorting.
*/
a
[
e2
]
=
a
[
left
];
a
[
e4
]
=
a
[
right
];
/*
* Skip elements, which are less or greater than pivot values.
*/
while
(
a
[++
less
]
<
pivot1
);
while
(
a
[--
great
]
>
pivot2
);
if
(
pivotsDiffer
)
{
/*
/*
* Partitioning:
* Partitioning:
*
*
* left part center part right part
* left part center part right part
* +------------------------------------------------------------+
* +------------------------------------------------------------
--
+
* | < pivot1 | pivot1 <= && <= pivot2 | ? | > pivot2 |
* | < pivot1 | pivot1 <= && <= pivot2 | ? | > pivot2 |
* +------------------------------------------------------------+
* +------------------------------------------------------------
--
+
* ^ ^ ^
* ^ ^ ^
* | | |
* | | |
* less k great
* less k great
...
@@ -1060,16 +1298,14 @@ final class DualPivotQuicksort {
...
@@ -1060,16 +1298,14 @@ final class DualPivotQuicksort {
* pivot1 <= all in [less, k) <= pivot2
* pivot1 <= all in [less, k) <= pivot2
* all in (great, right) > pivot2
* all in (great, right) > pivot2
*
*
* Pointer k is the first index of ?-part
* Pointer k is the first index of ?-part
.
*/
*/
outer:
outer:
for
(
int
k
=
less
;
k
<=
great
;
k
++)
{
for
(
int
k
=
less
;
k
<=
great
;
k
++)
{
char
ak
=
a
[
k
];
char
ak
=
a
[
k
];
if
(
ak
<
pivot1
)
{
// Move a[k] to left part
if
(
ak
<
pivot1
)
{
// Move a[k] to left part
if
(
k
!=
less
)
{
a
[
k
]
=
a
[
less
];
a
[
k
]
=
a
[
less
];
a
[
less
]
=
ak
;
a
[
less
]
=
ak
;
}
less
++;
less
++;
}
else
if
(
ak
>
pivot2
)
{
// Move a[k] to right part
}
else
if
(
ak
>
pivot2
)
{
// Move a[k] to right part
while
(
a
[
great
]
>
pivot2
)
{
while
(
a
[
great
]
>
pivot2
)
{
...
@@ -1079,89 +1315,32 @@ final class DualPivotQuicksort {
...
@@ -1079,89 +1315,32 @@ final class DualPivotQuicksort {
}
}
if
(
a
[
great
]
<
pivot1
)
{
if
(
a
[
great
]
<
pivot1
)
{
a
[
k
]
=
a
[
less
];
a
[
k
]
=
a
[
less
];
a
[
less
++
]
=
a
[
great
];
a
[
less
]
=
a
[
great
];
a
[
great
--]
=
ak
;
less
++
;
}
else
{
// pivot1 <= a[great] <= pivot2
}
else
{
// pivot1 <= a[great] <= pivot2
a
[
k
]
=
a
[
great
];
a
[
k
]
=
a
[
great
];
a
[
great
--]
=
ak
;
}
}
}
}
}
else
{
// Pivots are equal
a
[
great
]
=
ak
;
/*
* Partition degenerates to the traditional 3-way,
* or "Dutch National Flag", partition:
*
* left part center part right part
* +----------------------------------------------+
* | < pivot | == pivot | ? | > pivot |
* +----------------------------------------------+
* ^ ^ ^
* | | |
* less k great
*
* Invariants:
*
* all in (left, less) < pivot
* all in [less, k) == pivot
* all in (great, right) > pivot
*
* Pointer k is the first index of ?-part
*/
for
(
int
k
=
less
;
k
<=
great
;
k
++)
{
char
ak
=
a
[
k
];
if
(
ak
==
pivot1
)
{
continue
;
}
if
(
ak
<
pivot1
)
{
// Move a[k] to left part
if
(
k
!=
less
)
{
a
[
k
]
=
a
[
less
];
a
[
less
]
=
ak
;
}
less
++;
}
else
{
// (a[k] > pivot1) - Move a[k] to right part
/*
* We know that pivot1 == a[e3] == pivot2. Thus, we know
* that great will still be >= k when the following loop
* terminates, even though we don't test for it explicitly.
* In other words, a[e3] acts as a sentinel for great.
*/
while
(
a
[
great
]
>
pivot1
)
{
great
--;
great
--;
}
}
if
(
a
[
great
]
<
pivot1
)
{
a
[
k
]
=
a
[
less
];
a
[
less
++]
=
a
[
great
];
a
[
great
--]
=
ak
;
}
else
{
// a[great] == pivot1
a
[
k
]
=
pivot1
;
a
[
great
--]
=
ak
;
}
}
}
}
}
// Swap pivots into their final positions
// Swap pivots into their final positions
a
[
left
]
=
a
[
less
-
1
];
a
[
less
-
1
]
=
pivot1
;
a
[
left
]
=
a
[
less
-
1
];
a
[
less
-
1
]
=
pivot1
;
a
[
right
]
=
a
[
great
+
1
];
a
[
great
+
1
]
=
pivot2
;
a
[
right
]
=
a
[
great
+
1
];
a
[
great
+
1
]
=
pivot2
;
// Sort left and right parts recursively, excluding known pivot value
s
// Sort left and right parts recursively, excluding known pivot
s
doSort
(
a
,
left
,
less
-
2
);
sort
(
a
,
left
,
less
-
2
,
leftmost
);
doSort
(
a
,
great
+
2
,
right
);
sort
(
a
,
great
+
2
,
right
,
false
);
/*
/*
* If pivot1 == pivot2, all elements from center
* If center part is too large (comprises > 5/7 of the array),
* part are equal and, therefore, already sorted
* swap internal pivot values to ends.
*/
*/
if
(!
pivotsDiffer
)
{
if
(
less
<
e1
&&
e5
<
great
)
{
return
;
}
/*
/*
* If center part is too large (comprises > 2/3 of the array),
* Skip elements, which are equal to pivot values.
* swap internal pivot values to ends
*/
*/
if
(
less
<
e1
&&
great
>
e5
)
{
while
(
a
[
less
]
==
pivot1
)
{
while
(
a
[
less
]
==
pivot1
)
{
less
++;
less
++;
}
}
...
@@ -1186,12 +1365,16 @@ final class DualPivotQuicksort {
...
@@ -1186,12 +1365,16 @@ final class DualPivotQuicksort {
* pivot1 < all in [less, k) < pivot2
* pivot1 < all in [less, k) < pivot2
* all in (great, *) == pivot2
* all in (great, *) == pivot2
*
*
* Pointer k is the first index of ?-part
* Pointer k is the first index of ?-part.
*/
*/
outer:
outer:
for
(
int
k
=
less
;
k
<=
great
;
k
++)
{
for
(
int
k
=
less
;
k
<=
great
;
k
++)
{
char
ak
=
a
[
k
];
char
ak
=
a
[
k
];
if
(
ak
==
pivot2
)
{
// Move a[k] to right part
if
(
ak
==
pivot1
)
{
// Move a[k] to left part
a
[
k
]
=
a
[
less
];
a
[
less
]
=
ak
;
less
++;
}
else
if
(
ak
==
pivot2
)
{
// Move a[k] to right part
while
(
a
[
great
]
==
pivot2
)
{
while
(
a
[
great
]
==
pivot2
)
{
if
(
great
--
==
k
)
{
if
(
great
--
==
k
)
{
break
outer
;
break
outer
;
...
@@ -1199,20 +1382,94 @@ final class DualPivotQuicksort {
...
@@ -1199,20 +1382,94 @@ final class DualPivotQuicksort {
}
}
if
(
a
[
great
]
==
pivot1
)
{
if
(
a
[
great
]
==
pivot1
)
{
a
[
k
]
=
a
[
less
];
a
[
k
]
=
a
[
less
];
a
[
less
++]
=
pivot1
;
/*
* Even though a[great] equals to pivot1, the
* assignment a[less] = pivot1 may be incorrect,
* if a[great] and pivot1 are floating-point zeros
* of different signs. Therefore in float and
* double sorting methods we have to use more
* accurate assignment a[less] = a[great].
*/
a
[
less
]
=
pivot1
;
less
++;
}
else
{
// pivot1 < a[great] < pivot2
}
else
{
// pivot1 < a[great] < pivot2
a
[
k
]
=
a
[
great
];
a
[
k
]
=
a
[
great
];
}
}
a
[
great
--]
=
pivot2
;
a
[
great
]
=
ak
;
}
else
if
(
ak
==
pivot1
)
{
// Move a[k] to left part
great
--;
}
}
}
// Sort center part recursively
sort
(
a
,
less
,
great
,
false
);
}
else
{
// Pivots are equal
/*
* Partition degenerates to the traditional 3-way
* (or "Dutch National Flag") schema:
*
* left part center part right part
* +-------------------------------------------------+
* | < pivot | == pivot | ? | > pivot |
* +-------------------------------------------------+
* ^ ^ ^
* | | |
* less k great
*
* Invariants:
*
* all in (left, less) < pivot
* all in [less, k) == pivot
* all in (great, right) > pivot
*
* Pointer k is the first index of ?-part.
*/
for
(
int
k
=
left
;
k
<=
great
;
k
++)
{
if
(
a
[
k
]
==
pivot1
)
{
continue
;
}
char
ak
=
a
[
k
];
if
(
ak
<
pivot1
)
{
// Move a[k] to left part
a
[
k
]
=
a
[
less
];
a
[
less
]
=
ak
;
less
++;
}
else
{
// a[k] > pivot1 - Move a[k] to right part
/*
* We know that pivot1 == a[e3] == pivot2. Thus, we know
* that great will still be >= k when the following loop
* terminates, even though we don't test for it explicitly.
* In other words, a[e3] acts as a sentinel for great.
*/
while
(
a
[
great
]
>
pivot1
)
{
// assert great > k;
great
--;
}
if
(
a
[
great
]
<
pivot1
)
{
a
[
k
]
=
a
[
less
];
a
[
k
]
=
a
[
less
];
a
[
less
++]
=
pivot1
;
a
[
less
]
=
a
[
great
];
less
++;
}
else
{
// a[great] == pivot1
/*
* Even though a[great] equals to pivot1, the
* assignment a[k] = pivot1 may be incorrect,
* if a[great] and pivot1 are floating-point
* zeros of different signs. Therefore in float
* and double sorting methods we have to use
* more accurate assignment a[k] = a[great].
*/
a
[
k
]
=
pivot1
;
}
}
a
[
great
]
=
ak
;
great
--;
}
}
}
}
// Sort center part recursively, excluding known pivot values
// Sort left and right parts recursively
doSort
(
a
,
less
,
great
);
sort
(
a
,
left
,
less
-
1
,
leftmost
);
sort
(
a
,
great
+
1
,
right
,
false
);
}
}
}
/**
/**
...
@@ -1221,7 +1478,11 @@ final class DualPivotQuicksort {
...
@@ -1221,7 +1478,11 @@ final class DualPivotQuicksort {
* @param a the array to be sorted
* @param a the array to be sorted
*/
*/
public
static
void
sort
(
byte
[]
a
)
{
public
static
void
sort
(
byte
[]
a
)
{
doSort
(
a
,
0
,
a
.
length
-
1
);
if
(
a
.
length
>
COUNTING_SORT_THRESHOLD_FOR_BYTE
)
{
countingSort
(
a
,
0
,
a
.
length
-
1
);
}
else
{
sort
(
a
,
0
,
a
.
length
-
1
,
true
);
}
}
}
/**
/**
...
@@ -1239,112 +1500,163 @@ final class DualPivotQuicksort {
...
@@ -1239,112 +1500,163 @@ final class DualPivotQuicksort {
*/
*/
public
static
void
sort
(
byte
[]
a
,
int
fromIndex
,
int
toIndex
)
{
public
static
void
sort
(
byte
[]
a
,
int
fromIndex
,
int
toIndex
)
{
rangeCheck
(
a
.
length
,
fromIndex
,
toIndex
);
rangeCheck
(
a
.
length
,
fromIndex
,
toIndex
);
doSort
(
a
,
fromIndex
,
toIndex
-
1
);
if
(
toIndex
-
fromIndex
>
COUNTING_SORT_THRESHOLD_FOR_BYTE
)
{
countingSort
(
a
,
fromIndex
,
toIndex
-
1
);
}
else
{
sort
(
a
,
fromIndex
,
toIndex
-
1
,
true
);
}
}
}
/** The number of distinct byte values. */
/** The number of distinct byte values. */
private
static
final
int
NUM_BYTE_VALUES
=
1
<<
8
;
private
static
final
int
NUM_BYTE_VALUES
=
1
<<
8
;
/**
/**
* Sorts the specified range of the array into ascending order. This
* Sorts the specified range of the array by counting sort.
* method differs from the public {@code sort} method in that the
* {@code right} index is inclusive, and it does no range checking on
* {@code left} or {@code right}.
*
*
* @param a the array to be sorted
* @param a the array to be sorted
* @param left the index of the first element, inclusive, to be sorted
* @param left the index of the first element, inclusive, to be sorted
* @param right the index of the last element, inclusive, to be sorted
* @param right the index of the last element, inclusive, to be sorted
*/
*/
private
static
void
doSort
(
byte
[]
a
,
int
left
,
int
right
)
{
private
static
void
countingSort
(
byte
[]
a
,
int
left
,
int
right
)
{
// Use insertion sort on tiny arrays
if
(
right
-
left
+
1
<
INSERTION_SORT_THRESHOLD
)
{
for
(
int
i
=
left
+
1
;
i
<=
right
;
i
++)
{
byte
ai
=
a
[
i
];
int
j
;
for
(
j
=
i
-
1
;
j
>=
left
&&
ai
<
a
[
j
];
j
--)
{
a
[
j
+
1
]
=
a
[
j
];
}
a
[
j
+
1
]
=
ai
;
}
}
else
if
(
right
-
left
+
1
>
COUNTING_SORT_THRESHOLD_FOR_BYTE
)
{
// Use counting sort on huge arrays
int
[]
count
=
new
int
[
NUM_BYTE_VALUES
];
int
[]
count
=
new
int
[
NUM_BYTE_VALUES
];
for
(
int
i
=
left
;
i
<=
right
;
i
++)
{
for
(
int
i
=
left
;
i
<=
right
;
i
++)
{
count
[
a
[
i
]
-
Byte
.
MIN_VALUE
]++;
count
[
a
[
i
]
-
Byte
.
MIN_VALUE
]++;
}
}
for
(
int
i
=
0
,
k
=
left
;
i
<
count
.
length
&&
k
<=
right
;
i
++)
{
for
(
int
i
=
NUM_BYTE_VALUES
-
1
,
k
=
right
;
k
>=
left
;
i
--)
{
while
(
count
[
i
]
==
0
)
{
i
--;
}
byte
value
=
(
byte
)
(
i
+
Byte
.
MIN_VALUE
);
byte
value
=
(
byte
)
(
i
+
Byte
.
MIN_VALUE
);
int
s
=
count
[
i
];
for
(
int
s
=
count
[
i
];
s
>
0
;
s
--)
{
do
{
a
[
k
++]
=
value
;
a
[
k
--]
=
value
;
}
}
while
(--
s
>
0
);
}
}
else
{
// Use Dual-Pivot Quicksort on large arrays
dualPivotQuicksort
(
a
,
left
,
right
);
}
}
}
}
/**
/**
* Sorts the specified range of the array into ascending order by the
* Sorts the specified range of the array into ascending order by the
* Dual-Pivot Quicksort algorithm.
* Dual-Pivot Quicksort algorithm. This method differs from the public
* {@code sort} method in that the {@code right} index is inclusive,
* it does no range checking on {@code left} or {@code right}, and has
* boolean flag whether insertion sort with sentinel is used or not.
*
*
* @param a the array to be sorted
* @param a the array to be sorted
* @param left the index of the first element, inclusive, to be sorted
* @param left the index of the first element, inclusive, to be sorted
* @param right the index of the last element, inclusive, to be sorted
* @param right the index of the last element, inclusive, to be sorted
* @param leftmost indicates if the part is the most left in the range
*/
*/
private
static
void
dualPivotQuicksort
(
byte
[]
a
,
int
left
,
int
right
)
{
private
static
void
sort
(
byte
[]
a
,
int
left
,
int
right
,
boolean
leftmost
)
{
// Compute indices of five evenly spaced elements
int
length
=
right
-
left
+
1
;
int
sixth
=
(
right
-
left
+
1
)
/
6
;
int
e1
=
left
+
sixth
;
// Use insertion sort on tiny arrays
int
e5
=
right
-
sixth
;
if
(
length
<
INSERTION_SORT_THRESHOLD
)
{
int
e3
=
(
left
+
right
)
>>>
1
;
// The midpoint
if
(!
leftmost
)
{
int
e4
=
e3
+
sixth
;
/*
int
e2
=
e3
-
sixth
;
* Every element in adjoining part plays the role
* of sentinel, therefore this allows us to avoid
* the j >= left check on each iteration.
*/
for
(
int
j
,
i
=
left
+
1
;
i
<=
right
;
i
++)
{
byte
ai
=
a
[
i
];
for
(
j
=
i
-
1
;
ai
<
a
[
j
];
j
--)
{
// assert j >= left;
a
[
j
+
1
]
=
a
[
j
];
}
a
[
j
+
1
]
=
ai
;
}
}
else
{
/*
* For case of leftmost part traditional (without a sentinel)
* insertion sort, optimized for server JVM, is used.
*/
for
(
int
i
=
left
,
j
=
i
;
i
<
right
;
j
=
++
i
)
{
byte
ai
=
a
[
i
+
1
];
while
(
ai
<
a
[
j
])
{
a
[
j
+
1
]
=
a
[
j
];
if
(
j
--
==
left
)
{
break
;
}
}
a
[
j
+
1
]
=
ai
;
}
}
return
;
}
// Inexpensive approximation of length / 7
int
seventh
=
(
length
>>>
3
)
+
(
length
>>>
6
)
+
1
;
// Sort these elements using a 5-element sorting network
/*
byte
ae1
=
a
[
e1
],
ae2
=
a
[
e2
],
ae3
=
a
[
e3
],
ae4
=
a
[
e4
],
ae5
=
a
[
e5
];
* Sort five evenly spaced elements around (and including) the
* center element in the range. These elements will be used for
* pivot selection as described below. The choice for spacing
* these elements was empirically determined to work well on
* a wide variety of inputs.
*/
int
e3
=
(
left
+
right
)
>>>
1
;
// The midpoint
int
e2
=
e3
-
seventh
;
int
e1
=
e2
-
seventh
;
int
e4
=
e3
+
seventh
;
int
e5
=
e4
+
seventh
;
if
(
ae1
>
ae2
)
{
byte
t
=
ae1
;
ae1
=
ae2
;
ae2
=
t
;
}
// Sort these elements using insertion sort
if
(
ae4
>
ae5
)
{
byte
t
=
ae4
;
ae4
=
ae5
;
ae5
=
t
;
}
if
(
a
[
e2
]
<
a
[
e1
])
{
byte
t
=
a
[
e2
];
a
[
e2
]
=
a
[
e1
];
a
[
e1
]
=
t
;
}
if
(
ae1
>
ae3
)
{
byte
t
=
ae1
;
ae1
=
ae3
;
ae3
=
t
;
}
if
(
ae2
>
ae3
)
{
byte
t
=
ae2
;
ae2
=
ae3
;
ae3
=
t
;
}
if
(
ae1
>
ae4
)
{
byte
t
=
ae1
;
ae1
=
ae4
;
ae4
=
t
;
}
if
(
ae3
>
ae4
)
{
byte
t
=
ae3
;
ae3
=
ae4
;
ae4
=
t
;
}
if
(
ae2
>
ae5
)
{
byte
t
=
ae2
;
ae2
=
ae5
;
ae5
=
t
;
}
if
(
ae2
>
ae3
)
{
byte
t
=
ae2
;
ae2
=
ae3
;
ae3
=
t
;
}
if
(
ae4
>
ae5
)
{
byte
t
=
ae4
;
ae4
=
ae5
;
ae5
=
t
;
}
a
[
e1
]
=
ae1
;
a
[
e3
]
=
ae3
;
a
[
e5
]
=
ae5
;
if
(
a
[
e3
]
<
a
[
e2
])
{
byte
t
=
a
[
e3
];
a
[
e3
]
=
a
[
e2
];
a
[
e2
]
=
t
;
if
(
t
<
a
[
e1
])
{
a
[
e2
]
=
a
[
e1
];
a
[
e1
]
=
t
;
}
}
if
(
a
[
e4
]
<
a
[
e3
])
{
byte
t
=
a
[
e4
];
a
[
e4
]
=
a
[
e3
];
a
[
e3
]
=
t
;
if
(
t
<
a
[
e2
])
{
a
[
e3
]
=
a
[
e2
];
a
[
e2
]
=
t
;
if
(
t
<
a
[
e1
])
{
a
[
e2
]
=
a
[
e1
];
a
[
e1
]
=
t
;
}
}
}
if
(
a
[
e5
]
<
a
[
e4
])
{
byte
t
=
a
[
e5
];
a
[
e5
]
=
a
[
e4
];
a
[
e4
]
=
t
;
if
(
t
<
a
[
e3
])
{
a
[
e4
]
=
a
[
e3
];
a
[
e3
]
=
t
;
if
(
t
<
a
[
e2
])
{
a
[
e3
]
=
a
[
e2
];
a
[
e2
]
=
t
;
if
(
t
<
a
[
e1
])
{
a
[
e2
]
=
a
[
e1
];
a
[
e1
]
=
t
;
}
}
}
}
/*
/*
* Use the second and fourth of the five sorted elements as pivots.
* Use the second and fourth of the five sorted elements as pivots.
* These values are inexpensive approximations of the first and
* These values are inexpensive approximations of the first and
* second terciles of the array. Note that pivot1 <= pivot2.
* second terciles of the array. Note that pivot1 <= pivot2.
*
* The pivots are stored in local variables, and the first and
* the last of the elements to be sorted are moved to the locations
* formerly occupied by the pivots. When partitioning is complete,
* the pivots are swapped back into their final positions, and
* excluded from subsequent sorting.
*/
*/
byte
pivot1
=
a
e2
;
a
[
e2
]
=
a
[
left
];
byte
pivot1
=
a
[
e2
];
byte
pivot2
=
a
e4
;
a
[
e4
]
=
a
[
right
];
byte
pivot2
=
a
[
e4
];
// Pointers
// Pointers
int
less
=
left
+
1
;
// The index of first element of center part
int
less
=
left
;
// The index of the first element of center part
int
great
=
right
-
1
;
// The index before first element of right part
int
great
=
right
;
// The index before the first element of right part
if
(
pivot1
!=
pivot2
)
{
/*
* The first and the last elements to be sorted are moved to the
* locations formerly occupied by the pivots. When partitioning
* is complete, the pivots are swapped back into their final
* positions, and excluded from subsequent sorting.
*/
a
[
e2
]
=
a
[
left
];
a
[
e4
]
=
a
[
right
];
boolean
pivotsDiffer
=
(
pivot1
!=
pivot2
);
/*
* Skip elements, which are less or greater than pivot values.
*/
while
(
a
[++
less
]
<
pivot1
);
while
(
a
[--
great
]
>
pivot2
);
if
(
pivotsDiffer
)
{
/*
/*
* Partitioning:
* Partitioning:
*
*
* left part center part right part
* left part center part right part
* +------------------------------------------------------------+
* +------------------------------------------------------------
--
+
* | < pivot1 | pivot1 <= && <= pivot2 | ? | > pivot2 |
* | < pivot1 | pivot1 <= && <= pivot2 | ? | > pivot2 |
* +------------------------------------------------------------+
* +------------------------------------------------------------
--
+
* ^ ^ ^
* ^ ^ ^
* | | |
* | | |
* less k great
* less k great
...
@@ -1355,16 +1667,14 @@ final class DualPivotQuicksort {
...
@@ -1355,16 +1667,14 @@ final class DualPivotQuicksort {
* pivot1 <= all in [less, k) <= pivot2
* pivot1 <= all in [less, k) <= pivot2
* all in (great, right) > pivot2
* all in (great, right) > pivot2
*
*
* Pointer k is the first index of ?-part
* Pointer k is the first index of ?-part
.
*/
*/
outer:
outer:
for
(
int
k
=
less
;
k
<=
great
;
k
++)
{
for
(
int
k
=
less
;
k
<=
great
;
k
++)
{
byte
ak
=
a
[
k
];
byte
ak
=
a
[
k
];
if
(
ak
<
pivot1
)
{
// Move a[k] to left part
if
(
ak
<
pivot1
)
{
// Move a[k] to left part
if
(
k
!=
less
)
{
a
[
k
]
=
a
[
less
];
a
[
k
]
=
a
[
less
];
a
[
less
]
=
ak
;
a
[
less
]
=
ak
;
}
less
++;
less
++;
}
else
if
(
ak
>
pivot2
)
{
// Move a[k] to right part
}
else
if
(
ak
>
pivot2
)
{
// Move a[k] to right part
while
(
a
[
great
]
>
pivot2
)
{
while
(
a
[
great
]
>
pivot2
)
{
...
@@ -1374,89 +1684,32 @@ final class DualPivotQuicksort {
...
@@ -1374,89 +1684,32 @@ final class DualPivotQuicksort {
}
}
if
(
a
[
great
]
<
pivot1
)
{
if
(
a
[
great
]
<
pivot1
)
{
a
[
k
]
=
a
[
less
];
a
[
k
]
=
a
[
less
];
a
[
less
++
]
=
a
[
great
];
a
[
less
]
=
a
[
great
];
a
[
great
--]
=
ak
;
less
++
;
}
else
{
// pivot1 <= a[great] <= pivot2
}
else
{
// pivot1 <= a[great] <= pivot2
a
[
k
]
=
a
[
great
];
a
[
k
]
=
a
[
great
];
a
[
great
--]
=
ak
;
}
}
}
}
else
{
// Pivots are equal
/*
* Partition degenerates to the traditional 3-way,
* or "Dutch National Flag", partition:
*
* left part center part right part
* +----------------------------------------------+
* | < pivot | == pivot | ? | > pivot |
* +----------------------------------------------+
* ^ ^ ^
* | | |
* less k great
*
* Invariants:
*
* all in (left, less) < pivot
* all in [less, k) == pivot
* all in (great, right) > pivot
*
* Pointer k is the first index of ?-part
*/
for
(
int
k
=
less
;
k
<=
great
;
k
++)
{
byte
ak
=
a
[
k
];
if
(
ak
==
pivot1
)
{
continue
;
}
if
(
ak
<
pivot1
)
{
// Move a[k] to left part
if
(
k
!=
less
)
{
a
[
k
]
=
a
[
less
];
a
[
less
]
=
ak
;
}
}
less
++;
a
[
great
]
=
ak
;
}
else
{
// (a[k] > pivot1) - Move a[k] to right part
/*
* We know that pivot1 == a[e3] == pivot2. Thus, we know
* that great will still be >= k when the following loop
* terminates, even though we don't test for it explicitly.
* In other words, a[e3] acts as a sentinel for great.
*/
while
(
a
[
great
]
>
pivot1
)
{
great
--;
great
--;
}
}
if
(
a
[
great
]
<
pivot1
)
{
a
[
k
]
=
a
[
less
];
a
[
less
++]
=
a
[
great
];
a
[
great
--]
=
ak
;
}
else
{
// a[great] == pivot1
a
[
k
]
=
pivot1
;
a
[
great
--]
=
ak
;
}
}
}
}
}
// Swap pivots into their final positions
// Swap pivots into their final positions
a
[
left
]
=
a
[
less
-
1
];
a
[
less
-
1
]
=
pivot1
;
a
[
left
]
=
a
[
less
-
1
];
a
[
less
-
1
]
=
pivot1
;
a
[
right
]
=
a
[
great
+
1
];
a
[
great
+
1
]
=
pivot2
;
a
[
right
]
=
a
[
great
+
1
];
a
[
great
+
1
]
=
pivot2
;
// Sort left and right parts recursively, excluding known pivot value
s
// Sort left and right parts recursively, excluding known pivot
s
doSort
(
a
,
left
,
less
-
2
);
sort
(
a
,
left
,
less
-
2
,
leftmost
);
doSort
(
a
,
great
+
2
,
right
);
sort
(
a
,
great
+
2
,
right
,
false
);
/*
/*
* If pivot1 == pivot2, all elements from center
* If center part is too large (comprises > 5/7 of the array),
* part are equal and, therefore, already sorted
* swap internal pivot values to ends.
*/
*/
if
(!
pivotsDiffer
)
{
if
(
less
<
e1
&&
e5
<
great
)
{
return
;
}
/*
/*
* If center part is too large (comprises > 2/3 of the array),
* Skip elements, which are equal to pivot values.
* swap internal pivot values to ends
*/
*/
if
(
less
<
e1
&&
great
>
e5
)
{
while
(
a
[
less
]
==
pivot1
)
{
while
(
a
[
less
]
==
pivot1
)
{
less
++;
less
++;
}
}
...
@@ -1481,12 +1734,16 @@ final class DualPivotQuicksort {
...
@@ -1481,12 +1734,16 @@ final class DualPivotQuicksort {
* pivot1 < all in [less, k) < pivot2
* pivot1 < all in [less, k) < pivot2
* all in (great, *) == pivot2
* all in (great, *) == pivot2
*
*
* Pointer k is the first index of ?-part
* Pointer k is the first index of ?-part.
*/
*/
outer:
outer:
for
(
int
k
=
less
;
k
<=
great
;
k
++)
{
for
(
int
k
=
less
;
k
<=
great
;
k
++)
{
byte
ak
=
a
[
k
];
byte
ak
=
a
[
k
];
if
(
ak
==
pivot2
)
{
// Move a[k] to right part
if
(
ak
==
pivot1
)
{
// Move a[k] to left part
a
[
k
]
=
a
[
less
];
a
[
less
]
=
ak
;
less
++;
}
else
if
(
ak
==
pivot2
)
{
// Move a[k] to right part
while
(
a
[
great
]
==
pivot2
)
{
while
(
a
[
great
]
==
pivot2
)
{
if
(
great
--
==
k
)
{
if
(
great
--
==
k
)
{
break
outer
;
break
outer
;
...
@@ -1494,20 +1751,94 @@ final class DualPivotQuicksort {
...
@@ -1494,20 +1751,94 @@ final class DualPivotQuicksort {
}
}
if
(
a
[
great
]
==
pivot1
)
{
if
(
a
[
great
]
==
pivot1
)
{
a
[
k
]
=
a
[
less
];
a
[
k
]
=
a
[
less
];
a
[
less
++]
=
pivot1
;
/*
* Even though a[great] equals to pivot1, the
* assignment a[less] = pivot1 may be incorrect,
* if a[great] and pivot1 are floating-point zeros
* of different signs. Therefore in float and
* double sorting methods we have to use more
* accurate assignment a[less] = a[great].
*/
a
[
less
]
=
pivot1
;
less
++;
}
else
{
// pivot1 < a[great] < pivot2
}
else
{
// pivot1 < a[great] < pivot2
a
[
k
]
=
a
[
great
];
a
[
k
]
=
a
[
great
];
}
}
a
[
great
--]
=
pivot2
;
a
[
great
]
=
ak
;
}
else
if
(
ak
==
pivot1
)
{
// Move a[k] to left part
great
--;
}
}
}
// Sort center part recursively
sort
(
a
,
less
,
great
,
false
);
}
else
{
// Pivots are equal
/*
* Partition degenerates to the traditional 3-way
* (or "Dutch National Flag") schema:
*
* left part center part right part
* +-------------------------------------------------+
* | < pivot | == pivot | ? | > pivot |
* +-------------------------------------------------+
* ^ ^ ^
* | | |
* less k great
*
* Invariants:
*
* all in (left, less) < pivot
* all in [less, k) == pivot
* all in (great, right) > pivot
*
* Pointer k is the first index of ?-part.
*/
for
(
int
k
=
left
;
k
<=
great
;
k
++)
{
if
(
a
[
k
]
==
pivot1
)
{
continue
;
}
byte
ak
=
a
[
k
];
if
(
ak
<
pivot1
)
{
// Move a[k] to left part
a
[
k
]
=
a
[
less
];
a
[
less
]
=
ak
;
less
++;
}
else
{
// a[k] > pivot1 - Move a[k] to right part
/*
* We know that pivot1 == a[e3] == pivot2. Thus, we know
* that great will still be >= k when the following loop
* terminates, even though we don't test for it explicitly.
* In other words, a[e3] acts as a sentinel for great.
*/
while
(
a
[
great
]
>
pivot1
)
{
// assert great > k;
great
--;
}
if
(
a
[
great
]
<
pivot1
)
{
a
[
k
]
=
a
[
less
];
a
[
k
]
=
a
[
less
];
a
[
less
++]
=
pivot1
;
a
[
less
]
=
a
[
great
];
less
++;
}
else
{
// a[great] == pivot1
/*
* Even though a[great] equals to pivot1, the
* assignment a[k] = pivot1 may be incorrect,
* if a[great] and pivot1 are floating-point
* zeros of different signs. Therefore in float
* and double sorting methods we have to use
* more accurate assignment a[k] = a[great].
*/
a
[
k
]
=
pivot1
;
}
}
a
[
great
]
=
ak
;
great
--;
}
}
}
}
// Sort center part recursively, excluding known pivot values
// Sort left and right parts recursively
doSort
(
a
,
less
,
great
);
sort
(
a
,
left
,
less
-
1
,
leftmost
);
sort
(
a
,
great
+
1
,
right
,
false
);
}
}
}
/**
/**
...
@@ -1531,7 +1862,7 @@ final class DualPivotQuicksort {
...
@@ -1531,7 +1862,7 @@ final class DualPivotQuicksort {
* Sorts the specified range of the array into ascending order. The range
* Sorts the specified range of the array into ascending order. The range
* to be sorted extends from the index {@code fromIndex}, inclusive, to
* to be sorted extends from the index {@code fromIndex}, inclusive, to
* the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
* the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
* the range to be sorted is empty and the call is a no-op).
* the range to be sorted is empty
(
and the call is a no-op).
*
*
* <p>The {@code <} relation does not provide a total order on all float
* <p>The {@code <} relation does not provide a total order on all float
* values: {@code -0.0f == 0.0f} is {@code true} and a {@code Float.NaN}
* values: {@code -0.0f == 0.0f} is {@code true} and a {@code Float.NaN}
...
@@ -1565,247 +1896,238 @@ final class DualPivotQuicksort {
...
@@ -1565,247 +1896,238 @@ final class DualPivotQuicksort {
*/
*/
private
static
void
sortNegZeroAndNaN
(
float
[]
a
,
int
left
,
int
right
)
{
private
static
void
sortNegZeroAndNaN
(
float
[]
a
,
int
left
,
int
right
)
{
/*
/*
* Phase 1:
Count negative zeros and move NaNs to end of array
* Phase 1:
Move NaNs to the end of the array.
*/
*/
final
int
NEGATIVE_ZERO
=
Float
.
floatToIntBits
(-
0.0f
);
while
(
left
<=
right
&&
Float
.
isNaN
(
a
[
right
]))
{
int
numNegativeZeros
=
0
;
right
--;
int
n
=
right
;
}
for
(
int
k
=
right
-
1
;
k
>=
left
;
k
--)
{
for
(
int
k
=
left
;
k
<=
n
;
k
++)
{
float
ak
=
a
[
k
];
float
ak
=
a
[
k
];
if
(
ak
==
0.0f
&&
NEGATIVE_ZERO
==
Float
.
floatToIntBits
(
ak
))
{
if
(
ak
!=
ak
)
{
// a[k] is NaN
a
[
k
]
=
0.0f
;
a
[
k
]
=
a
[
right
];
numNegativeZeros
++;
a
[
right
]
=
ak
;
}
else
if
(
ak
!=
ak
)
{
// i.e., ak is NaN
right
--;
a
[
k
--]
=
a
[
n
];
a
[
n
--]
=
Float
.
NaN
;
}
}
}
}
/*
/*
* Phase 2: Sort everything except NaNs (which are already in place)
* Phase 2: Sort everything except NaNs (which are already in place)
.
*/
*/
doSort
(
a
,
left
,
n
);
sort
(
a
,
left
,
right
,
true
);
/*
/*
* Phase 3:
Turn positive zeros back into negative zeros as appropriate
* Phase 3:
Place negative zeros before positive zeros.
*/
*/
if
(
numNegativeZeros
==
0
)
{
int
hi
=
right
;
return
;
}
// Find first zero element
/*
int
zeroIndex
=
findAnyZero
(
a
,
left
,
n
);
* Search first zero, or first positive, or last negative element.
*/
while
(
left
<
hi
)
{
int
middle
=
(
left
+
hi
)
>>>
1
;
float
middleValue
=
a
[
middle
];
for
(
int
i
=
zeroIndex
-
1
;
i
>=
left
&&
a
[
i
]
==
0.0f
;
i
--)
{
if
(
middleValue
<
0.0f
)
{
zeroIndex
=
i
;
left
=
middle
+
1
;
}
else
{
hi
=
middle
;
}
}
// Turn the right number of positive zeros back into negative zeros
for
(
int
i
=
zeroIndex
,
m
=
zeroIndex
+
numNegativeZeros
;
i
<
m
;
i
++)
{
a
[
i
]
=
-
0.0f
;
}
}
/*
* Skip the last negative value (if any) or all leading negative zeros.
*/
while
(
left
<=
right
&&
Float
.
floatToRawIntBits
(
a
[
left
])
<
0
)
{
left
++;
}
}
/**
/*
* Returns the index of some zero element in the specified range via
* Move negative zeros to the beginning of the sub-range.
* binary search. The range is assumed to be sorted, and must contain
*
* at least one zero.
* Partitioning:
*
* +---------------------------------------------------+
* | < 0.0 | -0.0 | 0.0 | ? ( >= 0.0 ) |
* +---------------------------------------------------+
* ^ ^ ^
* | | |
* left p k
*
* Invariants:
*
*
* @param a the array to be searched
* all in (*, left) < 0.0
* @param low the index of the first element, inclusive, to be searched
* all in [left, p) == -0.0
* @param high the index of the last element, inclusive, to be searched
* all in [p, k) == 0.0
* all in [k, right] >= 0.0
*
* Pointer k is the first index of ?-part.
*/
*/
private
static
int
findAnyZero
(
float
[]
a
,
int
low
,
int
high
)
{
for
(
int
k
=
left
+
1
,
p
=
left
;
k
<=
right
;
k
++)
{
while
(
true
)
{
float
ak
=
a
[
k
];
int
middle
=
(
low
+
high
)
>>>
1
;
if
(
ak
!=
0.0f
)
{
float
middleValue
=
a
[
middle
];
break
;
}
if
(
middleValue
<
0.0f
)
{
if
(
Float
.
floatToRawIntBits
(
ak
)
<
0
)
{
// ak is -0.0f
low
=
middle
+
1
;
a
[
k
]
=
0.0f
;
}
else
if
(
middleValue
>
0.0f
)
{
a
[
p
++]
=
-
0.0f
;
high
=
middle
-
1
;
}
else
{
// middleValue == 0.0f
return
middle
;
}
}
}
}
}
}
/**
/**
* Sorts the specified range of the array into ascending order
. This
* Sorts the specified range of the array into ascending order
by the
*
method differs from the public {@code sort} method in three ways:
*
Dual-Pivot Quicksort algorithm. This method differs from the public
* {@code
right} index is inclusive, it does no range checking on
* {@code
sort} method in that the {@code right} index is inclusive,
*
{@code left} or {@code right}, and it does not handle negative
*
it does no range checking on {@code left} or {@code right}, and has
*
zeros or NaNs in the array
.
*
boolean flag whether insertion sort with sentinel is used or not
.
*
*
* @param a the array to be sorted
, which must not contain -0.0f or NaN
* @param a the array to be sorted
* @param left the index of the first element, inclusive, to be sorted
* @param left the index of the first element, inclusive, to be sorted
* @param right the index of the last element, inclusive, to be sorted
* @param right the index of the last element, inclusive, to be sorted
* @param leftmost indicates if the part is the most left in the range
*/
*/
private
static
void
doSort
(
float
[]
a
,
int
left
,
int
right
)
{
private
static
void
sort
(
float
[]
a
,
int
left
,
int
right
,
boolean
leftmost
)
{
int
length
=
right
-
left
+
1
;
// Use insertion sort on tiny arrays
// Use insertion sort on tiny arrays
if
(
right
-
left
+
1
<
INSERTION_SORT_THRESHOLD
)
{
if
(
length
<
INSERTION_SORT_THRESHOLD
)
{
for
(
int
i
=
left
+
1
;
i
<=
right
;
i
++)
{
if
(!
leftmost
)
{
/*
* Every element in adjoining part plays the role
* of sentinel, therefore this allows us to avoid
* the j >= left check on each iteration.
*/
for
(
int
j
,
i
=
left
+
1
;
i
<=
right
;
i
++)
{
float
ai
=
a
[
i
];
float
ai
=
a
[
i
];
int
j
;
for
(
j
=
i
-
1
;
ai
<
a
[
j
];
j
--)
{
for
(
j
=
i
-
1
;
j
>=
left
&&
ai
<
a
[
j
];
j
--)
{
// assert j >= left;
a
[
j
+
1
]
=
a
[
j
];
a
[
j
+
1
]
=
a
[
j
];
}
}
a
[
j
+
1
]
=
ai
;
a
[
j
+
1
]
=
ai
;
}
}
}
else
{
// Use Dual-Pivot Quicksort on large arrays
}
else
{
dualPivotQuicksort
(
a
,
left
,
right
);
/*
* For case of leftmost part traditional (without a sentinel)
* insertion sort, optimized for server JVM, is used.
*/
for
(
int
i
=
left
,
j
=
i
;
i
<
right
;
j
=
++
i
)
{
float
ai
=
a
[
i
+
1
];
while
(
ai
<
a
[
j
])
{
a
[
j
+
1
]
=
a
[
j
];
if
(
j
--
==
left
)
{
break
;
}
}
}
a
[
j
+
1
]
=
ai
;
}
}
return
;
}
}
/**
// Inexpensive approximation of length / 7
* Sorts the specified range of the array into ascending order by the
int
seventh
=
(
length
>>>
3
)
+
(
length
>>>
6
)
+
1
;
* Dual-Pivot Quicksort algorithm.
*
/*
* @param a the array to be sorted
* Sort five evenly spaced elements around (and including) the
* @param left the index of the first element, inclusive, to be sorted
* center element in the range. These elements will be used for
* @param right the index of the last element, inclusive, to be sorted
* pivot selection as described below. The choice for spacing
* these elements was empirically determined to work well on
* a wide variety of inputs.
*/
*/
private
static
void
dualPivotQuicksort
(
float
[]
a
,
int
left
,
int
right
)
{
// Compute indices of five evenly spaced elements
int
sixth
=
(
right
-
left
+
1
)
/
6
;
int
e1
=
left
+
sixth
;
int
e5
=
right
-
sixth
;
int
e3
=
(
left
+
right
)
>>>
1
;
// The midpoint
int
e3
=
(
left
+
right
)
>>>
1
;
// The midpoint
int
e4
=
e3
+
sixth
;
int
e2
=
e3
-
seventh
;
int
e2
=
e3
-
sixth
;
int
e1
=
e2
-
seventh
;
int
e4
=
e3
+
seventh
;
int
e5
=
e4
+
seventh
;
// Sort these elements using
a 5-element sorting network
// Sort these elements using
insertion sort
float
ae1
=
a
[
e1
],
ae2
=
a
[
e2
],
ae3
=
a
[
e3
],
ae4
=
a
[
e4
],
ae5
=
a
[
e5
];
if
(
a
[
e2
]
<
a
[
e1
])
{
float
t
=
a
[
e2
];
a
[
e2
]
=
a
[
e1
];
a
[
e1
]
=
t
;
}
if
(
ae1
>
ae2
)
{
float
t
=
ae1
;
ae1
=
ae2
;
ae2
=
t
;
}
if
(
a
[
e3
]
<
a
[
e2
])
{
float
t
=
a
[
e3
];
a
[
e3
]
=
a
[
e2
];
a
[
e2
]
=
t
;
if
(
ae4
>
ae5
)
{
float
t
=
ae4
;
ae4
=
ae5
;
ae5
=
t
;
}
if
(
t
<
a
[
e1
])
{
a
[
e2
]
=
a
[
e1
];
a
[
e1
]
=
t
;
}
if
(
ae1
>
ae3
)
{
float
t
=
ae1
;
ae1
=
ae3
;
ae3
=
t
;
}
}
if
(
ae2
>
ae3
)
{
float
t
=
ae2
;
ae2
=
ae3
;
ae3
=
t
;
}
if
(
a
[
e4
]
<
a
[
e3
])
{
float
t
=
a
[
e4
];
a
[
e4
]
=
a
[
e3
];
a
[
e3
]
=
t
;
if
(
ae1
>
ae4
)
{
float
t
=
ae1
;
ae1
=
ae4
;
ae4
=
t
;
}
if
(
t
<
a
[
e2
])
{
a
[
e3
]
=
a
[
e2
];
a
[
e2
]
=
t
;
if
(
ae3
>
ae4
)
{
float
t
=
ae3
;
ae3
=
ae4
;
ae4
=
t
;
}
if
(
t
<
a
[
e1
])
{
a
[
e2
]
=
a
[
e1
];
a
[
e1
]
=
t
;
}
if
(
ae2
>
ae5
)
{
float
t
=
ae2
;
ae2
=
ae5
;
ae5
=
t
;
}
}
if
(
ae2
>
ae3
)
{
float
t
=
ae2
;
ae2
=
ae3
;
ae3
=
t
;
}
}
if
(
ae4
>
ae5
)
{
float
t
=
ae4
;
ae4
=
ae5
;
ae5
=
t
;
}
if
(
a
[
e5
]
<
a
[
e4
])
{
float
t
=
a
[
e5
];
a
[
e5
]
=
a
[
e4
];
a
[
e4
]
=
t
;
if
(
t
<
a
[
e3
])
{
a
[
e4
]
=
a
[
e3
];
a
[
e3
]
=
t
;
a
[
e1
]
=
ae1
;
a
[
e3
]
=
ae3
;
a
[
e5
]
=
ae5
;
if
(
t
<
a
[
e2
])
{
a
[
e3
]
=
a
[
e2
];
a
[
e2
]
=
t
;
if
(
t
<
a
[
e1
])
{
a
[
e2
]
=
a
[
e1
];
a
[
e1
]
=
t
;
}
}
}
}
/*
/*
* Use the second and fourth of the five sorted elements as pivots.
* Use the second and fourth of the five sorted elements as pivots.
* These values are inexpensive approximations of the first and
* These values are inexpensive approximations of the first and
* second terciles of the array. Note that pivot1 <= pivot2.
* second terciles of the array. Note that pivot1 <= pivot2.
*
* The pivots are stored in local variables, and the first and
* the last of the elements to be sorted are moved to the locations
* formerly occupied by the pivots. When partitioning is complete,
* the pivots are swapped back into their final positions, and
* excluded from subsequent sorting.
*/
*/
float
pivot1
=
a
e2
;
a
[
e2
]
=
a
[
left
];
float
pivot1
=
a
[
e2
];
float
pivot2
=
a
e4
;
a
[
e4
]
=
a
[
right
];
float
pivot2
=
a
[
e4
];
// Pointers
// Pointers
int
less
=
left
+
1
;
// The index of first element of center part
int
less
=
left
;
// The index of the first element of center part
int
great
=
right
-
1
;
// The index before first element of right part
int
great
=
right
;
// The index before the first element of right part
boolean
pivotsDiffer
=
(
pivot1
!=
pivot2
);
if
(
pivot1
!=
pivot2
)
{
/*
if
(
pivotsDiffer
)
{
* The first and the last elements to be sorted are moved to the
/*
* locations formerly occupied by the pivots. When partitioning
* Partitioning:
* is complete, the pivots are swapped back into their final
*
* positions, and excluded from subsequent sorting.
* left part center part right part
*/
* +------------------------------------------------------------+
a
[
e2
]
=
a
[
left
];
* | < pivot1 | pivot1 <= && <= pivot2 | ? | > pivot2 |
a
[
e4
]
=
a
[
right
];
* +------------------------------------------------------------+
* ^ ^ ^
* | | |
* less k great
*
* Invariants:
*
* all in (left, less) < pivot1
* pivot1 <= all in [less, k) <= pivot2
* all in (great, right) > pivot2
*
* Pointer k is the first index of ?-part
*/
outer:
for
(
int
k
=
less
;
k
<=
great
;
k
++)
{
float
ak
=
a
[
k
];
if
(
ak
<
pivot1
)
{
// Move a[k] to left part
if
(
k
!=
less
)
{
a
[
k
]
=
a
[
less
];
a
[
less
]
=
ak
;
}
less
++;
}
else
if
(
ak
>
pivot2
)
{
// Move a[k] to right part
while
(
a
[
great
]
>
pivot2
)
{
if
(
great
--
==
k
)
{
break
outer
;
}
}
if
(
a
[
great
]
<
pivot1
)
{
a
[
k
]
=
a
[
less
];
a
[
less
++]
=
a
[
great
];
a
[
great
--]
=
ak
;
}
else
{
// pivot1 <= a[great] <= pivot2
a
[
k
]
=
a
[
great
];
a
[
great
--]
=
ak
;
}
}
}
}
else
{
// Pivots are equal
/*
/*
* Partition degenerates to the traditional 3-way,
* Skip elements, which are less or greater than pivot values.
* or "Dutch National Flag", partition:
*/
while
(
a
[++
less
]
<
pivot1
);
while
(
a
[--
great
]
>
pivot2
);
/*
* Partitioning:
*
*
* left part center part right part
* left part center part right part
* +----------------------------------------------+
* +----------------------------------------------
----------------
+
* | < pivot
| == pivot | ? | > pivot
|
* | < pivot
1 | pivot1 <= && <= pivot2 | ? | > pivot2
|
* +----------------------------------------------+
* +----------------------------------------------
----------------
+
* ^ ^ ^
* ^ ^ ^
* | | |
* | | |
* less k great
* less k great
*
*
* Invariants:
* Invariants:
*
*
*
all in (left, less) < pivot
*
all in (left, less) < pivot1
*
all in [less, k) == pivot
*
pivot1 <= all in [less, k) <= pivot2
*
all in (great, right) > pivot
*
all in (great, right) > pivot2
*
*
* Pointer k is the first index of ?-part
* Pointer k is the first index of ?-part
.
*/
*/
outer:
for
(
int
k
=
less
;
k
<=
great
;
k
++)
{
for
(
int
k
=
less
;
k
<=
great
;
k
++)
{
float
ak
=
a
[
k
];
float
ak
=
a
[
k
];
if
(
ak
==
pivot1
)
{
continue
;
}
if
(
ak
<
pivot1
)
{
// Move a[k] to left part
if
(
ak
<
pivot1
)
{
// Move a[k] to left part
if
(
k
!=
less
)
{
a
[
k
]
=
a
[
less
];
a
[
k
]
=
a
[
less
];
a
[
less
]
=
ak
;
a
[
less
]
=
ak
;
}
less
++;
less
++;
}
else
{
// (a[k] > pivot1) - Move a[k] to right part
}
else
if
(
ak
>
pivot2
)
{
// Move a[k] to right part
/*
while
(
a
[
great
]
>
pivot2
)
{
* We know that pivot1 == a[e3] == pivot2. Thus, we know
if
(
great
--
==
k
)
{
* that great will still be >= k when the following loop
break
outer
;
* terminates, even though we don't test for it explicitly.
}
* In other words, a[e3] acts as a sentinel for great.
*/
while
(
a
[
great
]
>
pivot1
)
{
great
--;
}
}
if
(
a
[
great
]
<
pivot1
)
{
if
(
a
[
great
]
<
pivot1
)
{
a
[
k
]
=
a
[
less
];
a
[
k
]
=
a
[
less
];
a
[
less
++]
=
a
[
great
];
a
[
less
]
=
a
[
great
];
a
[
great
--]
=
ak
;
less
++;
}
else
{
// a[great] == pivot1
}
else
{
// pivot1 <= a[great] <= pivot2
a
[
k
]
=
pivot1
;
a
[
k
]
=
a
[
great
];
a
[
great
--]
=
ak
;
}
}
}
a
[
great
]
=
ak
;
great
--;
}
}
}
}
...
@@ -1813,23 +2135,18 @@ final class DualPivotQuicksort {
...
@@ -1813,23 +2135,18 @@ final class DualPivotQuicksort {
a
[
left
]
=
a
[
less
-
1
];
a
[
less
-
1
]
=
pivot1
;
a
[
left
]
=
a
[
less
-
1
];
a
[
less
-
1
]
=
pivot1
;
a
[
right
]
=
a
[
great
+
1
];
a
[
great
+
1
]
=
pivot2
;
a
[
right
]
=
a
[
great
+
1
];
a
[
great
+
1
]
=
pivot2
;
// Sort left and right parts recursively, excluding known pivot value
s
// Sort left and right parts recursively, excluding known pivot
s
doSort
(
a
,
left
,
less
-
2
);
sort
(
a
,
left
,
less
-
2
,
leftmost
);
doSort
(
a
,
great
+
2
,
right
);
sort
(
a
,
great
+
2
,
right
,
false
);
/*
/*
* If pivot1 == pivot2, all elements from center
* If center part is too large (comprises > 5/7 of the array),
* part are equal and, therefore, already sorted
* swap internal pivot values to ends.
*/
*/
if
(!
pivotsDiffer
)
{
if
(
less
<
e1
&&
e5
<
great
)
{
return
;
}
/*
/*
* If center part is too large (comprises > 2/3 of the array),
* Skip elements, which are equal to pivot values.
* swap internal pivot values to ends
*/
*/
if
(
less
<
e1
&&
great
>
e5
)
{
while
(
a
[
less
]
==
pivot1
)
{
while
(
a
[
less
]
==
pivot1
)
{
less
++;
less
++;
}
}
...
@@ -1854,12 +2171,16 @@ final class DualPivotQuicksort {
...
@@ -1854,12 +2171,16 @@ final class DualPivotQuicksort {
* pivot1 < all in [less, k) < pivot2
* pivot1 < all in [less, k) < pivot2
* all in (great, *) == pivot2
* all in (great, *) == pivot2
*
*
* Pointer k is the first index of ?-part
* Pointer k is the first index of ?-part.
*/
*/
outer:
outer:
for
(
int
k
=
less
;
k
<=
great
;
k
++)
{
for
(
int
k
=
less
;
k
<=
great
;
k
++)
{
float
ak
=
a
[
k
];
float
ak
=
a
[
k
];
if
(
ak
==
pivot2
)
{
// Move a[k] to right part
if
(
ak
==
pivot1
)
{
// Move a[k] to left part
a
[
k
]
=
a
[
less
];
a
[
less
]
=
ak
;
less
++;
}
else
if
(
ak
==
pivot2
)
{
// Move a[k] to right part
while
(
a
[
great
]
==
pivot2
)
{
while
(
a
[
great
]
==
pivot2
)
{
if
(
great
--
==
k
)
{
if
(
great
--
==
k
)
{
break
outer
;
break
outer
;
...
@@ -1867,20 +2188,94 @@ final class DualPivotQuicksort {
...
@@ -1867,20 +2188,94 @@ final class DualPivotQuicksort {
}
}
if
(
a
[
great
]
==
pivot1
)
{
if
(
a
[
great
]
==
pivot1
)
{
a
[
k
]
=
a
[
less
];
a
[
k
]
=
a
[
less
];
a
[
less
++]
=
pivot1
;
/*
* Even though a[great] equals to pivot1, the
* assignment a[less] = pivot1 may be incorrect,
* if a[great] and pivot1 are floating-point zeros
* of different signs. Therefore in float and
* double sorting methods we have to use more
* accurate assignment a[less] = a[great].
*/
a
[
less
]
=
a
[
great
];
less
++;
}
else
{
// pivot1 < a[great] < pivot2
}
else
{
// pivot1 < a[great] < pivot2
a
[
k
]
=
a
[
great
];
a
[
k
]
=
a
[
great
];
}
}
a
[
great
--]
=
pivot2
;
a
[
great
]
=
ak
;
}
else
if
(
ak
==
pivot1
)
{
// Move a[k] to left part
great
--;
}
}
}
// Sort center part recursively
sort
(
a
,
less
,
great
,
false
);
}
else
{
// Pivots are equal
/*
* Partition degenerates to the traditional 3-way
* (or "Dutch National Flag") schema:
*
* left part center part right part
* +-------------------------------------------------+
* | < pivot | == pivot | ? | > pivot |
* +-------------------------------------------------+
* ^ ^ ^
* | | |
* less k great
*
* Invariants:
*
* all in (left, less) < pivot
* all in [less, k) == pivot
* all in (great, right) > pivot
*
* Pointer k is the first index of ?-part.
*/
for
(
int
k
=
left
;
k
<=
great
;
k
++)
{
if
(
a
[
k
]
==
pivot1
)
{
continue
;
}
float
ak
=
a
[
k
];
if
(
ak
<
pivot1
)
{
// Move a[k] to left part
a
[
k
]
=
a
[
less
];
a
[
less
]
=
ak
;
less
++;
}
else
{
// a[k] > pivot1 - Move a[k] to right part
/*
* We know that pivot1 == a[e3] == pivot2. Thus, we know
* that great will still be >= k when the following loop
* terminates, even though we don't test for it explicitly.
* In other words, a[e3] acts as a sentinel for great.
*/
while
(
a
[
great
]
>
pivot1
)
{
// assert great > k;
great
--;
}
if
(
a
[
great
]
<
pivot1
)
{
a
[
k
]
=
a
[
less
];
a
[
k
]
=
a
[
less
];
a
[
less
++]
=
pivot1
;
a
[
less
]
=
a
[
great
];
less
++;
}
else
{
// a[great] == pivot1
/*
* Even though a[great] equals to pivot1, the
* assignment a[k] = pivot1 may be incorrect,
* if a[great] and pivot1 are floating-point
* zeros of different signs. Therefore in float
* and double sorting methods we have to use
* more accurate assignment a[k] = a[great].
*/
a
[
k
]
=
a
[
great
];
}
}
a
[
great
]
=
ak
;
great
--;
}
}
}
}
// Sort center part recursively, excluding known pivot values
// Sort left and right parts recursively
doSort
(
a
,
less
,
great
);
sort
(
a
,
left
,
less
-
1
,
leftmost
);
sort
(
a
,
great
+
1
,
right
,
false
);
}
}
}
/**
/**
...
@@ -1938,159 +2333,204 @@ final class DualPivotQuicksort {
...
@@ -1938,159 +2333,204 @@ final class DualPivotQuicksort {
*/
*/
private
static
void
sortNegZeroAndNaN
(
double
[]
a
,
int
left
,
int
right
)
{
private
static
void
sortNegZeroAndNaN
(
double
[]
a
,
int
left
,
int
right
)
{
/*
/*
* Phase 1:
Count negative zeros and move NaNs to end of array
* Phase 1:
Move NaNs to the end of the array.
*/
*/
final
long
NEGATIVE_ZERO
=
Double
.
doubleToLongBits
(-
0.0d
);
while
(
left
<=
right
&&
Double
.
isNaN
(
a
[
right
]))
{
int
numNegativeZeros
=
0
;
right
--;
int
n
=
right
;
}
for
(
int
k
=
right
-
1
;
k
>=
left
;
k
--)
{
for
(
int
k
=
left
;
k
<=
n
;
k
++)
{
double
ak
=
a
[
k
];
double
ak
=
a
[
k
];
if
(
ak
==
0.0d
&&
NEGATIVE_ZERO
==
Double
.
doubleToLongBits
(
ak
))
{
if
(
ak
!=
ak
)
{
// a[k] is NaN
a
[
k
]
=
0.0d
;
a
[
k
]
=
a
[
right
];
numNegativeZeros
++;
a
[
right
]
=
ak
;
}
else
if
(
ak
!=
ak
)
{
// i.e., ak is NaN
right
--;
a
[
k
--]
=
a
[
n
];
a
[
n
--]
=
Double
.
NaN
;
}
}
}
}
/*
/*
* Phase 2: Sort everything except NaNs (which are already in place)
* Phase 2: Sort everything except NaNs (which are already in place)
.
*/
*/
doSort
(
a
,
left
,
n
);
sort
(
a
,
left
,
right
,
true
);
/*
/*
* Phase 3:
Turn positive zeros back into negative zeros as appropriate
* Phase 3:
Place negative zeros before positive zeros.
*/
*/
if
(
numNegativeZeros
==
0
)
{
int
hi
=
right
;
return
;
}
// Find first zero element
/*
int
zeroIndex
=
findAnyZero
(
a
,
left
,
n
);
* Search first zero, or first positive, or last negative element.
*/
while
(
left
<
hi
)
{
int
middle
=
(
left
+
hi
)
>>>
1
;
double
middleValue
=
a
[
middle
];
for
(
int
i
=
zeroIndex
-
1
;
i
>=
left
&&
a
[
i
]
==
0.0d
;
i
--)
{
if
(
middleValue
<
0.0d
)
{
zeroIndex
=
i
;
left
=
middle
+
1
;
}
else
{
hi
=
middle
;
}
}
// Turn the right number of positive zeros back into negative zeros
for
(
int
i
=
zeroIndex
,
m
=
zeroIndex
+
numNegativeZeros
;
i
<
m
;
i
++)
{
a
[
i
]
=
-
0.0d
;
}
}
/*
* Skip the last negative value (if any) or all leading negative zeros.
*/
while
(
left
<=
right
&&
Double
.
doubleToRawLongBits
(
a
[
left
])
<
0
)
{
left
++;
}
}
/*
*
/
*
* Returns the index of some zero element in the specified range via
* Move negative zeros to the beginning of the sub-range.
* binary search. The range is assumed to be sorted, and must contain
*
* at least one zero.
* Partitioning:
*
*
* @param a the array to be searched
* +---------------------------------------------------+
* @param low the index of the first element, inclusive, to be searched
* | < 0.0 | -0.0 | 0.0 | ? ( >= 0.0 ) |
* @param high the index of the last element, inclusive, to be searched
* +---------------------------------------------------+
* ^ ^ ^
* | | |
* left p k
*
* Invariants:
*
* all in (*, left) < 0.0
* all in [left, p) == -0.0
* all in [p, k) == 0.0
* all in [k, right] >= 0.0
*
* Pointer k is the first index of ?-part.
*/
*/
private
static
int
findAnyZero
(
double
[]
a
,
int
low
,
int
high
)
{
for
(
int
k
=
left
+
1
,
p
=
left
;
k
<=
right
;
k
++)
{
while
(
true
)
{
double
ak
=
a
[
k
];
int
middle
=
(
low
+
high
)
>>>
1
;
if
(
ak
!=
0.0d
)
{
double
middleValue
=
a
[
middle
];
break
;
}
if
(
middleValue
<
0.0d
)
{
if
(
Double
.
doubleToRawLongBits
(
ak
)
<
0
)
{
// ak is -0.0d
low
=
middle
+
1
;
a
[
k
]
=
0.0d
;
}
else
if
(
middleValue
>
0.0d
)
{
a
[
p
++]
=
-
0.0d
;
high
=
middle
-
1
;
}
else
{
// middleValue == 0.0d
return
middle
;
}
}
}
}
}
}
/**
/**
* Sorts the specified range of the array into ascending order
. This
* Sorts the specified range of the array into ascending order
by the
*
method differs from the public {@code sort} method in three ways:
*
Dual-Pivot Quicksort algorithm. This method differs from the public
* {@code
right} index is inclusive, it does no range checking on
* {@code
sort} method in that the {@code right} index is inclusive,
*
{@code left} or {@code right}, and it does not handle negative
*
it does no range checking on {@code left} or {@code right}, and has
*
zeros or NaNs in the array
.
*
boolean flag whether insertion sort with sentinel is used or not
.
*
*
* @param a the array to be sorted
, which must not contain -0.0d and NaN
* @param a the array to be sorted
* @param left the index of the first element, inclusive, to be sorted
* @param left the index of the first element, inclusive, to be sorted
* @param right the index of the last element, inclusive, to be sorted
* @param right the index of the last element, inclusive, to be sorted
* @param leftmost indicates if the part is the most left in the range
*/
*/
private
static
void
doSort
(
double
[]
a
,
int
left
,
int
right
)
{
private
static
void
sort
(
double
[]
a
,
int
left
,
int
right
,
boolean
leftmost
)
{
int
length
=
right
-
left
+
1
;
// Use insertion sort on tiny arrays
// Use insertion sort on tiny arrays
if
(
right
-
left
+
1
<
INSERTION_SORT_THRESHOLD
)
{
if
(
length
<
INSERTION_SORT_THRESHOLD
)
{
for
(
int
i
=
left
+
1
;
i
<=
right
;
i
++)
{
if
(!
leftmost
)
{
/*
* Every element in adjoining part plays the role
* of sentinel, therefore this allows us to avoid
* the j >= left check on each iteration.
*/
for
(
int
j
,
i
=
left
+
1
;
i
<=
right
;
i
++)
{
double
ai
=
a
[
i
];
double
ai
=
a
[
i
];
int
j
;
for
(
j
=
i
-
1
;
ai
<
a
[
j
];
j
--)
{
for
(
j
=
i
-
1
;
j
>=
left
&&
ai
<
a
[
j
];
j
--)
{
// assert j >= left;
a
[
j
+
1
]
=
a
[
j
];
}
a
[
j
+
1
]
=
ai
;
}
}
else
{
/*
* For case of leftmost part traditional (without a sentinel)
* insertion sort, optimized for server JVM, is used.
*/
for
(
int
i
=
left
,
j
=
i
;
i
<
right
;
j
=
++
i
)
{
double
ai
=
a
[
i
+
1
];
while
(
ai
<
a
[
j
])
{
a
[
j
+
1
]
=
a
[
j
];
a
[
j
+
1
]
=
a
[
j
];
if
(
j
--
==
left
)
{
break
;
}
}
}
a
[
j
+
1
]
=
ai
;
a
[
j
+
1
]
=
ai
;
}
}
}
else
{
// Use Dual-Pivot Quicksort on large arrays
dualPivotQuicksort
(
a
,
left
,
right
);
}
}
return
;
}
}
/**
// Inexpensive approximation of length / 7
* Sorts the specified range of the array into ascending order by the
int
seventh
=
(
length
>>>
3
)
+
(
length
>>>
6
)
+
1
;
* Dual-Pivot Quicksort algorithm.
*
/*
* @param a the array to be sorted
* Sort five evenly spaced elements around (and including) the
* @param left the index of the first element, inclusive, to be sorted
* center element in the range. These elements will be used for
* @param right the index of the last element, inclusive, to be sorted
* pivot selection as described below. The choice for spacing
* these elements was empirically determined to work well on
* a wide variety of inputs.
*/
*/
private
static
void
dualPivotQuicksort
(
double
[]
a
,
int
left
,
int
right
)
{
// Compute indices of five evenly spaced elements
int
sixth
=
(
right
-
left
+
1
)
/
6
;
int
e1
=
left
+
sixth
;
int
e5
=
right
-
sixth
;
int
e3
=
(
left
+
right
)
>>>
1
;
// The midpoint
int
e3
=
(
left
+
right
)
>>>
1
;
// The midpoint
int
e4
=
e3
+
sixth
;
int
e2
=
e3
-
seventh
;
int
e2
=
e3
-
sixth
;
int
e1
=
e2
-
seventh
;
int
e4
=
e3
+
seventh
;
// Sort these elements using a 5-element sorting network
int
e5
=
e4
+
seventh
;
double
ae1
=
a
[
e1
],
ae2
=
a
[
e2
],
ae3
=
a
[
e3
],
ae4
=
a
[
e4
],
ae5
=
a
[
e5
];
if
(
ae1
>
ae2
)
{
double
t
=
ae1
;
ae1
=
ae2
;
ae2
=
t
;
}
// Sort these elements using insertion sort
if
(
ae4
>
ae5
)
{
double
t
=
ae4
;
ae4
=
ae5
;
ae5
=
t
;
}
if
(
a
[
e2
]
<
a
[
e1
])
{
double
t
=
a
[
e2
];
a
[
e2
]
=
a
[
e1
];
a
[
e1
]
=
t
;
}
if
(
ae1
>
ae3
)
{
double
t
=
ae1
;
ae1
=
ae3
;
ae3
=
t
;
}
if
(
ae2
>
ae3
)
{
double
t
=
ae2
;
ae2
=
ae3
;
ae3
=
t
;
}
if
(
ae1
>
ae4
)
{
double
t
=
ae1
;
ae1
=
ae4
;
ae4
=
t
;
}
if
(
ae3
>
ae4
)
{
double
t
=
ae3
;
ae3
=
ae4
;
ae4
=
t
;
}
if
(
ae2
>
ae5
)
{
double
t
=
ae2
;
ae2
=
ae5
;
ae5
=
t
;
}
if
(
ae2
>
ae3
)
{
double
t
=
ae2
;
ae2
=
ae3
;
ae3
=
t
;
}
if
(
ae4
>
ae5
)
{
double
t
=
ae4
;
ae4
=
ae5
;
ae5
=
t
;
}
a
[
e1
]
=
ae1
;
a
[
e3
]
=
ae3
;
a
[
e5
]
=
ae5
;
if
(
a
[
e3
]
<
a
[
e2
])
{
double
t
=
a
[
e3
];
a
[
e3
]
=
a
[
e2
];
a
[
e2
]
=
t
;
if
(
t
<
a
[
e1
])
{
a
[
e2
]
=
a
[
e1
];
a
[
e1
]
=
t
;
}
}
if
(
a
[
e4
]
<
a
[
e3
])
{
double
t
=
a
[
e4
];
a
[
e4
]
=
a
[
e3
];
a
[
e3
]
=
t
;
if
(
t
<
a
[
e2
])
{
a
[
e3
]
=
a
[
e2
];
a
[
e2
]
=
t
;
if
(
t
<
a
[
e1
])
{
a
[
e2
]
=
a
[
e1
];
a
[
e1
]
=
t
;
}
}
}
if
(
a
[
e5
]
<
a
[
e4
])
{
double
t
=
a
[
e5
];
a
[
e5
]
=
a
[
e4
];
a
[
e4
]
=
t
;
if
(
t
<
a
[
e3
])
{
a
[
e4
]
=
a
[
e3
];
a
[
e3
]
=
t
;
if
(
t
<
a
[
e2
])
{
a
[
e3
]
=
a
[
e2
];
a
[
e2
]
=
t
;
if
(
t
<
a
[
e1
])
{
a
[
e2
]
=
a
[
e1
];
a
[
e1
]
=
t
;
}
}
}
}
/*
/*
* Use the second and fourth of the five sorted elements as pivots.
* Use the second and fourth of the five sorted elements as pivots.
* These values are inexpensive approximations of the first and
* These values are inexpensive approximations of the first and
* second terciles of the array. Note that pivot1 <= pivot2.
* second terciles of the array. Note that pivot1 <= pivot2.
*
* The pivots are stored in local variables, and the first and
* the last of the elements to be sorted are moved to the locations
* formerly occupied by the pivots. When partitioning is complete,
* the pivots are swapped back into their final positions, and
* excluded from subsequent sorting.
*/
*/
double
pivot1
=
a
e2
;
a
[
e2
]
=
a
[
left
];
double
pivot1
=
a
[
e2
];
double
pivot2
=
a
e4
;
a
[
e4
]
=
a
[
right
];
double
pivot2
=
a
[
e4
];
// Pointers
// Pointers
int
less
=
left
+
1
;
// The index of first element of center part
int
less
=
left
;
// The index of the first element of center part
int
great
=
right
-
1
;
// The index before first element of right part
int
great
=
right
;
// The index before the first element of right part
if
(
pivot1
!=
pivot2
)
{
/*
* The first and the last elements to be sorted are moved to the
* locations formerly occupied by the pivots. When partitioning
* is complete, the pivots are swapped back into their final
* positions, and excluded from subsequent sorting.
*/
a
[
e2
]
=
a
[
left
];
a
[
e4
]
=
a
[
right
];
boolean
pivotsDiffer
=
(
pivot1
!=
pivot2
);
/*
* Skip elements, which are less or greater than pivot values.
*/
while
(
a
[++
less
]
<
pivot1
);
while
(
a
[--
great
]
>
pivot2
);
if
(
pivotsDiffer
)
{
/*
/*
* Partitioning:
* Partitioning:
*
*
* left part center part right part
* left part center part right part
* +------------------------------------------------------------+
* +------------------------------------------------------------
--
+
* | < pivot1 | pivot1 <= && <= pivot2 | ? | > pivot2 |
* | < pivot1 | pivot1 <= && <= pivot2 | ? | > pivot2 |
* +------------------------------------------------------------+
* +------------------------------------------------------------
--
+
* ^ ^ ^
* ^ ^ ^
* | | |
* | | |
* less k great
* less k great
...
@@ -2101,16 +2541,14 @@ final class DualPivotQuicksort {
...
@@ -2101,16 +2541,14 @@ final class DualPivotQuicksort {
* pivot1 <= all in [less, k) <= pivot2
* pivot1 <= all in [less, k) <= pivot2
* all in (great, right) > pivot2
* all in (great, right) > pivot2
*
*
* Pointer k is the first index of ?-part
* Pointer k is the first index of ?-part
.
*/
*/
outer:
outer:
for
(
int
k
=
less
;
k
<=
great
;
k
++)
{
for
(
int
k
=
less
;
k
<=
great
;
k
++)
{
double
ak
=
a
[
k
];
double
ak
=
a
[
k
];
if
(
ak
<
pivot1
)
{
// Move a[k] to left part
if
(
ak
<
pivot1
)
{
// Move a[k] to left part
if
(
k
!=
less
)
{
a
[
k
]
=
a
[
less
];
a
[
k
]
=
a
[
less
];
a
[
less
]
=
ak
;
a
[
less
]
=
ak
;
}
less
++;
less
++;
}
else
if
(
ak
>
pivot2
)
{
// Move a[k] to right part
}
else
if
(
ak
>
pivot2
)
{
// Move a[k] to right part
while
(
a
[
great
]
>
pivot2
)
{
while
(
a
[
great
]
>
pivot2
)
{
...
@@ -2120,89 +2558,32 @@ final class DualPivotQuicksort {
...
@@ -2120,89 +2558,32 @@ final class DualPivotQuicksort {
}
}
if
(
a
[
great
]
<
pivot1
)
{
if
(
a
[
great
]
<
pivot1
)
{
a
[
k
]
=
a
[
less
];
a
[
k
]
=
a
[
less
];
a
[
less
++
]
=
a
[
great
];
a
[
less
]
=
a
[
great
];
a
[
great
--]
=
ak
;
less
++
;
}
else
{
// pivot1 <= a[great] <= pivot2
}
else
{
// pivot1 <= a[great] <= pivot2
a
[
k
]
=
a
[
great
];
a
[
k
]
=
a
[
great
];
a
[
great
--]
=
ak
;
}
}
}
a
[
great
]
=
ak
;
}
}
else
{
// Pivots are equal
/*
* Partition degenerates to the traditional 3-way,
* or "Dutch National Flag", partition:
*
* left part center part right part
* +----------------------------------------------+
* | < pivot | == pivot | ? | > pivot |
* +----------------------------------------------+
* ^ ^ ^
* | | |
* less k great
*
* Invariants:
*
* all in (left, less) < pivot
* all in [less, k) == pivot
* all in (great, right) > pivot
*
* Pointer k is the first index of ?-part
*/
for
(
int
k
=
less
;
k
<=
great
;
k
++)
{
double
ak
=
a
[
k
];
if
(
ak
==
pivot1
)
{
continue
;
}
if
(
ak
<
pivot1
)
{
// Move a[k] to left part
if
(
k
!=
less
)
{
a
[
k
]
=
a
[
less
];
a
[
less
]
=
ak
;
}
less
++;
}
else
{
// (a[k] > pivot1) - Move a[k] to right part
/*
* We know that pivot1 == a[e3] == pivot2. Thus, we know
* that great will still be >= k when the following loop
* terminates, even though we don't test for it explicitly.
* In other words, a[e3] acts as a sentinel for great.
*/
while
(
a
[
great
]
>
pivot1
)
{
great
--;
great
--;
}
}
if
(
a
[
great
]
<
pivot1
)
{
a
[
k
]
=
a
[
less
];
a
[
less
++]
=
a
[
great
];
a
[
great
--]
=
ak
;
}
else
{
// a[great] == pivot1
a
[
k
]
=
pivot1
;
a
[
great
--]
=
ak
;
}
}
}
}
}
// Swap pivots into their final positions
// Swap pivots into their final positions
a
[
left
]
=
a
[
less
-
1
];
a
[
less
-
1
]
=
pivot1
;
a
[
left
]
=
a
[
less
-
1
];
a
[
less
-
1
]
=
pivot1
;
a
[
right
]
=
a
[
great
+
1
];
a
[
great
+
1
]
=
pivot2
;
a
[
right
]
=
a
[
great
+
1
];
a
[
great
+
1
]
=
pivot2
;
// Sort left and right parts recursively, excluding known pivot value
s
// Sort left and right parts recursively, excluding known pivot
s
doSort
(
a
,
left
,
less
-
2
);
sort
(
a
,
left
,
less
-
2
,
leftmost
);
doSort
(
a
,
great
+
2
,
right
);
sort
(
a
,
great
+
2
,
right
,
false
);
/*
/*
* If pivot1 == pivot2, all elements from center
* If center part is too large (comprises > 5/7 of the array),
* part are equal and, therefore, already sorted
* swap internal pivot values to ends.
*/
*/
if
(!
pivotsDiffer
)
{
if
(
less
<
e1
&&
e5
<
great
)
{
return
;
}
/*
/*
* If center part is too large (comprises > 2/3 of the array),
* Skip elements, which are equal to pivot values.
* swap internal pivot values to ends
*/
*/
if
(
less
<
e1
&&
great
>
e5
)
{
while
(
a
[
less
]
==
pivot1
)
{
while
(
a
[
less
]
==
pivot1
)
{
less
++;
less
++;
}
}
...
@@ -2227,12 +2608,16 @@ final class DualPivotQuicksort {
...
@@ -2227,12 +2608,16 @@ final class DualPivotQuicksort {
* pivot1 < all in [less, k) < pivot2
* pivot1 < all in [less, k) < pivot2
* all in (great, *) == pivot2
* all in (great, *) == pivot2
*
*
* Pointer k is the first index of ?-part
* Pointer k is the first index of ?-part.
*/
*/
outer:
outer:
for
(
int
k
=
less
;
k
<=
great
;
k
++)
{
for
(
int
k
=
less
;
k
<=
great
;
k
++)
{
double
ak
=
a
[
k
];
double
ak
=
a
[
k
];
if
(
ak
==
pivot2
)
{
// Move a[k] to right part
if
(
ak
==
pivot1
)
{
// Move a[k] to left part
a
[
k
]
=
a
[
less
];
a
[
less
]
=
ak
;
less
++;
}
else
if
(
ak
==
pivot2
)
{
// Move a[k] to right part
while
(
a
[
great
]
==
pivot2
)
{
while
(
a
[
great
]
==
pivot2
)
{
if
(
great
--
==
k
)
{
if
(
great
--
==
k
)
{
break
outer
;
break
outer
;
...
@@ -2240,30 +2625,104 @@ final class DualPivotQuicksort {
...
@@ -2240,30 +2625,104 @@ final class DualPivotQuicksort {
}
}
if
(
a
[
great
]
==
pivot1
)
{
if
(
a
[
great
]
==
pivot1
)
{
a
[
k
]
=
a
[
less
];
a
[
k
]
=
a
[
less
];
a
[
less
++]
=
pivot1
;
/*
* Even though a[great] equals to pivot1, the
* assignment a[less] = pivot1 may be incorrect,
* if a[great] and pivot1 are floating-point zeros
* of different signs. Therefore in float and
* double sorting methods we have to use more
* accurate assignment a[less] = a[great].
*/
a
[
less
]
=
a
[
great
];
less
++;
}
else
{
// pivot1 < a[great] < pivot2
}
else
{
// pivot1 < a[great] < pivot2
a
[
k
]
=
a
[
great
];
a
[
k
]
=
a
[
great
];
}
}
a
[
great
--]
=
pivot2
;
a
[
great
]
=
ak
;
}
else
if
(
ak
==
pivot1
)
{
// Move a[k] to left part
great
--;
}
}
}
// Sort center part recursively
sort
(
a
,
less
,
great
,
false
);
}
else
{
// Pivots are equal
/*
* Partition degenerates to the traditional 3-way
* (or "Dutch National Flag") schema:
*
* left part center part right part
* +-------------------------------------------------+
* | < pivot | == pivot | ? | > pivot |
* +-------------------------------------------------+
* ^ ^ ^
* | | |
* less k great
*
* Invariants:
*
* all in (left, less) < pivot
* all in [less, k) == pivot
* all in (great, right) > pivot
*
* Pointer k is the first index of ?-part.
*/
for
(
int
k
=
left
;
k
<=
great
;
k
++)
{
if
(
a
[
k
]
==
pivot1
)
{
continue
;
}
double
ak
=
a
[
k
];
if
(
ak
<
pivot1
)
{
// Move a[k] to left part
a
[
k
]
=
a
[
less
];
a
[
less
]
=
ak
;
less
++;
}
else
{
// a[k] > pivot1 - Move a[k] to right part
/*
* We know that pivot1 == a[e3] == pivot2. Thus, we know
* that great will still be >= k when the following loop
* terminates, even though we don't test for it explicitly.
* In other words, a[e3] acts as a sentinel for great.
*/
while
(
a
[
great
]
>
pivot1
)
{
// assert great > k;
great
--;
}
if
(
a
[
great
]
<
pivot1
)
{
a
[
k
]
=
a
[
less
];
a
[
k
]
=
a
[
less
];
a
[
less
++]
=
pivot1
;
a
[
less
]
=
a
[
great
];
less
++;
}
else
{
// a[great] == pivot1
/*
* Even though a[great] equals to pivot1, the
* assignment a[k] = pivot1 may be incorrect,
* if a[great] and pivot1 are floating-point
* zeros of different signs. Therefore in float
* and double sorting methods we have to use
* more accurate assignment a[k] = a[great].
*/
a
[
k
]
=
a
[
great
];
}
}
a
[
great
]
=
ak
;
great
--;
}
}
}
}
// Sort center part recursively, excluding known pivot values
// Sort left and right parts recursively
doSort
(
a
,
less
,
great
);
sort
(
a
,
left
,
less
-
1
,
leftmost
);
sort
(
a
,
great
+
1
,
right
,
false
);
}
}
}
/**
/**
* Checks that {@code fromIndex} and {@code toIndex} are in
* Checks that {@code fromIndex} and {@code toIndex} are in
the range,
*
the range and throws an appropriate exception, if they aren't
.
*
otherwise throws an appropriate exception
.
*/
*/
private
static
void
rangeCheck
(
int
length
,
int
fromIndex
,
int
toIndex
)
{
private
static
void
rangeCheck
(
int
length
,
int
fromIndex
,
int
toIndex
)
{
if
(
fromIndex
>
toIndex
)
{
if
(
fromIndex
>
toIndex
)
{
throw
new
IllegalArgumentException
(
throw
new
IllegalArgumentException
(
"fromIndex
("
+
fromIndex
+
") > toIndex("
+
toIndex
+
")"
);
"fromIndex
: "
+
fromIndex
+
" > toIndex: "
+
toIndex
);
}
}
if
(
fromIndex
<
0
)
{
if
(
fromIndex
<
0
)
{
throw
new
ArrayIndexOutOfBoundsException
(
fromIndex
);
throw
new
ArrayIndexOutOfBoundsException
(
fromIndex
);
...
...
test/java/util/Arrays/Sorting.java
浏览文件 @
29ca4456
/*
/*
* Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2009,
2010,
Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
*
* This code is free software; you can redistribute it and/or modify it
* This code is free software; you can redistribute it and/or modify it
...
@@ -43,10 +43,11 @@ public class Sorting {
...
@@ -43,10 +43,11 @@ public class Sorting {
// Array lengths used in a long run (default)
// Array lengths used in a long run (default)
private
static
final
int
[]
LONG_RUN_LENGTHS
=
{
private
static
final
int
[]
LONG_RUN_LENGTHS
=
{
1
,
2
,
3
,
5
,
8
,
13
,
21
,
34
,
55
,
100
,
1000
,
10000
,
100000
,
1000000
};
1
,
2
,
3
,
5
,
8
,
13
,
21
,
34
,
55
,
100
,
1000
,
10000
,
100000
,
1000000
};
// Array lengths used in a short run
// Array lengths used in a short run
private
static
final
int
[]
SHORT_RUN_LENGTHS
=
{
1
,
2
,
3
,
21
,
55
,
1000
,
10000
};
private
static
final
int
[]
SHORT_RUN_LENGTHS
=
{
1
,
2
,
3
,
21
,
55
,
1000
,
10000
};
// Random initial values used in a long run (default)
// Random initial values used in a long run (default)
private
static
final
long
[]
LONG_RUN_RANDOMS
=
{
666
,
0xC0FFEE
,
999
};
private
static
final
long
[]
LONG_RUN_RANDOMS
=
{
666
,
0xC0FFEE
,
999
};
...
@@ -65,99 +66,338 @@ public class Sorting {
...
@@ -65,99 +66,338 @@ public class Sorting {
}
}
long
end
=
System
.
currentTimeMillis
();
long
end
=
System
.
currentTimeMillis
();
out
.
format
(
"
PASS
in %d sec.\n"
,
Math
.
round
((
end
-
start
)
/
1
E3
));
out
.
format
(
"
\nPASSED
in %d sec.\n"
,
Math
.
round
((
end
-
start
)
/
1
E3
));
}
}
private
static
void
testAndCheck
(
int
[]
lengths
,
long
[]
randoms
)
{
private
static
void
testAndCheck
(
int
[]
lengths
,
long
[]
randoms
)
{
testEmptyAndNullIntArray
();
testEmptyAndNullLongArray
();
testEmptyAndNullShortArray
();
testEmptyAndNullCharArray
();
testEmptyAndNullByteArray
();
testEmptyAndNullFloatArray
();
testEmptyAndNullDoubleArray
();
for
(
long
random
:
randoms
)
{
for
(
long
random
:
randoms
)
{
reset
(
random
);
reset
(
random
);
for
(
int
len
:
lengths
)
{
for
(
int
length
:
lengths
)
{
testAndCheckWithCheckSum
(
len
,
random
);
testAndCheckWithCheckSum
(
length
,
random
);
}
reset
(
random
);
for
(
int
length
:
lengths
)
{
testAndCheckWithScrambling
(
length
,
random
);
}
}
reset
(
random
);
reset
(
random
);
for
(
int
len
:
lengths
)
{
for
(
int
len
gth
:
lengths
)
{
testAndCheck
WithScrambling
(
len
,
random
);
testAndCheck
Float
(
length
,
random
);
}
}
reset
(
random
);
reset
(
random
);
for
(
int
len
:
lengths
)
{
for
(
int
len
gth
:
lengths
)
{
testAndCheck
Float
(
len
,
random
);
testAndCheck
Double
(
length
,
random
);
}
}
reset
(
random
);
reset
(
random
);
for
(
int
len
:
lengths
)
{
for
(
int
len
gth
:
lengths
)
{
testAndCheck
Double
(
len
,
random
);
testAndCheck
Range
(
length
,
random
);
}
}
reset
(
random
);
reset
(
random
);
for
(
int
len
:
lengths
)
{
for
(
int
len
gth
:
lengths
)
{
testAndCheck
Range
(
len
,
random
);
testAndCheck
SubArray
(
length
,
random
);
}
}
reset
(
random
);
reset
(
random
);
for
(
int
len
:
lengths
)
{
for
(
int
length
:
lengths
)
{
testAndCheckSubArray
(
len
,
random
);
testStable
(
length
,
random
);
}
}
}
private
static
void
testEmptyAndNullIntArray
()
{
ourDescription
=
"Check empty and null array"
;
Arrays
.
sort
(
new
int
[]
{});
Arrays
.
sort
(
new
int
[]
{},
0
,
0
);
try
{
Arrays
.
sort
((
int
[])
null
);
}
catch
(
NullPointerException
expected
)
{
try
{
Arrays
.
sort
((
int
[])
null
,
0
,
0
);
}
catch
(
NullPointerException
expected2
)
{
return
;
}
failed
(
"Arrays.sort(int[],fromIndex,toIndex) shouldn't "
+
"catch null array"
);
}
failed
(
"Arrays.sort(int[]) shouldn't catch null array"
);
}
private
static
void
testEmptyAndNullLongArray
()
{
ourDescription
=
"Check empty and null array"
;
Arrays
.
sort
(
new
long
[]
{});
Arrays
.
sort
(
new
long
[]
{},
0
,
0
);
try
{
Arrays
.
sort
((
long
[])
null
);
}
catch
(
NullPointerException
expected
)
{
try
{
Arrays
.
sort
((
long
[])
null
,
0
,
0
);
}
catch
(
NullPointerException
expected2
)
{
return
;
}
failed
(
"Arrays.sort(long[],fromIndex,toIndex) shouldn't "
+
"catch null array"
);
}
failed
(
"Arrays.sort(long[]) shouldn't catch null array"
);
}
private
static
void
testEmptyAndNullShortArray
()
{
ourDescription
=
"Check empty and null array"
;
Arrays
.
sort
(
new
short
[]
{});
Arrays
.
sort
(
new
short
[]
{},
0
,
0
);
try
{
Arrays
.
sort
((
short
[])
null
);
}
catch
(
NullPointerException
expected
)
{
try
{
Arrays
.
sort
((
short
[])
null
,
0
,
0
);
}
catch
(
NullPointerException
expected2
)
{
return
;
}
failed
(
"Arrays.sort(short[],fromIndex,toIndex) shouldn't "
+
"catch null array"
);
}
failed
(
"Arrays.sort(short[]) shouldn't catch null array"
);
}
private
static
void
testEmptyAndNullCharArray
()
{
ourDescription
=
"Check empty and null array"
;
Arrays
.
sort
(
new
char
[]
{});
Arrays
.
sort
(
new
char
[]
{},
0
,
0
);
try
{
Arrays
.
sort
((
char
[])
null
);
}
catch
(
NullPointerException
expected
)
{
try
{
Arrays
.
sort
((
char
[])
null
,
0
,
0
);
}
catch
(
NullPointerException
expected2
)
{
return
;
}
failed
(
"Arrays.sort(char[],fromIndex,toIndex) shouldn't "
+
"catch null array"
);
}
failed
(
"Arrays.sort(char[]) shouldn't catch null array"
);
}
private
static
void
testEmptyAndNullByteArray
()
{
ourDescription
=
"Check empty and null array"
;
Arrays
.
sort
(
new
byte
[]
{});
Arrays
.
sort
(
new
byte
[]
{},
0
,
0
);
try
{
Arrays
.
sort
((
byte
[])
null
);
}
catch
(
NullPointerException
expected
)
{
try
{
Arrays
.
sort
((
byte
[])
null
,
0
,
0
);
}
catch
(
NullPointerException
expected2
)
{
return
;
}
failed
(
"Arrays.sort(byte[],fromIndex,toIndex) shouldn't "
+
"catch null array"
);
}
failed
(
"Arrays.sort(byte[]) shouldn't catch null array"
);
}
private
static
void
testEmptyAndNullFloatArray
()
{
ourDescription
=
"Check empty and null array"
;
Arrays
.
sort
(
new
float
[]
{});
Arrays
.
sort
(
new
float
[]
{},
0
,
0
);
try
{
Arrays
.
sort
((
float
[])
null
);
}
catch
(
NullPointerException
expected
)
{
try
{
Arrays
.
sort
((
float
[])
null
,
0
,
0
);
}
catch
(
NullPointerException
expected2
)
{
return
;
}
failed
(
"Arrays.sort(float[],fromIndex,toIndex) shouldn't "
+
"catch null array"
);
}
failed
(
"Arrays.sort(float[]) shouldn't catch null array"
);
}
private
static
void
testEmptyAndNullDoubleArray
()
{
ourDescription
=
"Check empty and null array"
;
Arrays
.
sort
(
new
double
[]
{});
Arrays
.
sort
(
new
double
[]
{},
0
,
0
);
try
{
Arrays
.
sort
((
double
[])
null
);
}
catch
(
NullPointerException
expected
)
{
try
{
Arrays
.
sort
((
double
[])
null
,
0
,
0
);
}
catch
(
NullPointerException
expected2
)
{
return
;
}
}
failed
(
"Arrays.sort(double[],fromIndex,toIndex) shouldn't "
+
"catch null array"
);
}
}
failed
(
"Arrays.sort(double[]) shouldn't catch null array"
);
}
}
private
static
void
testAndCheckSubArray
(
int
len
,
long
random
)
{
private
static
void
testAndCheckSubArray
(
int
length
,
long
random
)
{
int
[]
golden
=
new
int
[
len
];
ourDescription
=
"Check sorting of subarray"
;
int
[]
golden
=
new
int
[
length
];
boolean
newLine
=
false
;
for
(
int
m
=
1
;
m
<
len
/
2
;
m
*=
2
)
{
for
(
int
m
=
1
;
m
<
length
/
2
;
m
*=
2
)
{
newLine
=
true
;
int
fromIndex
=
m
;
int
fromIndex
=
m
;
int
toIndex
=
len
-
m
;
int
toIndex
=
len
gth
-
m
;
prepareSubArray
(
golden
,
fromIndex
,
toIndex
,
m
);
prepareSubArray
(
golden
,
fromIndex
,
toIndex
,
m
);
int
[]
test
=
golden
.
clone
();
int
[]
test
=
golden
.
clone
();
for
(
TypeConverter
converter
:
TypeConverter
.
values
())
{
for
(
TypeConverter
converter
:
TypeConverter
.
values
())
{
out
.
println
(
"Test
#6
: "
+
converter
+
out
.
println
(
"Test
'subarray'
: "
+
converter
+
" len
= "
+
len
+
", m = "
+
m
);
" len
gth = "
+
length
+
", m = "
+
m
);
Object
convertedGolden
=
converter
.
convert
(
golden
);
Object
convertedGolden
=
converter
.
convert
(
golden
);
Object
convertedTest
=
converter
.
convert
(
test
);
Object
convertedTest
=
converter
.
convert
(
test
);
// outArray(test);
// outArr(test);
sortSubArray
(
convertedTest
,
fromIndex
,
toIndex
);
sortSubArray
(
convertedTest
,
fromIndex
,
toIndex
);
// outArr(test);
// outArr
ay
(test);
checkSubArray
(
convertedTest
,
fromIndex
,
toIndex
,
m
);
checkSubArray
(
convertedTest
,
fromIndex
,
toIndex
,
m
);
}
}
}
}
if
(
newLine
)
{
out
.
println
();
out
.
println
();
}
}
}
private
static
void
testAndCheckRange
(
int
len
,
long
random
)
{
private
static
void
testAndCheckRange
(
int
length
,
long
random
)
{
int
[]
golden
=
new
int
[
len
];
ourDescription
=
"Check range check"
;
int
[]
golden
=
new
int
[
length
];
for
(
int
m
=
1
;
m
<
2
*
len
;
m
*=
2
)
{
for
(
int
m
=
1
;
m
<
2
*
len
gth
;
m
*=
2
)
{
for
(
int
i
=
1
;
i
<=
len
;
i
++)
{
for
(
int
i
=
1
;
i
<=
len
gth
;
i
++)
{
golden
[
i
-
1
]
=
i
%
m
+
m
%
i
;
golden
[
i
-
1
]
=
i
%
m
+
m
%
i
;
}
}
for
(
TypeConverter
converter
:
TypeConverter
.
values
())
{
for
(
TypeConverter
converter
:
TypeConverter
.
values
())
{
out
.
println
(
"Test
#5
: "
+
converter
+
out
.
println
(
"Test
'range'
: "
+
converter
+
", len
= "
+
len
+
", m = "
+
m
);
", len
gth = "
+
length
+
", m = "
+
m
);
Object
convertedGolden
=
converter
.
convert
(
golden
);
Object
convertedGolden
=
converter
.
convert
(
golden
);
sortRange
(
convertedGolden
,
m
);
checkRange
(
convertedGolden
,
m
);
sortEmpty
(
convertedGolden
);
}
}
}
}
out
.
println
();
out
.
println
();
}
}
private
static
void
testAndCheckWithCheckSum
(
int
len
,
long
random
)
{
private
static
void
testStable
(
int
length
,
long
random
)
{
int
[]
golden
=
new
int
[
len
];
ourDescription
=
"Check if sorting is stable"
;
Pair
[]
a
=
build
(
length
);
out
.
println
(
"Test 'stable': "
+
"random = "
+
random
+
", length = "
+
length
);
Arrays
.
sort
(
a
);
checkSorted
(
a
);
checkStable
(
a
);
}
private
static
void
checkSorted
(
Pair
[]
a
)
{
for
(
int
i
=
0
;
i
<
a
.
length
-
1
;
i
++)
{
if
(
a
[
i
].
getKey
()
>
a
[
i
+
1
].
getKey
())
{
failed
(
i
,
""
+
a
[
i
].
getKey
(),
""
+
a
[
i
+
1
].
getKey
());
}
}
}
private
static
void
checkStable
(
Pair
[]
a
)
{
for
(
int
i
=
0
;
i
<
a
.
length
/
4
;
)
{
int
key1
=
a
[
i
].
getKey
();
int
value1
=
a
[
i
++].
getValue
();
int
key2
=
a
[
i
].
getKey
();
int
value2
=
a
[
i
++].
getValue
();
int
key3
=
a
[
i
].
getKey
();
int
value3
=
a
[
i
++].
getValue
();
int
key4
=
a
[
i
].
getKey
();
int
value4
=
a
[
i
++].
getValue
();
if
(!(
key1
==
key2
&&
key2
==
key3
&&
key3
==
key4
))
{
failed
(
"On position "
+
i
+
" must keys are different "
+
key1
+
", "
+
key2
+
", "
+
key3
+
", "
+
key4
);
}
if
(!(
value1
<
value2
&&
value2
<
value3
&&
value3
<
value4
))
{
failed
(
"Sorting is not stable at position "
+
i
+
". Second values have been changed: "
+
value1
+
", "
+
value2
+
", "
+
value3
+
", "
+
value4
);
}
}
}
private
static
Pair
[]
build
(
int
length
)
{
Pair
[]
a
=
new
Pair
[
length
*
4
];
for
(
int
i
=
0
;
i
<
a
.
length
;
)
{
int
key
=
ourRandom
.
nextInt
();
a
[
i
++]
=
new
Pair
(
key
,
1
);
a
[
i
++]
=
new
Pair
(
key
,
2
);
a
[
i
++]
=
new
Pair
(
key
,
3
);
a
[
i
++]
=
new
Pair
(
key
,
4
);
}
return
a
;
}
private
static
final
class
Pair
implements
Comparable
<
Pair
>
{
Pair
(
int
key
,
int
value
)
{
myKey
=
key
;
myValue
=
value
;
}
int
getKey
()
{
return
myKey
;
}
int
getValue
()
{
return
myValue
;
}
public
int
compareTo
(
Pair
pair
)
{
if
(
myKey
<
pair
.
myKey
)
{
return
-
1
;
}
if
(
myKey
>
pair
.
myKey
)
{
return
1
;
}
return
0
;
}
@Override
public
String
toString
()
{
return
"("
+
myKey
+
", "
+
myValue
+
")"
;
}
private
int
myKey
;
private
int
myValue
;
}
for
(
int
m
=
1
;
m
<
2
*
len
;
m
*=
2
)
{
private
static
void
testAndCheckWithCheckSum
(
int
length
,
long
random
)
{
ourDescription
=
"Check sorting with check sum"
;
int
[]
golden
=
new
int
[
length
];
for
(
int
m
=
1
;
m
<
2
*
length
;
m
*=
2
)
{
for
(
UnsortedBuilder
builder
:
UnsortedBuilder
.
values
())
{
for
(
UnsortedBuilder
builder
:
UnsortedBuilder
.
values
())
{
builder
.
build
(
golden
,
m
);
builder
.
build
(
golden
,
m
);
int
[]
test
=
golden
.
clone
();
int
[]
test
=
golden
.
clone
();
for
(
TypeConverter
converter
:
TypeConverter
.
values
())
{
for
(
TypeConverter
converter
:
TypeConverter
.
values
())
{
out
.
println
(
"Test
#1: "
+
converter
+
" "
+
builder
+
out
.
println
(
"Test
'check sum': "
+
converter
+
" "
+
"random = "
+
random
+
", len = "
+
len
+
builder
+
"random = "
+
random
+
", length = "
+
", m = "
+
m
);
length
+
", m = "
+
m
);
Object
convertedGolden
=
converter
.
convert
(
golden
);
Object
convertedGolden
=
converter
.
convert
(
golden
);
Object
convertedTest
=
converter
.
convert
(
test
);
Object
convertedTest
=
converter
.
convert
(
test
);
sort
(
convertedTest
);
sort
(
convertedTest
);
...
@@ -168,11 +408,12 @@ public class Sorting {
...
@@ -168,11 +408,12 @@ public class Sorting {
out
.
println
();
out
.
println
();
}
}
private
static
void
testAndCheckWithScrambling
(
int
len
,
long
random
)
{
private
static
void
testAndCheckWithScrambling
(
int
length
,
long
random
)
{
int
[]
golden
=
new
int
[
len
];
ourDescription
=
"Check sorting with scrambling"
;
int
[]
golden
=
new
int
[
length
];
for
(
int
m
=
1
;
m
<=
7
;
m
++)
{
for
(
int
m
=
1
;
m
<=
7
;
m
++)
{
if
(
m
>
len
)
{
if
(
m
>
len
gth
)
{
break
;
break
;
}
}
for
(
SortedBuilder
builder
:
SortedBuilder
.
values
())
{
for
(
SortedBuilder
builder
:
SortedBuilder
.
values
())
{
...
@@ -181,9 +422,9 @@ public class Sorting {
...
@@ -181,9 +422,9 @@ public class Sorting {
scramble
(
test
);
scramble
(
test
);
for
(
TypeConverter
converter
:
TypeConverter
.
values
())
{
for
(
TypeConverter
converter
:
TypeConverter
.
values
())
{
out
.
println
(
"Test
#2: "
+
converter
+
" "
+
builder
+
out
.
println
(
"Test
'scrambling': "
+
converter
+
" "
+
"random = "
+
random
+
", len = "
+
len
+
builder
+
"random = "
+
random
+
", length = "
+
", m = "
+
m
);
length
+
", m = "
+
m
);
Object
convertedGolden
=
converter
.
convert
(
golden
);
Object
convertedGolden
=
converter
.
convert
(
golden
);
Object
convertedTest
=
converter
.
convert
(
test
);
Object
convertedTest
=
converter
.
convert
(
test
);
sort
(
convertedTest
);
sort
(
convertedTest
);
...
@@ -194,8 +435,9 @@ public class Sorting {
...
@@ -194,8 +435,9 @@ public class Sorting {
out
.
println
();
out
.
println
();
}
}
private
static
void
testAndCheckFloat
(
int
len
,
long
random
)
{
private
static
void
testAndCheckFloat
(
int
length
,
long
random
)
{
float
[]
golden
=
new
float
[
len
];
ourDescription
=
"Check float sorting"
;
float
[]
golden
=
new
float
[
length
];
final
int
MAX
=
10
;
final
int
MAX
=
10
;
boolean
newLine
=
false
;
boolean
newLine
=
false
;
...
@@ -204,22 +446,23 @@ public class Sorting {
...
@@ -204,22 +446,23 @@ public class Sorting {
for
(
int
z
=
0
;
z
<=
MAX
;
z
++)
{
for
(
int
z
=
0
;
z
<=
MAX
;
z
++)
{
for
(
int
n
=
0
;
n
<=
MAX
;
n
++)
{
for
(
int
n
=
0
;
n
<=
MAX
;
n
++)
{
for
(
int
p
=
0
;
p
<=
MAX
;
p
++)
{
for
(
int
p
=
0
;
p
<=
MAX
;
p
++)
{
if
(
a
+
g
+
z
+
n
+
p
>
len
)
{
if
(
a
+
g
+
z
+
n
+
p
>
len
gth
)
{
continue
;
continue
;
}
}
if
(
a
+
g
+
z
+
n
+
p
<
len
)
{
if
(
a
+
g
+
z
+
n
+
p
<
len
gth
)
{
continue
;
continue
;
}
}
for
(
FloatBuilder
builder
:
FloatBuilder
.
values
())
{
for
(
FloatBuilder
builder
:
FloatBuilder
.
values
())
{
out
.
println
(
"Test #3: random = "
+
random
+
out
.
println
(
"Test 'float': random = "
+
random
+
", len = "
+
len
+
", a = "
+
a
+
", g = "
+
g
+
", length = "
+
length
+
", a = "
+
a
+
", z = "
+
z
+
", n = "
+
n
+
", p = "
+
p
);
", g = "
+
g
+
", z = "
+
z
+
", n = "
+
n
+
", p = "
+
p
);
builder
.
build
(
golden
,
a
,
g
,
z
,
n
,
p
);
builder
.
build
(
golden
,
a
,
g
,
z
,
n
,
p
);
float
[]
test
=
golden
.
clone
();
float
[]
test
=
golden
.
clone
();
scramble
(
test
);
scramble
(
test
);
// outArr(test);
// outArr
ay
(test);
sort
(
test
);
sort
(
test
);
// outArr(test);
// outArr
ay
(test);
compare
(
test
,
golden
,
a
,
n
,
g
);
compare
(
test
,
golden
,
a
,
n
,
g
);
}
}
newLine
=
true
;
newLine
=
true
;
...
@@ -233,8 +476,9 @@ public class Sorting {
...
@@ -233,8 +476,9 @@ public class Sorting {
}
}
}
}
private
static
void
testAndCheckDouble
(
int
len
,
long
random
)
{
private
static
void
testAndCheckDouble
(
int
length
,
long
random
)
{
double
[]
golden
=
new
double
[
len
];
ourDescription
=
"Check double sorting"
;
double
[]
golden
=
new
double
[
length
];
final
int
MAX
=
10
;
final
int
MAX
=
10
;
boolean
newLine
=
false
;
boolean
newLine
=
false
;
...
@@ -243,22 +487,22 @@ public class Sorting {
...
@@ -243,22 +487,22 @@ public class Sorting {
for
(
int
z
=
0
;
z
<=
MAX
;
z
++)
{
for
(
int
z
=
0
;
z
<=
MAX
;
z
++)
{
for
(
int
n
=
0
;
n
<=
MAX
;
n
++)
{
for
(
int
n
=
0
;
n
<=
MAX
;
n
++)
{
for
(
int
p
=
0
;
p
<=
MAX
;
p
++)
{
for
(
int
p
=
0
;
p
<=
MAX
;
p
++)
{
if
(
a
+
g
+
z
+
n
+
p
>
len
)
{
if
(
a
+
g
+
z
+
n
+
p
>
len
gth
)
{
continue
;
continue
;
}
}
if
(
a
+
g
+
z
+
n
+
p
<
len
)
{
if
(
a
+
g
+
z
+
n
+
p
<
len
gth
)
{
continue
;
continue
;
}
}
for
(
DoubleBuilder
builder
:
DoubleBuilder
.
values
())
{
for
(
DoubleBuilder
builder
:
DoubleBuilder
.
values
())
{
out
.
println
(
"Test
#4
: random = "
+
random
+
out
.
println
(
"Test
'double'
: random = "
+
random
+
", len
= "
+
len
+
", a = "
+
a
+
", g = "
+
g
+
", len
gth = "
+
length
+
", a = "
+
a
+
", g = "
+
", z = "
+
z
+
", n = "
+
n
+
", p = "
+
p
);
g
+
", z = "
+
z
+
", n = "
+
n
+
", p = "
+
p
);
builder
.
build
(
golden
,
a
,
g
,
z
,
n
,
p
);
builder
.
build
(
golden
,
a
,
g
,
z
,
n
,
p
);
double
[]
test
=
golden
.
clone
();
double
[]
test
=
golden
.
clone
();
scramble
(
test
);
scramble
(
test
);
// outArr(test);
// outArr
ay
(test);
sort
(
test
);
sort
(
test
);
// outArr(test);
// outArr
ay
(test);
compare
(
test
,
golden
,
a
,
n
,
g
);
compare
(
test
,
golden
,
a
,
n
,
g
);
}
}
newLine
=
true
;
newLine
=
true
;
...
@@ -276,37 +520,29 @@ public class Sorting {
...
@@ -276,37 +520,29 @@ public class Sorting {
for
(
int
i
=
0
;
i
<
fromIndex
;
i
++)
{
for
(
int
i
=
0
;
i
<
fromIndex
;
i
++)
{
a
[
i
]
=
0xBABA
;
a
[
i
]
=
0xBABA
;
}
}
for
(
int
i
=
fromIndex
;
i
<
toIndex
;
i
++)
{
for
(
int
i
=
fromIndex
;
i
<
toIndex
;
i
++)
{
a
[
i
]
=
-
i
+
m
;
a
[
i
]
=
-
i
+
m
;
}
}
for
(
int
i
=
toIndex
;
i
<
a
.
length
;
i
++)
{
for
(
int
i
=
toIndex
;
i
<
a
.
length
;
i
++)
{
a
[
i
]
=
0xDEDA
;
a
[
i
]
=
0xDEDA
;
}
}
}
}
private
static
void
scramble
(
int
[]
a
)
{
private
static
void
scramble
(
int
[]
a
)
{
int
length
=
a
.
length
;
for
(
int
i
=
0
;
i
<
a
.
length
*
7
;
i
++)
{
swap
(
a
,
ourRandom
.
nextInt
(
a
.
length
),
ourRandom
.
nextInt
(
a
.
length
));
for
(
int
i
=
0
;
i
<
length
*
7
;
i
++)
{
swap
(
a
,
ourRandom
.
nextInt
(
length
),
ourRandom
.
nextInt
(
length
));
}
}
}
}
private
static
void
scramble
(
float
[]
a
)
{
private
static
void
scramble
(
float
[]
a
)
{
int
length
=
a
.
length
;
for
(
int
i
=
0
;
i
<
a
.
length
*
7
;
i
++)
{
swap
(
a
,
ourRandom
.
nextInt
(
a
.
length
),
ourRandom
.
nextInt
(
a
.
length
));
for
(
int
i
=
0
;
i
<
length
*
7
;
i
++)
{
swap
(
a
,
ourRandom
.
nextInt
(
length
),
ourRandom
.
nextInt
(
length
));
}
}
}
}
private
static
void
scramble
(
double
[]
a
)
{
private
static
void
scramble
(
double
[]
a
)
{
int
length
=
a
.
length
;
for
(
int
i
=
0
;
i
<
a
.
length
*
7
;
i
++)
{
swap
(
a
,
ourRandom
.
nextInt
(
a
.
length
),
ourRandom
.
nextInt
(
a
.
length
));
for
(
int
i
=
0
;
i
<
length
*
7
;
i
++)
{
swap
(
a
,
ourRandom
.
nextInt
(
length
),
ourRandom
.
nextInt
(
length
));
}
}
}
}
...
@@ -393,6 +629,16 @@ public class Sorting {
...
@@ -393,6 +629,16 @@ public class Sorting {
}
}
return
b
;
return
b
;
}
}
},
INTEGER
{
Object
convert
(
int
[]
a
)
{
Integer
[]
b
=
new
Integer
[
a
.
length
];
for
(
int
i
=
0
;
i
<
a
.
length
;
i
++)
{
b
[
i
]
=
new
Integer
(
a
[
i
]);
}
return
b
;
}
};
};
abstract
Object
convert
(
int
[]
a
);
abstract
Object
convert
(
int
[]
a
);
...
@@ -691,6 +937,8 @@ public class Sorting {
...
@@ -691,6 +937,8 @@ public class Sorting {
compare
((
float
[])
test
,
(
float
[])
golden
);
compare
((
float
[])
test
,
(
float
[])
golden
);
}
else
if
(
test
instanceof
double
[])
{
}
else
if
(
test
instanceof
double
[])
{
compare
((
double
[])
test
,
(
double
[])
golden
);
compare
((
double
[])
test
,
(
double
[])
golden
);
}
else
if
(
test
instanceof
Integer
[])
{
compare
((
Integer
[])
test
,
(
Integer
[])
golden
);
}
else
{
}
else
{
failed
(
"Unknow type of array: "
+
test
+
" of class "
+
failed
(
"Unknow type of array: "
+
test
+
" of class "
+
test
.
getClass
().
getName
());
test
.
getClass
().
getName
());
...
@@ -703,13 +951,13 @@ public class Sorting {
...
@@ -703,13 +951,13 @@ public class Sorting {
}
}
private
static
void
failed
(
String
message
)
{
private
static
void
failed
(
String
message
)
{
err
.
format
(
"\n***
FAILED: %s\n\n"
,
message
);
err
.
format
(
"\n***
TEST FAILED - %s\n\n%s\n\n"
,
ourDescription
,
message
);
throw
new
RuntimeException
(
"Test failed - see log file for details"
);
throw
new
RuntimeException
(
"Test failed - see log file for details"
);
}
}
private
static
void
failed
(
int
index
,
String
value1
,
String
value2
)
{
private
static
void
failed
(
int
index
,
String
value1
,
String
value2
)
{
failed
(
"Array is not sorted at "
+
index
+
"-th position: "
+
value1
+
failed
(
"Array is not sorted at "
+
index
+
"-th position: "
+
" and "
+
value2
);
value1
+
" and "
+
value2
);
}
}
private
static
void
checkSorted
(
Object
object
)
{
private
static
void
checkSorted
(
Object
object
)
{
...
@@ -727,12 +975,22 @@ public class Sorting {
...
@@ -727,12 +975,22 @@ public class Sorting {
checkSorted
((
float
[])
object
);
checkSorted
((
float
[])
object
);
}
else
if
(
object
instanceof
double
[])
{
}
else
if
(
object
instanceof
double
[])
{
checkSorted
((
double
[])
object
);
checkSorted
((
double
[])
object
);
}
else
if
(
object
instanceof
Integer
[])
{
checkSorted
((
Integer
[])
object
);
}
else
{
}
else
{
failed
(
"Unknow type of array: "
+
object
+
" of class "
+
failed
(
"Unknow type of array: "
+
object
+
" of class "
+
object
.
getClass
().
getName
());
object
.
getClass
().
getName
());
}
}
}
}
private
static
void
compare
(
Integer
[]
a
,
Integer
[]
b
)
{
for
(
int
i
=
0
;
i
<
a
.
length
;
i
++)
{
if
(
a
[
i
].
intValue
()
!=
b
[
i
].
intValue
())
{
failed
(
i
,
""
+
a
[
i
],
""
+
b
[
i
]);
}
}
}
private
static
void
compare
(
int
[]
a
,
int
[]
b
)
{
private
static
void
compare
(
int
[]
a
,
int
[]
b
)
{
for
(
int
i
=
0
;
i
<
a
.
length
;
i
++)
{
for
(
int
i
=
0
;
i
<
a
.
length
;
i
++)
{
if
(
a
[
i
]
!=
b
[
i
])
{
if
(
a
[
i
]
!=
b
[
i
])
{
...
@@ -789,6 +1047,14 @@ public class Sorting {
...
@@ -789,6 +1047,14 @@ public class Sorting {
}
}
}
}
private
static
void
checkSorted
(
Integer
[]
a
)
{
for
(
int
i
=
0
;
i
<
a
.
length
-
1
;
i
++)
{
if
(
a
[
i
].
intValue
()
>
a
[
i
+
1
].
intValue
())
{
failed
(
i
,
""
+
a
[
i
],
""
+
a
[
i
+
1
]);
}
}
}
private
static
void
checkSorted
(
int
[]
a
)
{
private
static
void
checkSorted
(
int
[]
a
)
{
for
(
int
i
=
0
;
i
<
a
.
length
-
1
;
i
++)
{
for
(
int
i
=
0
;
i
<
a
.
length
-
1
;
i
++)
{
if
(
a
[
i
]
>
a
[
i
+
1
])
{
if
(
a
[
i
]
>
a
[
i
+
1
])
{
...
@@ -847,7 +1113,7 @@ public class Sorting {
...
@@ -847,7 +1113,7 @@ public class Sorting {
private
static
void
checkCheckSum
(
Object
test
,
Object
golden
)
{
private
static
void
checkCheckSum
(
Object
test
,
Object
golden
)
{
if
(
checkSum
(
test
)
!=
checkSum
(
golden
))
{
if
(
checkSum
(
test
)
!=
checkSum
(
golden
))
{
failed
(
"
Original and sorted arrays seems
not identical"
);
failed
(
"
It seems that original and sorted arrays are
not identical"
);
}
}
}
}
...
@@ -866,6 +1132,8 @@ public class Sorting {
...
@@ -866,6 +1132,8 @@ public class Sorting {
return
checkSum
((
float
[])
object
);
return
checkSum
((
float
[])
object
);
}
else
if
(
object
instanceof
double
[])
{
}
else
if
(
object
instanceof
double
[])
{
return
checkSum
((
double
[])
object
);
return
checkSum
((
double
[])
object
);
}
else
if
(
object
instanceof
Integer
[])
{
return
checkSum
((
Integer
[])
object
);
}
else
{
}
else
{
failed
(
"Unknow type of array: "
+
object
+
" of class "
+
failed
(
"Unknow type of array: "
+
object
+
" of class "
+
object
.
getClass
().
getName
());
object
.
getClass
().
getName
());
...
@@ -873,6 +1141,15 @@ public class Sorting {
...
@@ -873,6 +1141,15 @@ public class Sorting {
}
}
}
}
private
static
int
checkSum
(
Integer
[]
a
)
{
int
checkXorSum
=
0
;
for
(
Integer
e
:
a
)
{
checkXorSum
^=
e
.
intValue
();
}
return
checkXorSum
;
}
private
static
int
checkSum
(
int
[]
a
)
{
private
static
int
checkSum
(
int
[]
a
)
{
int
checkXorSum
=
0
;
int
checkXorSum
=
0
;
...
@@ -951,6 +1228,8 @@ public class Sorting {
...
@@ -951,6 +1228,8 @@ public class Sorting {
Arrays
.
sort
((
float
[])
object
);
Arrays
.
sort
((
float
[])
object
);
}
else
if
(
object
instanceof
double
[])
{
}
else
if
(
object
instanceof
double
[])
{
Arrays
.
sort
((
double
[])
object
);
Arrays
.
sort
((
double
[])
object
);
}
else
if
(
object
instanceof
Integer
[])
{
Arrays
.
sort
((
Integer
[])
object
);
}
else
{
}
else
{
failed
(
"Unknow type of array: "
+
object
+
" of class "
+
failed
(
"Unknow type of array: "
+
object
+
" of class "
+
object
.
getClass
().
getName
());
object
.
getClass
().
getName
());
...
@@ -972,6 +1251,8 @@ public class Sorting {
...
@@ -972,6 +1251,8 @@ public class Sorting {
Arrays
.
sort
((
float
[])
object
,
fromIndex
,
toIndex
);
Arrays
.
sort
((
float
[])
object
,
fromIndex
,
toIndex
);
}
else
if
(
object
instanceof
double
[])
{
}
else
if
(
object
instanceof
double
[])
{
Arrays
.
sort
((
double
[])
object
,
fromIndex
,
toIndex
);
Arrays
.
sort
((
double
[])
object
,
fromIndex
,
toIndex
);
}
else
if
(
object
instanceof
Integer
[])
{
Arrays
.
sort
((
Integer
[])
object
,
fromIndex
,
toIndex
);
}
else
{
}
else
{
failed
(
"Unknow type of array: "
+
object
+
" of class "
+
failed
(
"Unknow type of array: "
+
object
+
" of class "
+
object
.
getClass
().
getName
());
object
.
getClass
().
getName
());
...
@@ -993,12 +1274,36 @@ public class Sorting {
...
@@ -993,12 +1274,36 @@ public class Sorting {
checkSubArray
((
float
[])
object
,
fromIndex
,
toIndex
,
m
);
checkSubArray
((
float
[])
object
,
fromIndex
,
toIndex
,
m
);
}
else
if
(
object
instanceof
double
[])
{
}
else
if
(
object
instanceof
double
[])
{
checkSubArray
((
double
[])
object
,
fromIndex
,
toIndex
,
m
);
checkSubArray
((
double
[])
object
,
fromIndex
,
toIndex
,
m
);
}
else
if
(
object
instanceof
Integer
[])
{
checkSubArray
((
Integer
[])
object
,
fromIndex
,
toIndex
,
m
);
}
else
{
}
else
{
failed
(
"Unknow type of array: "
+
object
+
" of class "
+
failed
(
"Unknow type of array: "
+
object
+
" of class "
+
object
.
getClass
().
getName
());
object
.
getClass
().
getName
());
}
}
}
}
private
static
void
checkSubArray
(
Integer
[]
a
,
int
fromIndex
,
int
toIndex
,
int
m
)
{
for
(
int
i
=
0
;
i
<
fromIndex
;
i
++)
{
if
(
a
[
i
].
intValue
()
!=
0xBABA
)
{
failed
(
"Range sort changes left element on position "
+
i
+
": "
+
a
[
i
]
+
", must be "
+
0xBABA
);
}
}
for
(
int
i
=
fromIndex
;
i
<
toIndex
-
1
;
i
++)
{
if
(
a
[
i
].
intValue
()
>
a
[
i
+
1
].
intValue
())
{
failed
(
i
,
""
+
a
[
i
],
""
+
a
[
i
+
1
]);
}
}
for
(
int
i
=
toIndex
;
i
<
a
.
length
;
i
++)
{
if
(
a
[
i
].
intValue
()
!=
0xDEDA
)
{
failed
(
"Range sort changes right element on position "
+
i
+
": "
+
a
[
i
]
+
", must be "
+
0xDEDA
);
}
}
}
private
static
void
checkSubArray
(
int
[]
a
,
int
fromIndex
,
int
toIndex
,
int
m
)
{
private
static
void
checkSubArray
(
int
[]
a
,
int
fromIndex
,
int
toIndex
,
int
m
)
{
for
(
int
i
=
0
;
i
<
fromIndex
;
i
++)
{
for
(
int
i
=
0
;
i
<
fromIndex
;
i
++)
{
if
(
a
[
i
]
!=
0xBABA
)
{
if
(
a
[
i
]
!=
0xBABA
)
{
...
@@ -1153,49 +1458,59 @@ public class Sorting {
...
@@ -1153,49 +1458,59 @@ public class Sorting {
}
}
}
}
private
static
void
sort
Range
(
Object
object
,
int
m
)
{
private
static
void
check
Range
(
Object
object
,
int
m
)
{
if
(
object
instanceof
int
[])
{
if
(
object
instanceof
int
[])
{
sort
Range
((
int
[])
object
,
m
);
check
Range
((
int
[])
object
,
m
);
}
else
if
(
object
instanceof
long
[])
{
}
else
if
(
object
instanceof
long
[])
{
sort
Range
((
long
[])
object
,
m
);
check
Range
((
long
[])
object
,
m
);
}
else
if
(
object
instanceof
short
[])
{
}
else
if
(
object
instanceof
short
[])
{
sort
Range
((
short
[])
object
,
m
);
check
Range
((
short
[])
object
,
m
);
}
else
if
(
object
instanceof
byte
[])
{
}
else
if
(
object
instanceof
byte
[])
{
sort
Range
((
byte
[])
object
,
m
);
check
Range
((
byte
[])
object
,
m
);
}
else
if
(
object
instanceof
char
[])
{
}
else
if
(
object
instanceof
char
[])
{
sort
Range
((
char
[])
object
,
m
);
check
Range
((
char
[])
object
,
m
);
}
else
if
(
object
instanceof
float
[])
{
}
else
if
(
object
instanceof
float
[])
{
sort
Range
((
float
[])
object
,
m
);
check
Range
((
float
[])
object
,
m
);
}
else
if
(
object
instanceof
double
[])
{
}
else
if
(
object
instanceof
double
[])
{
sortRange
((
double
[])
object
,
m
);
checkRange
((
double
[])
object
,
m
);
}
else
if
(
object
instanceof
Integer
[])
{
checkRange
((
Integer
[])
object
,
m
);
}
else
{
}
else
{
failed
(
"Unknow type of array: "
+
object
+
" of class "
+
failed
(
"Unknow type of array: "
+
object
+
" of class "
+
object
.
getClass
().
getName
());
object
.
getClass
().
getName
());
}
}
}
}
private
static
void
sortEmpty
(
Object
object
)
{
private
static
void
checkRange
(
Integer
[]
a
,
int
m
)
{
if
(
object
instanceof
int
[])
{
try
{
Arrays
.
sort
(
new
int
[]
{});
Arrays
.
sort
(
a
,
m
+
1
,
m
);
}
else
if
(
object
instanceof
long
[])
{
Arrays
.
sort
(
new
long
[]
{});
failed
(
"Sort does not throw IllegalArgumentException "
+
}
else
if
(
object
instanceof
short
[])
{
" as expected: fromIndex = "
+
(
m
+
1
)
+
Arrays
.
sort
(
new
short
[]
{});
" toIndex = "
+
m
);
}
else
if
(
object
instanceof
byte
[])
{
Arrays
.
sort
(
new
byte
[]
{});
}
else
if
(
object
instanceof
char
[])
{
Arrays
.
sort
(
new
char
[]
{});
}
else
if
(
object
instanceof
float
[])
{
Arrays
.
sort
(
new
float
[]
{});
}
else
if
(
object
instanceof
double
[])
{
Arrays
.
sort
(
new
double
[]
{});
}
else
{
failed
(
"Unknow type of array: "
+
object
+
" of class "
+
object
.
getClass
().
getName
());
}
}
catch
(
IllegalArgumentException
iae
)
{
try
{
Arrays
.
sort
(
a
,
-
m
,
a
.
length
);
failed
(
"Sort does not throw ArrayIndexOutOfBoundsException "
+
" as expected: fromIndex = "
+
(-
m
));
}
}
catch
(
ArrayIndexOutOfBoundsException
aoe
)
{
try
{
Arrays
.
sort
(
a
,
0
,
a
.
length
+
m
);
private
static
void
sortRange
(
int
[]
a
,
int
m
)
{
failed
(
"Sort does not throw ArrayIndexOutOfBoundsException "
+
" as expected: toIndex = "
+
(
a
.
length
+
m
));
}
catch
(
ArrayIndexOutOfBoundsException
aie
)
{
return
;
}
}
}
}
private
static
void
checkRange
(
int
[]
a
,
int
m
)
{
try
{
try
{
Arrays
.
sort
(
a
,
m
+
1
,
m
);
Arrays
.
sort
(
a
,
m
+
1
,
m
);
...
@@ -1224,7 +1539,7 @@ public class Sorting {
...
@@ -1224,7 +1539,7 @@ public class Sorting {
}
}
}
}
private
static
void
sort
Range
(
long
[]
a
,
int
m
)
{
private
static
void
check
Range
(
long
[]
a
,
int
m
)
{
try
{
try
{
Arrays
.
sort
(
a
,
m
+
1
,
m
);
Arrays
.
sort
(
a
,
m
+
1
,
m
);
...
@@ -1253,7 +1568,7 @@ public class Sorting {
...
@@ -1253,7 +1568,7 @@ public class Sorting {
}
}
}
}
private
static
void
sort
Range
(
byte
[]
a
,
int
m
)
{
private
static
void
check
Range
(
byte
[]
a
,
int
m
)
{
try
{
try
{
Arrays
.
sort
(
a
,
m
+
1
,
m
);
Arrays
.
sort
(
a
,
m
+
1
,
m
);
...
@@ -1282,7 +1597,7 @@ public class Sorting {
...
@@ -1282,7 +1597,7 @@ public class Sorting {
}
}
}
}
private
static
void
sort
Range
(
short
[]
a
,
int
m
)
{
private
static
void
check
Range
(
short
[]
a
,
int
m
)
{
try
{
try
{
Arrays
.
sort
(
a
,
m
+
1
,
m
);
Arrays
.
sort
(
a
,
m
+
1
,
m
);
...
@@ -1311,7 +1626,7 @@ public class Sorting {
...
@@ -1311,7 +1626,7 @@ public class Sorting {
}
}
}
}
private
static
void
sort
Range
(
char
[]
a
,
int
m
)
{
private
static
void
check
Range
(
char
[]
a
,
int
m
)
{
try
{
try
{
Arrays
.
sort
(
a
,
m
+
1
,
m
);
Arrays
.
sort
(
a
,
m
+
1
,
m
);
...
@@ -1340,7 +1655,7 @@ public class Sorting {
...
@@ -1340,7 +1655,7 @@ public class Sorting {
}
}
}
}
private
static
void
sort
Range
(
float
[]
a
,
int
m
)
{
private
static
void
check
Range
(
float
[]
a
,
int
m
)
{
try
{
try
{
Arrays
.
sort
(
a
,
m
+
1
,
m
);
Arrays
.
sort
(
a
,
m
+
1
,
m
);
...
@@ -1369,7 +1684,7 @@ public class Sorting {
...
@@ -1369,7 +1684,7 @@ public class Sorting {
}
}
}
}
private
static
void
sort
Range
(
double
[]
a
,
int
m
)
{
private
static
void
check
Range
(
double
[]
a
,
int
m
)
{
try
{
try
{
Arrays
.
sort
(
a
,
m
+
1
,
m
);
Arrays
.
sort
(
a
,
m
+
1
,
m
);
...
@@ -1410,31 +1725,36 @@ public class Sorting {
...
@@ -1410,31 +1725,36 @@ public class Sorting {
ourSecond
=
0
;
ourSecond
=
0
;
}
}
private
static
void
outArr
(
in
t
[]
a
)
{
private
static
void
outArr
ay
(
Objec
t
[]
a
)
{
for
(
int
i
=
0
;
i
<
a
.
length
;
i
++)
{
for
(
int
i
=
0
;
i
<
a
.
length
;
i
++)
{
out
.
print
(
a
[
i
]
+
" "
);
out
.
print
(
a
[
i
]
+
" "
);
}
}
out
.
println
();
out
.
println
();
out
.
println
();
}
}
private
static
void
outArr
(
floa
t
[]
a
)
{
private
static
void
outArr
ay
(
in
t
[]
a
)
{
for
(
int
i
=
0
;
i
<
a
.
length
;
i
++)
{
for
(
int
i
=
0
;
i
<
a
.
length
;
i
++)
{
out
.
print
(
a
[
i
]
+
" "
);
out
.
print
(
a
[
i
]
+
" "
);
}
}
out
.
println
();
out
.
println
();
out
.
println
();
}
}
private
static
void
outArr
(
double
[]
a
)
{
private
static
void
outArr
ay
(
float
[]
a
)
{
for
(
int
i
=
0
;
i
<
a
.
length
;
i
++)
{
for
(
int
i
=
0
;
i
<
a
.
length
;
i
++)
{
out
.
print
(
a
[
i
]
+
" "
);
out
.
print
(
a
[
i
]
+
" "
);
}
}
out
.
println
();
out
.
println
();
}
private
static
void
outArray
(
double
[]
a
)
{
for
(
int
i
=
0
;
i
<
a
.
length
;
i
++)
{
out
.
print
(
a
[
i
]
+
" "
);
}
out
.
println
();
out
.
println
();
}
}
private
static
int
ourFirst
;
private
static
int
ourFirst
;
private
static
int
ourSecond
;
private
static
int
ourSecond
;
private
static
Random
ourRandom
;
private
static
Random
ourRandom
;
private
static
String
ourDescription
;
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录