PageRenderTime 58ms CodeModel.GetById 31ms app.highlight 23ms RepoModel.GetById 1ms app.codeStats 0ms

/runtime/array.d

http://github.com/wilkie/djehuty
D | 334 lines | 115 code | 30 blank | 189 comment | 20 complexity | 8d11c59bdffddcc59560f8a95208e873 MD5 | raw file
  1/*
  2 * array.d
  3 *
  4 * This module implements the runtime functions related
  5 * to arrays.
  6 *
  7 */
  8
  9module runtime.array;
 10
 11import core.unicode;
 12
 13import data.iterable;
 14
 15import runtime.common;
 16import math.random;
 17
 18import core.util;
 19import io.console;
 20
 21// Arrays in D are represented as such:
 22
 23// align(size_t.sizeof)
 24// struct Array {
 25//   size_t length;
 26//   void* ptr;
 27// }
 28
 29extern(C):
 30
 31// Description: This runtime function reverses a char array in place and is invoked with
 32//   the reverse property: array.reverse
 33// Returns: The reference to the input.
 34char[] _adReverseChar(char[] a) {
 35	return a.reverse();
 36}
 37
 38// Description: This runtime function reverses a wchar array in place and is invoked with
 39//   the reverse property: array.reverse
 40// Returns: The reference to the input.
 41wchar[] _adReverseWchar(wchar[] a) {
 42	return a.reverse();
 43}
 44
 45// Description: This runtime function reverses an array in place and
 46//   is invoked with the reverse property: array.reverse
 47// array: The generic array struct that contains the array items.
 48// elementSize: The size of an individual element.
 49// Returns: The reference to the input.
 50void[] _adReverse(ubyte[] array, size_t elementSize) {
 51	size_t front, end;
 52
 53	// Go from front to end, and swap each index
 54
 55	// Note: Since the array passed has a length measured in a factor
 56	//   of elementSize, we need to account for that when we treat
 57	//   it is a byte array.
 58
 59	if (array.length == 0) {
 60		return array;
 61	}
 62
 63	front = 0;
 64	end = array.length * elementSize;
 65	ubyte[] cmp = (array.ptr)[0..end];
 66	end -= elementSize;
 67
 68	while(front < end) {
 69		for(size_t i=0; i < elementSize; i++) {
 70			// xor swap elements
 71			cmp[i+front] ^= cmp[i+end];
 72			cmp[i+end] ^= cmp[i+front];
 73			cmp[i+front] ^= cmp[i+end];
 74		}
 75		front += elementSize;
 76		end -= elementSize;
 77	}
 78
 79	return array;
 80}
 81
 82// Description: This runtime function will compare two arrays.
 83// Returns: 0 when equal, positive when first array is larger, negative otherwise.
 84int _adCmp(void[] a1, void[] a2, TypeInfo ti) {
 85	return ti.compare(&a1, &a2);
 86}
 87
 88// Description: This runtime function will compare two utf8 arrays.
 89// Returns: 0 when equal, positive when first array is larger, negative otherwise.
 90int _adCmpChar(void[] a1, void[] a2) {
 91	return _adCmp(a1, a2, typeid(char));
 92}
 93
 94// Description: This runtime function will compare two arrays for equality.
 95// Returns: 1 when equal, 0 otherwise
 96int _adEq(void[] a1, void[] a2, TypeInfo ti) {
 97	return ti.equals(&a1, &a2);
 98}
 99
100// Description: This runtime function sorts an array and is invoked with
101// the sort property: array.sort
102ubyte[] _adSort(ubyte[] array, TypeInfo ti) {
103	ubyte[] cmp = (array.ptr)[0..array.length * ti.tsize()];
104	_qsort(cmp, ti.tsize(), ti);
105	return array;
106}
107
108// Special quicksort implementation
109private void _qsort(ubyte[] array, size_t size, TypeInfo ti, Random rnd = null) {
110	if (rnd is null) {
111		rnd = new Random();
112	}
113
114	// Base case
115	if ((array.length/size) < 2) {
116		return;
117	}
118
119	// Selecting a pivot
120	size_t length = array.length / size;
121	size_t element = cast(size_t)rnd.nextLong(length);
122	element *= size;
123	//Console.putln("pivot: ", element/size, " array.length: ", array.length/size);
124
125	// Move things
126	size_t end = array.length - size;
127	for(size_t i = 0; i < array.length; i += size) {
128		if (i == element) {
129			continue;
130		}
131		if (i > end) {
132			break;
133		}
134		// compare array[i..i+size] to array[element..element+size]
135		// if < and i < element
136		//    Just continue (this is normal)
137		// if < and i > element
138		//    Swap i and element ('i' can only be the next element, that is, element+size)
139		// if > and end == element
140		//    Swap i and element (This will place element to the left of 'i'), decrement end
141		// if > and end > element
142		//    Swap i with end, decrement end (this is normal)
143		int cmp = ti.compare(&array[i], &array[element]);
144		//Console.putln("comparing ", i/size, " against ", element/size, " : ", cmp);
145		if (cmp < 0) {
146			// array[i] < array[element]
147			if (i > element) {
148				// swap with element
149				for(size_t idx; idx < size; idx++) {
150					array[i+idx] ^= array[element+idx];
151					array[element+idx] ^= array[i+idx];
152					array[i+idx] ^= array[element+idx];
153				}
154				element = i;
155			}
156		}
157		else if (cmp > 0) {
158			if (end > element) {
159				if (end != i) {
160					for(size_t idx; idx < size; idx++) {
161						array[i+idx] ^= array[end+idx];
162						array[end+idx] ^= array[i+idx];
163						array[i+idx] ^= array[end+idx];
164					}
165				}
166				// we need to compare with the item at end
167				i -= size;
168			}
169			else {
170				// swap with element
171				for(size_t idx; idx < size; idx++) {
172					array[i+idx] ^= array[element+idx];
173					array[element+idx] ^= array[i+idx];
174					array[i+idx] ^= array[element+idx];
175				}
176				element = i;
177			}
178			end -= size;
179		}
180	}
181
182	_qsort(array[0..element], size, ti, rnd);
183	_qsort(array[element+size..$], size, ti, rnd);
184}//*/
185
186// Description: This runtime function sorts a char array and is invoked with
187// the sort property: array.sort
188ubyte[] _adSortChar(ubyte[] array) {
189	return _adSort(array, typeid(char[]));
190}
191
192// Description: This runtime function sorts a wchar array and is invoked with
193// the sort property: array.sort
194ubyte[] _adSortWchar(ubyte[] array) {
195	return _adSort(array, typeid(wchar[]));
196}
197
198private template _array_init(T) {
199	void _array_init(T[] array, T value) {
200		foreach(ref element; array) {
201			element = value;
202		}
203	}
204}
205
206/*
207void _d_array_init_i1(bool* array, size_t length, bool value) {
208	_array_init(array[0..length], value);
209}
210
211void _d_array_init_i8(ubyte[] array, ubyte value) {
212	_array_init(array[0..length], value);
213}
214
215void _d_array_init_i16(ushort[] array, ushort value) {
216	_array_init(array[0..length], value);
217}
218
219void _d_array_init_i32(uint[] array, uint value) {
220	_array_init(array[0..length], value);
221}
222
223void _d_array_init_i64(ulong[] array, ulong value) {
224	_array_init(array[0..length], value);
225}
226
227void _d_array_init_float(float[] array, float value) {
228	_array_init(array[0..length], value);
229}
230
231void _d_array_init_double(double* array, size_t length, double value) {
232	_array_init(array[0..length], value);
233}
234
235void _d_array_init_pointer(void** array, size_t length, void* value) {
236	_array_init(array[0..length], value);
237}
238
239void _d_array_init_mem(ubyte* array, size_t length, ubyte* value, size_t valueLength) {
240	if (valueLength == 0 || length == 0) {
241		return;
242	}
243
244	ubyte[] cmp = array[0..length*valueLength];
245
246	size_t valueIndex = 0;
247	foreach(ref element; cmp) {
248		element = value[valueIndex];
249		valueIndex++;
250		if (valueIndex == valueLength) {
251			valueIndex = 0;
252		}
253	}
254}
255//*/
256
257/*
258size_t _d_array_cast_len(size_t length, size_t elementSize, size_t newElementSize) {
259	if (newElementSize == 1) {
260		return length * elementSize;
261	}
262	else if (length % newElementSize != 0) {
263		// Probably bad
264	}
265
266	return (length * elementSize) / newElementSize;
267}
268
269// Description: This runtime function will simply set the length to reflect storing a different type.
270void[] _d_arraycast(size_t toElementSize, size_t fromElementSize, void[] array) {
271	if (toElementSize == fromElementSize) {
272		return array;
273	}
274
275	if (toElementSize == 0) {
276		// Technically does not divide evenly
277		throw new Exception("Array cast misalignment");
278	}
279
280	size_t numbytes = array.length * fromElementSize;
281
282	// Can we divide this array up into equal parts of the new elements?
283	if (numbytes % toElementSize != 0) {
284		// Error
285		throw new Exception("Array cast misalignment");
286	}
287	
288	size_t newLength = numbytes / toElementSize;
289
290	// Set the new length
291	*cast(size_t*)&array = newLength;
292	return array;
293}
294
295byte[] _d_arraycopy(size_t size, byte[] from, byte[] to) {
296	// The arrays should be of equal size
297	if (to.length != from.length) {
298		throw new Exception("Length mismatch for array copy");
299	}
300
301	// Get the memory bounds for the array
302	byte* toEnd = to.ptr + (to.length * size);
303	byte* fromEnd = from.ptr + (from.length * size);
304
305	// Check for overlapping copy
306	if (toEnd > from.ptr && fromEnd > to.ptr) {
307		// Overlapping...
308		throw new Exception("Array copy overlaps");
309	}
310
311	// Perform the copy
312	foreach(size_t idx, ref element; to) {
313		element = from[idx];
314	}
315
316	return to;
317}
318
319void _d_array_slice_copy(ubyte* dst, size_t dstLength, ubyte* src, size_t srcLength) {
320	if (dstLength != srcLength) {
321		throw new Exception("Length mismatch for array copy");
322	}
323	
324	if (dst + dstLength > src && src + srcLength > dst) {
325		// Overlapping copy
326		throw new Exception("Array copy overlaps");
327	}
328
329	// Perform the copy
330	foreach(size_t idx, ref element; dst[0..dstLength]) {
331		element = src[idx];
332	}
333}
334//*/