/* * Copyright 2004-2011 H2 Group. Multiple-Licensed under the H2 License, * Version 1.0, and under the Eclipse Public License, Version 1.0 * (http://h2database.com/html/license.html). * Initial Developer: H2 Group */ package org.h2.test.unit; import java.util.Arrays; import java.util.Comparator; import java.util.Random; import java.util.concurrent.atomic.AtomicInteger; import org.h2.dev.sort.InPlaceStableMergeSort; import org.h2.dev.sort.InPlaceStableQuicksort; import org.h2.test.TestBase; /** * Tests the stable in-place sorting implementations. */ public class TestSort extends TestBase { /** * The number of times the compare method was called. */ AtomicInteger compareCount = new AtomicInteger(); /** * The comparison object used in this test. */ Comparator<Long> comp = new Comparator<Long>() { public int compare(Long o1, Long o2) { compareCount.incrementAndGet(); return Long.valueOf(o1 >> 32).compareTo(o2 >> 32); } }; private Long[] array = new Long[100000]; private Class<?> clazz; /** * Run just this test. * * @param a ignored */ public static void main(String... a) throws Exception { TestBase.createCaller().init().test(); } public void test() throws Exception { test(InPlaceStableMergeSort.class); test(InPlaceStableQuicksort.class); test(Arrays.class); } private void test(Class<?> c) throws Exception { this.clazz = c; ordered(array); shuffle(array); stabilize(array); test("random"); ordered(array); stabilize(array); test("ordered"); ordered(array); reverse(array); stabilize(array); test("reverse"); ordered(array); stretch(array); shuffle(array); stabilize(array); test("few random"); ordered(array); stretch(array); stabilize(array); test("few ordered"); ordered(array); reverse(array); stretch(array); stabilize(array); test("few reverse"); // System.out.println(); } /** * Sort the array and verify the result. * * @param type the type of data */ private void test(String type) throws Exception { compareCount.set(0); // long t = System.currentTimeMillis(); clazz.getMethod("sort", Object[].class, Comparator.class).invoke(null, array, comp); // System.out.printf( // "%4d ms; %10d comparisons order: %s data: %s\n", // (System.currentTimeMillis() - t), // compareCount.get(), clazz, type); verify(array); } private static void verify(Long[] array) { long last = Long.MIN_VALUE; int len = array.length; for (int i = 0; i < len; i++) { long x = array[i]; long x1 = x >> 32, x2 = x - (x1 << 32); long last1 = last >> 32, last2 = last - (last1 << 32); if (x1 < last1) { if (array.length < 1000) { System.out.println(Arrays.toString(array)); } throw new RuntimeException("" + x); } else if (x1 == last1 && x2 < last2) { if (array.length < 1000) { System.out.println(Arrays.toString(array)); } throw new RuntimeException("" + x); } last = x; } } private static void ordered(Long[] array) { for (int i = 0; i < array.length; i++) { array[i] = (long) i; } } private static void stretch(Long[] array) { for (int i = array.length - 1; i >= 0; i--) { array[i] = array[i / 4]; } } private static void reverse(Long[] array) { for (int i = 0; i < array.length / 2; i++) { long temp = array[i]; array[i] = array[array.length - i - 1]; array[array.length - i - 1] = temp; } } private static void shuffle(Long[] array) { Random r = new Random(1); for (int i = 0; i < array.length; i++) { long temp = array[i]; int j = r.nextInt(array.length); array[j] = array[i]; array[i] = temp; } } private static void stabilize(Long[] array) { for (int i = 0; i < array.length; i++) { array[i] = (array[i] << 32) + i; } } }