d3_rails 2.8.0 → 2.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.DS_Store +0 -0
- data/README.md +27 -5
- data/lib/d3_rails/version.rb +1 -1
- data/vendor/.DS_Store +0 -0
- data/vendor/assets/.DS_Store +0 -0
- data/vendor/assets/javascripts/.DS_Store +0 -0
- data/vendor/assets/javascripts/d3.v2.js +99 -80
- data/vendor/assets/javascripts/morris.js +1 -0
- data/vendor/assets/javascripts/morris/.DS_Store +0 -0
- data/vendor/assets/javascripts/morris/Makefile +10 -0
- data/vendor/assets/javascripts/morris/README.md +87 -0
- data/vendor/assets/javascripts/morris/examples/_template.html +18 -0
- data/vendor/assets/javascripts/morris/examples/days.html +36 -0
- data/vendor/assets/javascripts/morris/examples/decimal.html +31 -0
- data/vendor/assets/javascripts/morris/examples/lib/example.css +13 -0
- data/vendor/assets/javascripts/morris/examples/lib/example.js +4 -0
- data/vendor/assets/javascripts/morris/examples/lib/prettify.css +1 -0
- data/vendor/assets/javascripts/morris/examples/lib/prettify.js +28 -0
- data/vendor/assets/javascripts/morris/examples/months-no-smooth.html +37 -0
- data/vendor/assets/javascripts/morris/examples/negative.html +35 -0
- data/vendor/assets/javascripts/morris/examples/non-date.html +36 -0
- data/vendor/assets/javascripts/morris/examples/quarters.html +53 -0
- data/vendor/assets/javascripts/morris/examples/timestamps.html +37 -0
- data/vendor/assets/javascripts/morris/examples/weeks.html +52 -0
- data/vendor/assets/javascripts/morris/morris.coffee +444 -0
- data/vendor/assets/javascripts/morris/morris.js +493 -0
- data/vendor/assets/javascripts/morris/morris.min.js +1 -0
- data/vendor/assets/javascripts/tesseract.js +1 -0
- data/vendor/assets/javascripts/tesseract/.gitignore +2 -0
- data/vendor/assets/javascripts/tesseract/LICENSE +12 -0
- data/vendor/assets/javascripts/tesseract/Makefile +48 -0
- data/vendor/assets/javascripts/tesseract/README.md +11 -0
- data/vendor/assets/javascripts/tesseract/index.js +1 -0
- data/vendor/assets/javascripts/tesseract/lib/dart/AUTHORS +9 -0
- data/vendor/assets/javascripts/tesseract/lib/dart/LICENSE +25 -0
- data/vendor/assets/javascripts/tesseract/lib/dart/dual_pivot_quicksort.dart +342 -0
- data/vendor/assets/javascripts/tesseract/package.json +11 -0
- data/vendor/assets/javascripts/tesseract/src/array.js +32 -0
- data/vendor/assets/javascripts/tesseract/src/bisect.js +44 -0
- data/vendor/assets/javascripts/tesseract/src/filter.js +19 -0
- data/vendor/assets/javascripts/tesseract/src/heap.js +44 -0
- data/vendor/assets/javascripts/tesseract/src/heapselect.js +36 -0
- data/vendor/assets/javascripts/tesseract/src/identity.js +3 -0
- data/vendor/assets/javascripts/tesseract/src/insertionsort.js +18 -0
- data/vendor/assets/javascripts/tesseract/src/null.js +3 -0
- data/vendor/assets/javascripts/tesseract/src/package.js +14 -0
- data/vendor/assets/javascripts/tesseract/src/permute.js +8 -0
- data/vendor/assets/javascripts/tesseract/src/quicksort.js +282 -0
- data/vendor/assets/javascripts/tesseract/src/reduce.js +19 -0
- data/vendor/assets/javascripts/tesseract/src/tesseract.js +663 -0
- data/vendor/assets/javascripts/tesseract/src/version.js +1 -0
- data/vendor/assets/javascripts/tesseract/src/zero.js +3 -0
- data/vendor/assets/javascripts/tesseract/tesseract.js +1177 -0
- data/vendor/assets/javascripts/tesseract/tesseract.min.js +1 -0
- data/vendor/assets/javascripts/tesseract/test/benchmark.js +177 -0
- data/vendor/assets/javascripts/tesseract/test/bisect-test.js +206 -0
- data/vendor/assets/javascripts/tesseract/test/heap-test.js +44 -0
- data/vendor/assets/javascripts/tesseract/test/permute-test.js +51 -0
- data/vendor/assets/javascripts/tesseract/test/select-test.js +63 -0
- data/vendor/assets/javascripts/tesseract/test/sort-test.js +83 -0
- data/vendor/assets/javascripts/tesseract/test/tesseract-test.js +655 -0
- data/vendor/assets/javascripts/tesseract/test/version-test.js +16 -0
- metadata +63 -8
@@ -0,0 +1,32 @@
|
|
1
|
+
var tesseract_array8 = tesseract_arrayUntyped,
|
2
|
+
tesseract_array16 = tesseract_arrayUntyped,
|
3
|
+
tesseract_array32 = tesseract_arrayUntyped,
|
4
|
+
tesseract_arrayLengthen = tesseract_identity,
|
5
|
+
tesseract_arrayWiden = tesseract_identity;
|
6
|
+
|
7
|
+
if (typeof Uint8Array !== "undefined") {
|
8
|
+
tesseract_array8 = function(n) { return new Uint8Array(n); };
|
9
|
+
tesseract_array16 = function(n) { return new Uint16Array(n); };
|
10
|
+
tesseract_array32 = function(n) { return new Uint32Array(n); };
|
11
|
+
|
12
|
+
tesseract_arrayLengthen = function(array, length) {
|
13
|
+
var copy = new array.constructor(length);
|
14
|
+
copy.set(array);
|
15
|
+
return copy;
|
16
|
+
};
|
17
|
+
|
18
|
+
tesseract_arrayWiden = function(array, width) {
|
19
|
+
var copy;
|
20
|
+
switch (width) {
|
21
|
+
case 16: copy = tesseract_array16(array.length); break;
|
22
|
+
case 32: copy = tesseract_array32(array.length); break;
|
23
|
+
default: throw new Error("invalid array width!");
|
24
|
+
}
|
25
|
+
copy.set(array);
|
26
|
+
return copy;
|
27
|
+
};
|
28
|
+
}
|
29
|
+
|
30
|
+
function tesseract_arrayUntyped(n) {
|
31
|
+
return new Array(n);
|
32
|
+
}
|
@@ -0,0 +1,44 @@
|
|
1
|
+
var bisect = tesseract.bisect = bisect_by(tesseract_identity);
|
2
|
+
|
3
|
+
bisect.by = bisect_by;
|
4
|
+
|
5
|
+
function bisect_by(f) {
|
6
|
+
|
7
|
+
// Locate the insertion point for x in a to maintain sorted order. The
|
8
|
+
// arguments lo and hi may be used to specify a subset of the array which
|
9
|
+
// should be considered; by default the entire array is used. If x is already
|
10
|
+
// present in a, the insertion point will be before (to the left of) any
|
11
|
+
// existing entries. The return value is suitable for use as the first
|
12
|
+
// argument to `array.splice` assuming that a is already sorted.
|
13
|
+
//
|
14
|
+
// The returned insertion point i partitions the array a into two halves so
|
15
|
+
// that all v < x for v in a[lo:i] for the left side and all v >= x for v in
|
16
|
+
// a[i:hi] for the right side.
|
17
|
+
function bisectLeft(a, x, lo, hi) {
|
18
|
+
while (lo < hi) {
|
19
|
+
var mid = lo + hi >> 1;
|
20
|
+
if (f(a[mid]) < x) lo = mid + 1;
|
21
|
+
else hi = mid;
|
22
|
+
}
|
23
|
+
return lo;
|
24
|
+
}
|
25
|
+
|
26
|
+
// Similar to bisectLeft, but returns an insertion point which comes after (to
|
27
|
+
// the right of) any existing entries of x in a.
|
28
|
+
//
|
29
|
+
// The returned insertion point i partitions the array into two halves so that
|
30
|
+
// all v <= x for v in a[lo:i] for the left side and all v > x for v in
|
31
|
+
// a[i:hi] for the right side.
|
32
|
+
function bisectRight(a, x, lo, hi) {
|
33
|
+
while (lo < hi) {
|
34
|
+
var mid = lo + hi >> 1;
|
35
|
+
if (x < f(a[mid])) hi = mid;
|
36
|
+
else lo = mid + 1;
|
37
|
+
}
|
38
|
+
return lo;
|
39
|
+
}
|
40
|
+
|
41
|
+
bisectRight.right = bisectRight;
|
42
|
+
bisectRight.left = bisectLeft;
|
43
|
+
return bisectRight;
|
44
|
+
}
|
@@ -0,0 +1,19 @@
|
|
1
|
+
function tesseract_filterExact(bisect, value) {
|
2
|
+
return function(values) {
|
3
|
+
var n = values.length;
|
4
|
+
return [bisect.left(values, value, 0, n), bisect.right(values, value, 0, n)];
|
5
|
+
};
|
6
|
+
}
|
7
|
+
|
8
|
+
function tesseract_filterRange(bisect, range) {
|
9
|
+
var min = range[0],
|
10
|
+
max = range[1];
|
11
|
+
return function(values) {
|
12
|
+
var n = values.length;
|
13
|
+
return [bisect.left(values, min, 0, n), bisect.left(values, max, 0, n)];
|
14
|
+
};
|
15
|
+
}
|
16
|
+
|
17
|
+
function tesseract_filterAll(values) {
|
18
|
+
return [0, values.length];
|
19
|
+
}
|
@@ -0,0 +1,44 @@
|
|
1
|
+
var heap = tesseract.heap = heap_by(tesseract_identity);
|
2
|
+
|
3
|
+
heap.by = heap_by;
|
4
|
+
|
5
|
+
function heap_by(f) {
|
6
|
+
|
7
|
+
// Builds a binary heap within the specified array a[lo:hi]. The heap has the
|
8
|
+
// property such that the parent a[lo+i] is always less than or equal to its
|
9
|
+
// two children: a[lo+2*i+1] and a[lo+2*i+2].
|
10
|
+
function heap(a, lo, hi) {
|
11
|
+
var n = hi - lo,
|
12
|
+
i = (n >>> 1) + 1;
|
13
|
+
while (--i > 0) sift(a, i, n, lo);
|
14
|
+
return a;
|
15
|
+
}
|
16
|
+
|
17
|
+
// Sorts the specified array a[lo:hi] in descending order, assuming it is
|
18
|
+
// already a heap.
|
19
|
+
function sort(a, lo, hi) {
|
20
|
+
var n = hi - lo,
|
21
|
+
t;
|
22
|
+
while (--n > 0) t = a[lo], a[lo] = a[lo + n], a[lo + n] = t, sift(a, 1, n, lo);
|
23
|
+
return a;
|
24
|
+
}
|
25
|
+
|
26
|
+
// Sifts the element a[lo+i-1] down the heap, where the heap is the contiguous
|
27
|
+
// slice of array a[lo:lo+n]. This method can also be used to update the heap
|
28
|
+
// incrementally, without incurring the full cost of reconstructing the heap.
|
29
|
+
function sift(a, i, n, lo) {
|
30
|
+
var d = a[--lo + i],
|
31
|
+
x = f(d),
|
32
|
+
child;
|
33
|
+
while ((child = i << 1) <= n) {
|
34
|
+
if (child < n && f(a[lo + child]) > f(a[lo + child + 1])) child++;
|
35
|
+
if (x <= f(a[lo + child])) break;
|
36
|
+
a[lo + i] = a[lo + child];
|
37
|
+
i = child;
|
38
|
+
}
|
39
|
+
a[lo + i] = d;
|
40
|
+
}
|
41
|
+
|
42
|
+
heap.sort = sort;
|
43
|
+
return heap;
|
44
|
+
}
|
@@ -0,0 +1,36 @@
|
|
1
|
+
var heapselect = tesseract.heapselect = heapselect_by(tesseract_identity);
|
2
|
+
|
3
|
+
heapselect.by = heapselect_by;
|
4
|
+
|
5
|
+
function heapselect_by(f) {
|
6
|
+
var heap = heap_by(f);
|
7
|
+
|
8
|
+
// Returns a new array containing the top k elements in the array a[lo:hi].
|
9
|
+
// The returned array is not sorted, but maintains the heap property. If k is
|
10
|
+
// greater than hi - lo, then fewer than k elements will be returned. The
|
11
|
+
// order of elements in a is unchanged by this operation.
|
12
|
+
function heapselect(a, lo, hi, k) {
|
13
|
+
var queue = new Array(k = Math.min(hi - lo, k)),
|
14
|
+
min,
|
15
|
+
i,
|
16
|
+
x,
|
17
|
+
d;
|
18
|
+
|
19
|
+
for (i = 0; i < k; ++i) queue[i] = a[lo++];
|
20
|
+
heap(queue, 0, k);
|
21
|
+
|
22
|
+
if (lo < hi) {
|
23
|
+
min = f(queue[0]);
|
24
|
+
do {
|
25
|
+
if (x = f(d = a[lo]) > min) {
|
26
|
+
queue[0] = d;
|
27
|
+
min = f(heap(queue, 0, k)[0]);
|
28
|
+
}
|
29
|
+
} while (++lo < hi);
|
30
|
+
}
|
31
|
+
|
32
|
+
return queue;
|
33
|
+
}
|
34
|
+
|
35
|
+
return heapselect;
|
36
|
+
}
|
@@ -0,0 +1,18 @@
|
|
1
|
+
var insertionsort = tesseract.insertionsort = insertionsort_by(tesseract_identity);
|
2
|
+
|
3
|
+
insertionsort.by = insertionsort_by;
|
4
|
+
|
5
|
+
function insertionsort_by(f) {
|
6
|
+
|
7
|
+
function insertionsort(a, lo, hi) {
|
8
|
+
for (var i = lo + 1; i < hi; ++i) {
|
9
|
+
for (var j = i, t = a[i], x = f(t); j > lo && f(a[j - 1]) > x; --j) {
|
10
|
+
a[j] = a[j - 1];
|
11
|
+
}
|
12
|
+
a[j] = t;
|
13
|
+
}
|
14
|
+
return a;
|
15
|
+
}
|
16
|
+
|
17
|
+
return insertionsort;
|
18
|
+
}
|
@@ -0,0 +1,14 @@
|
|
1
|
+
var util = require("util"),
|
2
|
+
tesseract = require("../tesseract").tesseract;
|
3
|
+
|
4
|
+
util.puts(JSON.stringify({
|
5
|
+
"name": "tesseract",
|
6
|
+
"version": tesseract.version,
|
7
|
+
"private": true,
|
8
|
+
"main": "./index.js",
|
9
|
+
"devDependencies": {
|
10
|
+
"d3": "2.8.0",
|
11
|
+
"vows": "0.6.1",
|
12
|
+
"uglify-js": "1.2.5"
|
13
|
+
}
|
14
|
+
}, null, 2));
|
@@ -0,0 +1,282 @@
|
|
1
|
+
// Algorithm designed by Vladimir Yaroslavskiy.
|
2
|
+
// Implementation based on the Dart project; see lib/dart/LICENSE for details.
|
3
|
+
|
4
|
+
var quicksort = tesseract.quicksort = quicksort_by(tesseract_identity);
|
5
|
+
|
6
|
+
quicksort.by = quicksort_by;
|
7
|
+
|
8
|
+
function quicksort_by(f) {
|
9
|
+
var insertionsort = insertionsort_by(f);
|
10
|
+
|
11
|
+
function sort(a, lo, hi) {
|
12
|
+
return (hi - lo < quicksort_sizeThreshold
|
13
|
+
? insertionsort
|
14
|
+
: quicksort)(a, lo, hi);
|
15
|
+
}
|
16
|
+
|
17
|
+
function quicksort(a, lo, hi) {
|
18
|
+
|
19
|
+
// Compute the two pivots by looking at 5 elements.
|
20
|
+
var sixth = (hi - lo) / 6 | 0,
|
21
|
+
i1 = lo + sixth,
|
22
|
+
i5 = hi - 1 - sixth,
|
23
|
+
i3 = lo + hi - 1 >> 1, // The midpoint.
|
24
|
+
i2 = i3 - sixth,
|
25
|
+
i4 = i3 + sixth;
|
26
|
+
|
27
|
+
var e1 = a[i1], x1 = f(e1),
|
28
|
+
e2 = a[i2], x2 = f(e2),
|
29
|
+
e3 = a[i3], x3 = f(e3),
|
30
|
+
e4 = a[i4], x4 = f(e4),
|
31
|
+
e5 = a[i5], x5 = f(e5);
|
32
|
+
|
33
|
+
// Sort the selected 5 elements using a sorting network.
|
34
|
+
if (x1 > x2) t = e1, e1 = e2, e2 = t, t = x1, x1 = x2, x2 = t;
|
35
|
+
if (x4 > x5) t = e4, e4 = e5, e5 = t, t = x4, x4 = x5, x5 = t;
|
36
|
+
if (x1 > x3) t = e1, e1 = e3, e3 = t, t = x1, x1 = x3, x3 = t;
|
37
|
+
if (x2 > x3) t = e2, e2 = e3, e3 = t, t = x2, x2 = x3, x3 = t;
|
38
|
+
if (x1 > x4) t = e1, e1 = e4, e4 = t, t = x1, x1 = x4, x4 = t;
|
39
|
+
if (x3 > x4) t = e3, e3 = e4, e4 = t, t = x3, x3 = x4, x4 = t;
|
40
|
+
if (x2 > x5) t = e2, e2 = e5, e5 = t, t = x2, x2 = x5, x5 = t;
|
41
|
+
if (x2 > x3) t = e2, e2 = e3, e3 = t, t = x2, x2 = x3, x3 = t;
|
42
|
+
if (x4 > x5) t = e4, e4 = e5, e5 = t, t = x4, x4 = x5, x5 = t;
|
43
|
+
|
44
|
+
var pivot1 = e2, pivotValue1 = x2,
|
45
|
+
pivot2 = e4, pivotValue2 = x4;
|
46
|
+
|
47
|
+
// e2 and e4 have been saved in the pivot variables. They will be written
|
48
|
+
// back, once the partitioning is finished.
|
49
|
+
a[i1] = e1;
|
50
|
+
a[i2] = a[lo];
|
51
|
+
a[i3] = e3;
|
52
|
+
a[i4] = a[hi - 1];
|
53
|
+
a[i5] = e5;
|
54
|
+
|
55
|
+
var less = lo + 1, // First element in the middle partition.
|
56
|
+
great = hi - 2; // Last element in the middle partition.
|
57
|
+
|
58
|
+
// Note that for value comparison, <, <=, >= and > coerce to a primitive via
|
59
|
+
// Object.prototype.valueOf; == and === do not, so in order to be consistent
|
60
|
+
// with natural order (such as for Date objects), we must do two compares.
|
61
|
+
var pivotsEqual = pivotValue1 <= pivotValue2 && pivotValue1 >= pivotValue2;
|
62
|
+
if (pivotsEqual) {
|
63
|
+
|
64
|
+
// Degenerated case where the partitioning becomes a dutch national flag
|
65
|
+
// problem.
|
66
|
+
//
|
67
|
+
// [ | < pivot | == pivot | unpartitioned | > pivot | ]
|
68
|
+
// ^ ^ ^ ^ ^
|
69
|
+
// left less k great right
|
70
|
+
//
|
71
|
+
// a[left] and a[right] are undefined and are filled after the
|
72
|
+
// partitioning.
|
73
|
+
//
|
74
|
+
// Invariants:
|
75
|
+
// 1) for x in ]left, less[ : x < pivot.
|
76
|
+
// 2) for x in [less, k[ : x == pivot.
|
77
|
+
// 3) for x in ]great, right[ : x > pivot.
|
78
|
+
for (var k = less; k <= great; ++k) {
|
79
|
+
var ek = a[k], xk = f(ek);
|
80
|
+
if (xk < pivotValue1) {
|
81
|
+
if (k !== less) {
|
82
|
+
a[k] = a[less];
|
83
|
+
a[less] = ek;
|
84
|
+
}
|
85
|
+
++less;
|
86
|
+
} else if (xk > pivotValue1) {
|
87
|
+
|
88
|
+
// Find the first element <= pivot in the range [k - 1, great] and
|
89
|
+
// put [:ek:] there. We know that such an element must exist:
|
90
|
+
// When k == less, then el3 (which is equal to pivot) lies in the
|
91
|
+
// interval. Otherwise a[k - 1] == pivot and the search stops at k-1.
|
92
|
+
// Note that in the latter case invariant 2 will be violated for a
|
93
|
+
// short amount of time. The invariant will be restored when the
|
94
|
+
// pivots are put into their final positions.
|
95
|
+
while (true) {
|
96
|
+
var greatValue = f(a[great]);
|
97
|
+
if (greatValue > pivotValue1) {
|
98
|
+
great--;
|
99
|
+
// This is the only location in the while-loop where a new
|
100
|
+
// iteration is started.
|
101
|
+
continue;
|
102
|
+
} else if (greatValue < pivotValue1) {
|
103
|
+
// Triple exchange.
|
104
|
+
a[k] = a[less];
|
105
|
+
a[less++] = a[great];
|
106
|
+
a[great--] = ek;
|
107
|
+
break;
|
108
|
+
} else {
|
109
|
+
a[k] = a[great];
|
110
|
+
a[great--] = ek;
|
111
|
+
// Note: if great < k then we will exit the outer loop and fix
|
112
|
+
// invariant 2 (which we just violated).
|
113
|
+
break;
|
114
|
+
}
|
115
|
+
}
|
116
|
+
}
|
117
|
+
}
|
118
|
+
} else {
|
119
|
+
|
120
|
+
// We partition the list into three parts:
|
121
|
+
// 1. < pivot1
|
122
|
+
// 2. >= pivot1 && <= pivot2
|
123
|
+
// 3. > pivot2
|
124
|
+
//
|
125
|
+
// During the loop we have:
|
126
|
+
// [ | < pivot1 | >= pivot1 && <= pivot2 | unpartitioned | > pivot2 | ]
|
127
|
+
// ^ ^ ^ ^ ^
|
128
|
+
// left less k great right
|
129
|
+
//
|
130
|
+
// a[left] and a[right] are undefined and are filled after the
|
131
|
+
// partitioning.
|
132
|
+
//
|
133
|
+
// Invariants:
|
134
|
+
// 1. for x in ]left, less[ : x < pivot1
|
135
|
+
// 2. for x in [less, k[ : pivot1 <= x && x <= pivot2
|
136
|
+
// 3. for x in ]great, right[ : x > pivot2
|
137
|
+
for (var k = less; k <= great; k++) {
|
138
|
+
var ek = a[k], xk = f(ek);
|
139
|
+
if (xk < pivotValue1) {
|
140
|
+
if (k !== less) {
|
141
|
+
a[k] = a[less];
|
142
|
+
a[less] = ek;
|
143
|
+
}
|
144
|
+
++less;
|
145
|
+
} else {
|
146
|
+
if (xk > pivotValue2) {
|
147
|
+
while (true) {
|
148
|
+
var greatValue = f(a[great]);
|
149
|
+
if (greatValue > pivotValue2) {
|
150
|
+
great--;
|
151
|
+
if (great < k) break;
|
152
|
+
// This is the only location inside the loop where a new
|
153
|
+
// iteration is started.
|
154
|
+
continue;
|
155
|
+
} else {
|
156
|
+
// a[great] <= pivot2.
|
157
|
+
if (greatValue < pivotValue1) {
|
158
|
+
// Triple exchange.
|
159
|
+
a[k] = a[less];
|
160
|
+
a[less++] = a[great];
|
161
|
+
a[great--] = ek;
|
162
|
+
} else {
|
163
|
+
// a[great] >= pivot1.
|
164
|
+
a[k] = a[great];
|
165
|
+
a[great--] = ek;
|
166
|
+
}
|
167
|
+
break;
|
168
|
+
}
|
169
|
+
}
|
170
|
+
}
|
171
|
+
}
|
172
|
+
}
|
173
|
+
}
|
174
|
+
|
175
|
+
// Move pivots into their final positions.
|
176
|
+
// We shrunk the list from both sides (a[left] and a[right] have
|
177
|
+
// meaningless values in them) and now we move elements from the first
|
178
|
+
// and third partition into these locations so that we can store the
|
179
|
+
// pivots.
|
180
|
+
a[lo] = a[less - 1];
|
181
|
+
a[less - 1] = pivot1;
|
182
|
+
a[hi - 1] = a[great + 1];
|
183
|
+
a[great + 1] = pivot2;
|
184
|
+
|
185
|
+
// The list is now partitioned into three partitions:
|
186
|
+
// [ < pivot1 | >= pivot1 && <= pivot2 | > pivot2 ]
|
187
|
+
// ^ ^ ^ ^
|
188
|
+
// left less great right
|
189
|
+
|
190
|
+
// Recursive descent. (Don't include the pivot values.)
|
191
|
+
sort(a, lo, less - 1);
|
192
|
+
sort(a, great + 2, hi);
|
193
|
+
|
194
|
+
if (pivotsEqual) {
|
195
|
+
// All elements in the second partition are equal to the pivot. No
|
196
|
+
// need to sort them.
|
197
|
+
return a;
|
198
|
+
}
|
199
|
+
|
200
|
+
// In theory it should be enough to call _doSort recursively on the second
|
201
|
+
// partition.
|
202
|
+
// The Android source however removes the pivot elements from the recursive
|
203
|
+
// call if the second partition is too large (more than 2/3 of the list).
|
204
|
+
if (less < i1 && great > i5) {
|
205
|
+
var lessValue, greatValue;
|
206
|
+
while ((lessValue = f(a[less])) <= pivotValue1 && lessValue >= pivotValue1) ++less;
|
207
|
+
while ((greatValue = f(a[great])) <= pivotValue2 && greatValue >= pivotValue2) --great;
|
208
|
+
|
209
|
+
// Copy paste of the previous 3-way partitioning with adaptions.
|
210
|
+
//
|
211
|
+
// We partition the list into three parts:
|
212
|
+
// 1. == pivot1
|
213
|
+
// 2. > pivot1 && < pivot2
|
214
|
+
// 3. == pivot2
|
215
|
+
//
|
216
|
+
// During the loop we have:
|
217
|
+
// [ == pivot1 | > pivot1 && < pivot2 | unpartitioned | == pivot2 ]
|
218
|
+
// ^ ^ ^
|
219
|
+
// less k great
|
220
|
+
//
|
221
|
+
// Invariants:
|
222
|
+
// 1. for x in [ *, less[ : x == pivot1
|
223
|
+
// 2. for x in [less, k[ : pivot1 < x && x < pivot2
|
224
|
+
// 3. for x in ]great, * ] : x == pivot2
|
225
|
+
for (var k = less; k <= great; k++) {
|
226
|
+
var ek = a[k], xk = f(ek);
|
227
|
+
if (xk <= pivotValue1 && xk >= pivotValue1) {
|
228
|
+
if (k !== less) {
|
229
|
+
a[k] = a[less];
|
230
|
+
a[less] = ek;
|
231
|
+
}
|
232
|
+
less++;
|
233
|
+
} else {
|
234
|
+
if (xk <= pivotValue2 && xk >= pivotValue2) {
|
235
|
+
while (true) {
|
236
|
+
var greatValue = f(a[great]);
|
237
|
+
if (greatValue <= pivotValue2 && greatValue >= pivotValue2) {
|
238
|
+
great--;
|
239
|
+
if (great < k) break;
|
240
|
+
// This is the only location inside the loop where a new
|
241
|
+
// iteration is started.
|
242
|
+
continue;
|
243
|
+
} else {
|
244
|
+
// a[great] < pivot2.
|
245
|
+
if (greatValue < pivotValue1) {
|
246
|
+
// Triple exchange.
|
247
|
+
a[k] = a[less];
|
248
|
+
a[less++] = a[great];
|
249
|
+
a[great--] = ek;
|
250
|
+
} else {
|
251
|
+
// a[great] == pivot1.
|
252
|
+
a[k] = a[great];
|
253
|
+
a[great--] = ek;
|
254
|
+
}
|
255
|
+
break;
|
256
|
+
}
|
257
|
+
}
|
258
|
+
}
|
259
|
+
}
|
260
|
+
}
|
261
|
+
}
|
262
|
+
|
263
|
+
// The second partition has now been cleared of pivot elements and looks
|
264
|
+
// as follows:
|
265
|
+
// [ * | > pivot1 && < pivot2 | * ]
|
266
|
+
// ^ ^
|
267
|
+
// less great
|
268
|
+
// Sort the second partition using recursive descent.
|
269
|
+
|
270
|
+
// The second partition looks as follows:
|
271
|
+
// [ * | >= pivot1 && <= pivot2 | * ]
|
272
|
+
// ^ ^
|
273
|
+
// less great
|
274
|
+
// Simply sort it by recursive descent.
|
275
|
+
|
276
|
+
return sort(a, less, great + 1);
|
277
|
+
}
|
278
|
+
|
279
|
+
return sort;
|
280
|
+
}
|
281
|
+
|
282
|
+
var quicksort_sizeThreshold = 32;
|