KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sf > cglib > util > ParallelSorter


1 /*
2  * Copyright 2003 The Apache Software Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package net.sf.cglib.util;
17
18 import java.lang.reflect.*;
19 import java.util.Comparator JavaDoc;
20 import net.sf.cglib.core.*;
21 import org.objectweb.asm.ClassVisitor;
22
23 /**
24  * For the efficient sorting of multiple arrays in parallel.
25  * <p>
26  * Given two arrays of equal length and varying types, the standard
27  * technique for sorting them in parallel is to create a new temporary
28  * object for each row, store the objects in a temporary array, sort the
29  * array using a custom comparator, and the extract the original values
30  * back into their respective arrays. This is wasteful in both time and
31  * memory.
32  * <p>
33  * This class generates bytecode customized to the particular set of
34  * arrays you need to sort, in such a way that both arrays are sorted
35  * in-place, simultaneously.
36  * <p>
37  * Two sorting algorithms are provided.
38  * Quicksort is best when you only need to sort by a single column, as
39  * it requires very few comparisons and swaps. Mergesort is best used
40  * when sorting multiple columns, as it is a "stable" sort--that is, it
41  * does not affect the relative order of equal objects from previous sorts.
42  * <p>
43  * The mergesort algorithm here is an "in-place" variant, which while
44  * slower, does not require a temporary array.
45  *
46  * @author Chris Nokleberg
47  */

48 abstract public class ParallelSorter extends SorterTemplate {
49     protected Object JavaDoc[] a;
50     private Comparer comparer;
51     
52     protected ParallelSorter() {
53     }
54
55     abstract public ParallelSorter newInstance(Object JavaDoc[] arrays);
56
57     /**
58      * Create a new ParallelSorter object for a set of arrays. You may
59      * sort the arrays multiple times via the same ParallelSorter object.
60      * @param arrays An array of arrays to sort. The arrays may be a mix
61      * of primitive and non-primitive types, but should all be the same
62      * length.
63      * @param loader ClassLoader for generated class, uses "current" if null
64      */

65     public static ParallelSorter create(Object JavaDoc[] arrays) {
66         Generator gen = new Generator();
67         gen.setArrays(arrays);
68         return gen.create();
69     }
70
71     private int len() {
72         return ((Object JavaDoc[])a[0]).length;
73     }
74
75     /**
76      * Sort the arrays using the quicksort algorithm.
77      * @param index array (column) to sort by
78      */

79     public void quickSort(int index) {
80         quickSort(index, 0, len(), null);
81     }
82
83     /**
84      * Sort the arrays using the quicksort algorithm.
85      * @param index array (column) to sort by
86      * @param lo starting array index (row), inclusive
87      * @param hi ending array index (row), exclusive
88      */

89     public void quickSort(int index, int lo, int hi) {
90         quickSort(index, lo, hi, null);
91     }
92
93     /**
94      * Sort the arrays using the quicksort algorithm.
95      * @param index array (column) to sort by
96      * @param cmp Comparator to use if the specified column is non-primitive
97      */

98     public void quickSort(int index, Comparator JavaDoc cmp) {
99         quickSort(index, 0, len(), cmp);
100     }
101
102     /**
103      * Sort the arrays using the quicksort algorithm.
104      * @param index array (column) to sort by
105      * @param lo starting array index (row), inclusive
106      * @param hi ending array index (row), exclusive
107      * @param cmp Comparator to use if the specified column is non-primitive
108      */

109     public void quickSort(int index, int lo, int hi, Comparator JavaDoc cmp) {
110         chooseComparer(index, cmp);
111         super.quickSort(lo, hi - 1);
112     }
113
114     /**
115      * @param index array (column) to sort by
116      */

117     public void mergeSort(int index) {
118         mergeSort(index, 0, len(), null);
119     }
120
121     /**
122      * Sort the arrays using an in-place merge sort.
123      * @param index array (column) to sort by
124      * @param lo starting array index (row), inclusive
125      * @param hi ending array index (row), exclusive
126      */

127     public void mergeSort(int index, int lo, int hi) {
128         mergeSort(index, lo, hi, null);
129     }
130
131     /**
132      * Sort the arrays using an in-place merge sort.
133      * @param index array (column) to sort by
134      * @param lo starting array index (row), inclusive
135      * @param hi ending array index (row), exclusive
136      */

137     public void mergeSort(int index, Comparator JavaDoc cmp) {
138         mergeSort(index, 0, len(), cmp);
139     }
140
141     /**
142      * Sort the arrays using an in-place merge sort.
143      * @param index array (column) to sort by
144      * @param lo starting array index (row), inclusive
145      * @param hi ending array index (row), exclusive
146      * @param cmp Comparator to use if the specified column is non-primitive
147      */

148     public void mergeSort(int index, int lo, int hi, Comparator JavaDoc cmp) {
149         chooseComparer(index, cmp);
150         super.mergeSort(lo, hi - 1);
151     }
152     
153     private void chooseComparer(int index, Comparator JavaDoc cmp) {
154         Object JavaDoc array = a[index];
155         Class JavaDoc type = array.getClass().getComponentType();
156         if (type.equals(Integer.TYPE)) {
157             comparer = new IntComparer((int[])array);
158         } else if (type.equals(Long.TYPE)) {
159             comparer = new LongComparer((long[])array);
160         } else if (type.equals(Double.TYPE)) {
161             comparer = new DoubleComparer((double[])array);
162         } else if (type.equals(Float.TYPE)) {
163             comparer = new FloatComparer((float[])array);
164         } else if (type.equals(Short.TYPE)) {
165             comparer = new ShortComparer((short[])array);
166         } else if (type.equals(Byte.TYPE)) {
167             comparer = new ByteComparer((byte[])array);
168         } else if (cmp != null) {
169             comparer = new ComparatorComparer((Object JavaDoc[])array, cmp);
170         } else {
171             comparer = new ObjectComparer((Object JavaDoc[])array);
172         }
173     }
174
175     protected int compare(int i, int j) {
176         return comparer.compare(i, j);
177     }
178
179     interface Comparer {
180         int compare(int i, int j);
181     }
182
183     static class ComparatorComparer implements Comparer {
184         private Object JavaDoc[] a;
185         private Comparator JavaDoc cmp;
186
187         public ComparatorComparer(Object JavaDoc[] a, Comparator JavaDoc cmp) {
188             this.a = a;
189             this.cmp = cmp;
190         }
191
192         public int compare(int i, int j) {
193             return cmp.compare(a[i], a[j]);
194         }
195     }
196     
197     static class ObjectComparer implements Comparer {
198         private Object JavaDoc[] a;
199         public ObjectComparer(Object JavaDoc[] a) { this.a = a; }
200         public int compare(int i, int j) {
201             return ((Comparable JavaDoc)a[i]).compareTo(a[j]);
202         }
203     }
204
205     static class IntComparer implements Comparer {
206         private int[] a;
207         public IntComparer(int[] a) { this.a = a; }
208         public int compare(int i, int j) { return a[i] - a[j]; }
209     }
210
211     static class LongComparer implements Comparer {
212         private long[] a;
213         public LongComparer(long[] a) { this.a = a; }
214         public int compare(int i, int j) {
215             long vi = a[i];
216             long vj = a[j];
217             return (vi == vj) ? 0 : (vi > vj) ? 1 : -1;
218         }
219     }
220
221     static class FloatComparer implements Comparer {
222         private float[] a;
223         public FloatComparer(float[] a) { this.a = a; }
224         public int compare(int i, int j) {
225             float vi = a[i];
226             float vj = a[j];
227             return (vi == vj) ? 0 : (vi > vj) ? 1 : -1;
228         }
229     }
230     
231     static class DoubleComparer implements Comparer {
232         private double[] a;
233         public DoubleComparer(double[] a) { this.a = a; }
234         public int compare(int i, int j) {
235             double vi = a[i];
236             double vj = a[j];
237             return (vi == vj) ? 0 : (vi > vj) ? 1 : -1;
238         }
239     }
240
241     static class ShortComparer implements Comparer {
242         private short[] a;
243         public ShortComparer(short[] a) { this.a = a; }
244         public int compare(int i, int j) { return a[i] - a[j]; }
245     }
246
247     static class ByteComparer implements Comparer {
248         private byte[] a;
249         public ByteComparer(byte[] a) { this.a = a; }
250         public int compare(int i, int j) { return a[i] - a[j]; }
251     }
252
253     public static class Generator extends AbstractClassGenerator {
254         private static final Source SOURCE = new Source(ParallelSorter.class.getName());
255
256         private Object JavaDoc[] arrays;
257
258         public Generator() {
259             super(SOURCE);
260         }
261
262         protected ClassLoader JavaDoc getDefaultClassLoader() {
263             return null; // TODO
264
}
265
266         public void setArrays(Object JavaDoc[] arrays) {
267             this.arrays = arrays;
268         }
269
270         public ParallelSorter create() {
271             return (ParallelSorter)super.create(ClassesKey.create(arrays));
272         }
273
274         public void generateClass(ClassVisitor v) throws Exception JavaDoc {
275             if (arrays.length == 0) {
276                 throw new IllegalArgumentException JavaDoc("No arrays specified to sort");
277             }
278             for (int i = 0; i < arrays.length; i++) {
279                 if (!arrays[i].getClass().isArray()) {
280                     throw new IllegalArgumentException JavaDoc(arrays[i].getClass() + " is not an array");
281                 }
282             }
283             new ParallelSorterEmitter(v, getClassName(), arrays);
284         }
285         
286         protected Object JavaDoc firstInstance(Class JavaDoc type) {
287             return ((ParallelSorter)ReflectUtils.newInstance(type)).newInstance(arrays);
288         }
289
290         protected Object JavaDoc nextInstance(Object JavaDoc instance) {
291             return ((ParallelSorter)instance).newInstance(arrays);
292         }
293     }
294 }
295
Popular Tags