KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > logicalcobwebs > cglib > util > ParallelSorter


1 /*
2  * The Apache Software License, Version 1.1
3  *
4  * Copyright (c) 2003 The Apache Software Foundation. All rights
5  * reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright
12  * notice, this list of conditions and the following disclaimer.
13  *
14  * 2. Redistributions in binary form must reproduce the above copyright
15  * notice, this list of conditions and the following disclaimer in
16  * the documentation and/or other materials provided with the
17  * distribution.
18  *
19  * 3. The end-user documentation included with the redistribution,
20  * if any, must include the following acknowledgment:
21  * "This product includes software developed by the
22  * Apache Software Foundation (http://www.apache.org/)."
23  * Alternately, this acknowledgment may appear in the software itself,
24  * if and wherever such third-party acknowledgments normally appear.
25  *
26  * 4. The names "Apache" and "Apache Software Foundation" must
27  * not be used to endorse or promote products derived from this
28  * software without prior written permission. For written
29  * permission, please contact apache@apache.org.
30  *
31  * 5. Products derived from this software may not be called "Apache",
32  * nor may "Apache" appear in their name, without prior written
33  * permission of the Apache Software Foundation.
34  *
35  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
36  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
37  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
38  * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
39  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
41  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
42  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
43  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
44  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
45  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
46  * SUCH DAMAGE.
47  * ====================================================================
48  *
49  * This software consists of voluntary contributions made by many
50  * individuals on behalf of the Apache Software Foundation. For more
51  * information on the Apache Software Foundation, please see
52  * <http://www.apache.org/>.
53  */

54 package org.logicalcobwebs.cglib.util;
55
56 import java.lang.reflect.*;
57 import java.util.Comparator JavaDoc;
58 import org.logicalcobwebs.cglib.core.*;
59 import org.logicalcobwebs.asm.ClassVisitor;
60
61 /**
62  * For the efficient sorting of multiple arrays in parallel.
63  * <p>
64  * Given two arrays of equal length and varying types, the standard
65  * technique for sorting them in parallel is to create a new temporary
66  * object for each row, store the objects in a temporary array, sort the
67  * array using a custom comparator, and the extract the original values
68  * back into their respective arrays. This is wasteful in both time and
69  * memory.
70  * <p>
71  * This class generates bytecode customized to the particular set of
72  * arrays you need to sort, in such a way that both arrays are sorted
73  * in-place, simultaneously.
74  * <p>
75  * Two sorting algorithms are provided.
76  * Quicksort is best when you only need to sort by a single column, as
77  * it requires very few comparisons and swaps. Mergesort is best used
78  * when sorting multiple columns, as it is a "stable" sort--that is, it
79  * does not affect the relative order of equal objects from previous sorts.
80  * <p>
81  * The mergesort algorithm here is an "in-place" variant, which while
82  * slower, does not require a temporary array.
83  *
84  * @author Chris Nokleberg
85  */

86 abstract public class ParallelSorter extends SorterTemplate {
87     protected Object JavaDoc[] a;
88     private Comparer comparer;
89     
90     protected ParallelSorter() {
91     }
92
93     abstract public ParallelSorter newInstance(Object JavaDoc[] arrays);
94
95     /**
96      * Create a new ParallelSorter object for a set of arrays. You may
97      * sort the arrays multiple times via the same ParallelSorter object.
98      * @param arrays An array of arrays to sort. The arrays may be a mix
99      * of primitive and non-primitive types, but should all be the same
100      * length.
101      * @param loader ClassLoader for generated class, uses "current" if null
102      */

103     public static ParallelSorter create(Object JavaDoc[] arrays) {
104         Generator gen = new Generator();
105         gen.setArrays(arrays);
106         return gen.create();
107     }
108
109     private int len() {
110         return ((Object JavaDoc[])a[0]).length;
111     }
112
113     /**
114      * Sort the arrays using the quicksort algorithm.
115      * @param index array (column) to sort by
116      */

117     public void quickSort(int index) {
118         quickSort(index, 0, len(), null);
119     }
120
121     /**
122      * Sort the arrays using the quicksort algorithm.
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 quickSort(int index, int lo, int hi) {
128         quickSort(index, lo, hi, null);
129     }
130
131     /**
132      * Sort the arrays using the quicksort algorithm.
133      * @param index array (column) to sort by
134      * @param cmp Comparator to use if the specified column is non-primitive
135      */

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

147     public void quickSort(int index, int lo, int hi, Comparator JavaDoc cmp) {
148         chooseComparer(index, cmp);
149         super.quickSort(lo, hi - 1);
150     }
151
152     /**
153      * @param index array (column) to sort by
154      */

155     public void mergeSort(int index) {
156         mergeSort(index, 0, len(), null);
157     }
158
159     /**
160      * Sort the arrays using an in-place merge sort.
161      * @param index array (column) to sort by
162      * @param lo starting array index (row), inclusive
163      * @param hi ending array index (row), exclusive
164      */

165     public void mergeSort(int index, int lo, int hi) {
166         mergeSort(index, lo, hi, null);
167     }
168
169     /**
170      * Sort the arrays using an in-place merge sort.
171      * @param index array (column) to sort by
172      * @param lo starting array index (row), inclusive
173      * @param hi ending array index (row), exclusive
174      */

175     public void mergeSort(int index, Comparator JavaDoc cmp) {
176         mergeSort(index, 0, len(), cmp);
177     }
178
179     /**
180      * Sort the arrays using an in-place merge sort.
181      * @param index array (column) to sort by
182      * @param lo starting array index (row), inclusive
183      * @param hi ending array index (row), exclusive
184      * @param cmp Comparator to use if the specified column is non-primitive
185      */

186     public void mergeSort(int index, int lo, int hi, Comparator JavaDoc cmp) {
187         chooseComparer(index, cmp);
188         super.mergeSort(lo, hi - 1);
189     }
190     
191     private void chooseComparer(int index, Comparator JavaDoc cmp) {
192         Object JavaDoc array = a[index];
193         Class JavaDoc type = array.getClass().getComponentType();
194         if (type.equals(Integer.TYPE)) {
195             comparer = new IntComparer((int[])array);
196         } else if (type.equals(Long.TYPE)) {
197             comparer = new LongComparer((long[])array);
198         } else if (type.equals(Double.TYPE)) {
199             comparer = new DoubleComparer((double[])array);
200         } else if (type.equals(Float.TYPE)) {
201             comparer = new FloatComparer((float[])array);
202         } else if (type.equals(Short.TYPE)) {
203             comparer = new ShortComparer((short[])array);
204         } else if (type.equals(Byte.TYPE)) {
205             comparer = new ByteComparer((byte[])array);
206         } else if (cmp != null) {
207             comparer = new ComparatorComparer((Object JavaDoc[])array, cmp);
208         } else {
209             comparer = new ObjectComparer((Object JavaDoc[])array);
210         }
211     }
212
213     protected int compare(int i, int j) {
214         return comparer.compare(i, j);
215     }
216
217     interface Comparer {
218         int compare(int i, int j);
219     }
220
221     static class ComparatorComparer implements Comparer {
222         private Object JavaDoc[] a;
223         private Comparator JavaDoc cmp;
224
225         public ComparatorComparer(Object JavaDoc[] a, Comparator JavaDoc cmp) {
226             this.a = a;
227             this.cmp = cmp;
228         }
229
230         public int compare(int i, int j) {
231             return cmp.compare(a[i], a[j]);
232         }
233     }
234     
235     static class ObjectComparer implements Comparer {
236         private Object JavaDoc[] a;
237         public ObjectComparer(Object JavaDoc[] a) { this.a = a; }
238         public int compare(int i, int j) {
239             return ((Comparable JavaDoc)a[i]).compareTo(a[j]);
240         }
241     }
242
243     static class IntComparer implements Comparer {
244         private int[] a;
245         public IntComparer(int[] a) { this.a = a; }
246         public int compare(int i, int j) { return a[i] - a[j]; }
247     }
248
249     static class LongComparer implements Comparer {
250         private long[] a;
251         public LongComparer(long[] a) { this.a = a; }
252         public int compare(int i, int j) {
253             long vi = a[i];
254             long vj = a[j];
255             return (vi == vj) ? 0 : (vi > vj) ? 1 : -1;
256         }
257     }
258
259     static class FloatComparer implements Comparer {
260         private float[] a;
261         public FloatComparer(float[] a) { this.a = a; }
262         public int compare(int i, int j) {
263             float vi = a[i];
264             float vj = a[j];
265             return (vi == vj) ? 0 : (vi > vj) ? 1 : -1;
266         }
267     }
268     
269     static class DoubleComparer implements Comparer {
270         private double[] a;
271         public DoubleComparer(double[] a) { this.a = a; }
272         public int compare(int i, int j) {
273             double vi = a[i];
274             double vj = a[j];
275             return (vi == vj) ? 0 : (vi > vj) ? 1 : -1;
276         }
277     }
278
279     static class ShortComparer implements Comparer {
280         private short[] a;
281         public ShortComparer(short[] a) { this.a = a; }
282         public int compare(int i, int j) { return a[i] - a[j]; }
283     }
284
285     static class ByteComparer implements Comparer {
286         private byte[] a;
287         public ByteComparer(byte[] a) { this.a = a; }
288         public int compare(int i, int j) { return a[i] - a[j]; }
289     }
290
291     public static class Generator extends AbstractClassGenerator {
292         private static final Source SOURCE = new Source(ParallelSorter.class.getName());
293
294         private Object JavaDoc[] arrays;
295
296         public Generator() {
297             super(SOURCE);
298         }
299
300         protected ClassLoader JavaDoc getDefaultClassLoader() {
301             return null; // TODO
302
}
303
304         public void setArrays(Object JavaDoc[] arrays) {
305             this.arrays = arrays;
306         }
307
308         public ParallelSorter create() {
309             return (ParallelSorter)super.create(ClassesKey.create(arrays));
310         }
311
312         public void generateClass(ClassVisitor v) throws Exception JavaDoc {
313             if (arrays.length == 0) {
314                 throw new IllegalArgumentException JavaDoc("No arrays specified to sort");
315             }
316             for (int i = 0; i < arrays.length; i++) {
317                 if (!arrays[i].getClass().isArray()) {
318                     throw new IllegalArgumentException JavaDoc(arrays[i].getClass() + " is not an array");
319                 }
320             }
321             new ParallelSorterEmitter(v, getClassName(), arrays);
322         }
323         
324         protected Object JavaDoc firstInstance(Class JavaDoc type) {
325             return ((ParallelSorter)ReflectUtils.newInstance(type)).newInstance(arrays);
326         }
327
328         protected Object JavaDoc nextInstance(Object JavaDoc instance) {
329             return ((ParallelSorter)instance).newInstance(arrays);
330         }
331     }
332 }
333
Popular Tags