github.com/balzaczyy/golucene@v0.0.0-20151210033525-d0be9ee89713/core/util/array.go (about) 1 package util 2 3 import ( 4 "math" 5 "sort" 6 ) 7 8 // util/ArrayUtil.java 9 10 /* Maximum length for an array */ 11 const MAX_ARRAY_LENGTH = math.MaxInt32 - NUM_BYTES_ARRAY_HEADER 12 13 // L152 14 /** Returns an array size >= minTargetSize, generally 15 * over-allocating exponentially to achieve amortized 16 * linear-time cost as the array grows. 17 * 18 * NOTE: this was originally borrowed from Python 2.4.2 19 * listobject.c sources (attribution in LICENSE.txt), but 20 * has now been substantially changed based on 21 * discussions from java-dev thread with subject "Dynamic 22 * array reallocation algorithms", started on Jan 12 23 * 2010. 24 * 25 * @param minTargetSize Minimum required value to be returned. 26 * @param bytesPerElement Bytes used by each element of 27 * the array. See constants in {@link RamUsageEstimator}. 28 * 29 * @lucene.internal 30 */ 31 func Oversize(minTargetSize int, bytesPerElement int) int { 32 // catch usage that accidentally overflows int 33 assert2(minTargetSize >= 0, "invalid array size %v", minTargetSize) 34 35 if minTargetSize == 0 { 36 // wait until at least one element is requested 37 return 0 38 } 39 40 assert2(minTargetSize <= MAX_ARRAY_LENGTH, 41 "requested array size %v exceeds maximum array in Go (%v)", MAX_ARRAY_LENGTH) 42 43 // asymptotic exponential growth by 1/8th, favors 44 // spending a bit more CPU to not tie up too much wasted 45 // RAM: 46 extra := minTargetSize >> 3 47 if extra < 3 { 48 // for very small arrays, where constant overhead of 49 // realloc is presumably relatively high, we grow 50 // faster 51 extra = 3 52 } 53 54 newSize := minTargetSize + extra 55 // add 7 to allow for worst case byte alignment addition below: 56 if n := int32(newSize + 7); n < 0 || n > MAX_ARRAY_LENGTH { 57 // int overflowed, or we exceeded the maximum array length 58 return MAX_ARRAY_LENGTH 59 } 60 61 // Lucene support 32bit/64bit detection 62 // However I assume golucene in 64bit only 63 // if is64bit { 64 // round up to 8 byte alignment in 64bit env 65 switch bytesPerElement { 66 case 4: 67 // round up to multiple of 2 68 return (newSize + 1) & 0x7ffffffe 69 case 2: 70 // round up to multiple of 4 71 return (newSize + 3) & 0x7ffffffc 72 case 1: 73 // round up to multiple of 8 74 return (newSize + 7) & 0x7ffffff8 75 case 8: 76 // no rounding 77 return newSize 78 default: 79 // odd (invalid?) size 80 return newSize 81 } 82 // } 83 } 84 85 // L285 86 func GrowIntSlice(arr []int, minSize int) []int { 87 assert2(minSize >= 0, "size must be positive (got %v): likely integer overflow?", minSize) 88 if len(arr) < minSize { 89 newArr := make([]int, Oversize(minSize, NUM_BYTES_INT)) 90 copy(newArr, arr) 91 return newArr 92 } 93 return arr 94 } 95 96 // L343 97 func GrowByteSlice(arr []byte, minSize int) []byte { 98 assert2(minSize >= 0, "size must be positive (got %v): likely integer overflow?", minSize) 99 if cap(arr) < minSize { 100 newArr := make([]byte, Oversize(minSize, 1)) 101 copy(newArr, arr) 102 return newArr[:minSize] 103 } 104 for len(arr) < minSize { 105 arr = append(arr, 0) 106 } 107 return arr 108 } 109 110 // L699 111 /* 112 Sorts the given array slice in its own order. This method uses the 113 Tim sort algorithm, but falls back to binary sort for small arrays. 114 */ 115 func TimSort(data sort.Interface) { 116 newArrayTimSorter(data, data.Len()/64).sort(0, data.Len()) 117 } 118 119 // util/ArrayTimSorter.java 120 121 // A TimSorter for object arrays 122 type ArrayTimSorter struct { 123 *TimSorter 124 arr sort.Interface 125 tmp []interface{} 126 } 127 128 // Create a new ArrayTimSorter 129 func newArrayTimSorter(arr sort.Interface, maxTempSlots int) *ArrayTimSorter { 130 ans := &ArrayTimSorter{ 131 TimSorter: newTimSorter(arr, maxTempSlots), 132 arr: arr, 133 } 134 if maxTempSlots > 0 { 135 ans.tmp = make([]interface{}, maxTempSlots) 136 } 137 return ans 138 }