CLucene - a full-featured, c++ search engine
API Documentation
00001 /*------------------------------------------------------------------------------ 00002 * Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team 00003 * 00004 * Distributable under the terms of either the Apache License (Version 2.0) or 00005 * the GNU Lesser General Public License, as specified in the COPYING file. 00006 ------------------------------------------------------------------------------*/ 00007 #ifndef _lucene_util_Arrays_ 00008 #define _lucene_util_Arrays_ 00009 00010 #if defined(_LUCENE_PRAGMA_ONCE) 00011 # pragma once 00012 #endif 00013 00014 #include "VoidList.h" 00015 00016 CL_NS_DEF(util) 00017 class Arrays{ 00018 public: 00019 template<typename _type> 00020 class _Arrays { 00021 protected: 00022 //used by binarySearch to check for equality 00023 virtual bool equals(_type a,_type b) const = 0; 00024 virtual int32_t compare(_type a,_type b) const = 0; 00025 public: 00026 virtual ~_Arrays(){ 00027 } 00028 00029 void sort(_type* a, int32_t alen, int32_t fromIndex, int32_t toIndex) const{ 00030 CND_PRECONDITION(fromIndex < toIndex,"fromIndex >= toIndex"); 00031 CND_PRECONDITION(fromIndex >= 0,"fromIndex < 0"); 00032 00033 // First presort the array in chunks of length 6 with insertion 00034 // sort. A mergesort would give too much overhead for this length. 00035 for (int32_t chunk = fromIndex; chunk < toIndex; chunk += 6) 00036 { 00037 int32_t end = min(chunk + 6, toIndex); 00038 for (int32_t i = chunk + 1; i < end; i++) 00039 { 00040 if (compare(a[i - 1], a[i]) > 0) 00041 { 00042 // not already sorted 00043 int32_t j = i; 00044 _type elem = a[j]; 00045 do 00046 { 00047 a[j] = a[j - 1]; 00048 j--; 00049 } 00050 while (j > chunk && compare(a[j - 1], elem) > 0); 00051 a[j] = elem; 00052 } 00053 } 00054 } 00055 00056 int32_t len = toIndex - fromIndex; 00057 // If length is smaller or equal 6 we are done. 00058 if (len <= 6) 00059 return; 00060 00061 _type* src = a; 00062 _type* dest = _CL_NEWARRAY(_type,alen); 00063 _type* t = NULL; // t is used for swapping src and dest 00064 00065 // The difference of the fromIndex of the src and dest array. 00066 int32_t srcDestDiff = -fromIndex; 00067 00068 // The merges are done in this loop 00069 for (int32_t size = 6; size < len; size <<= 1) 00070 { 00071 for (int32_t start = fromIndex; start < toIndex; start += size << 1) 00072 { 00073 // mid is the start of the second sublist; 00074 // end the start of the next sublist (or end of array). 00075 int32_t mid = start + size; 00076 int32_t end = min(toIndex, mid + size); 00077 00078 // The second list is empty or the elements are already in 00079 // order - no need to merge 00080 if (mid >= end || compare(src[mid - 1], src[mid]) <= 0) 00081 { 00082 memcpy(dest + start + srcDestDiff, src+start, (end-start)*sizeof(_type)); 00083 }// The two halves just need swapping - no need to merge 00084 else if (compare(src[start], src[end - 1]) > 0) 00085 { 00086 memcpy(dest+end-size+srcDestDiff, src+start, size * sizeof(_type)); 00087 memcpy(dest+start+srcDestDiff, src+mid, (end-mid) * sizeof(_type)); 00088 00089 }else{ 00090 // Declare a lot of variables to save repeating 00091 // calculations. Hopefully a decent JIT will put these 00092 // in registers and make this fast 00093 int32_t p1 = start; 00094 int32_t p2 = mid; 00095 int32_t i = start + srcDestDiff; 00096 00097 // The main merge loop; terminates as soon as either 00098 // half is ended 00099 while (p1 < mid && p2 < end) 00100 { 00101 dest[i++] = src[(compare(src[p1], src[p2]) <= 0 00102 ? p1++ : p2++)]; 00103 } 00104 00105 // Finish up by copying the remainder of whichever half 00106 // wasn't finished. 00107 if (p1 < mid) 00108 memcpy(dest+i,src+p1, (mid-p1) * sizeof(_type)); 00109 else 00110 memcpy(dest+i,src+p2, (end-p2) * sizeof(_type)); 00111 } 00112 } 00113 // swap src and dest ready for the next merge 00114 t = src; 00115 src = dest; 00116 dest = t; 00117 fromIndex += srcDestDiff; 00118 toIndex += srcDestDiff; 00119 srcDestDiff = -srcDestDiff; 00120 } 00121 00122 // make sure the result ends up back in the right place. Note 00123 // that src and dest may have been swapped above, so src 00124 // contains the sorted array. 00125 if (src != a) 00126 { 00127 // Note that fromIndex == 0. 00128 memcpy(a+srcDestDiff,src,toIndex * sizeof(_type)); 00129 } 00130 } 00131 }; 00132 }; 00133 00134 template <typename _kt, typename _comparator, 00135 typename class1, typename class2> 00136 class CLListEquals: 00137 public CL_NS_STD(binary_function)<class1*,class2*,bool> 00138 { 00139 typedef typename class1::const_iterator _itr1; 00140 typedef typename class2::const_iterator _itr2; 00141 public: 00142 CLListEquals(){ 00143 } 00144 bool equals( class1* val1, class2* val2 ) const{ 00145 static _comparator comp; 00146 if ( val1 == val2 ) 00147 return true; 00148 size_t size = val1->size(); 00149 if ( size != val2->size() ) 00150 return false; 00151 00152 _itr1 itr1 = val1->begin(); 00153 _itr2 itr2 = val2->begin(); 00154 while ( --size >= 0 ){ 00155 if ( !comp(*itr1,*itr2) ) 00156 return false; 00157 itr1++; 00158 itr2++; 00159 } 00160 return true; 00161 } 00162 }; 00163 CL_NS_END 00164 #endif