void fx_TypedArray_prototype_sort(txMachine* the)
{
	mxMutableTypedArrayDeclarations;
	txSlot* data = buffer->value.reference->next;
	txInteger delta = dispatch->value.typedArray.dispatch->size;
	txSlot* function = C_NULL;
	if (mxArgc > 0) {
		txSlot* slot = mxArgv(0);
		if (slot->kind != XS_UNDEFINED_KIND) {
			if (fxIsCallable(the, slot))
				function = slot;
			else
				mxTypeError("compare is no function");
		}
	}
	if (function) {
		/* like GCC qsort */
		#define COMPARE(INDEX) \
			fxCompareTypedArrayItem(the, function, dispatch, view, data, INDEX)
		#define MOVE(FROM,TO) \
			from = data->value.arrayBuffer.address + view->value.dataView.offset + ((FROM) * delta); \
			to = data->value.arrayBuffer.address + view->value.dataView.offset + ((TO) * delta); \
			for (k = 0; k < delta; k++) *to++ = *from++
		#define PUSH(INDEX) \
			mxPushUndefined(); \
			(*dispatch->value.typedArray.dispatch->getter)(the, data, view->value.dataView.offset + ((INDEX) * delta), the->stack, EndianNative)
		#define PULL(INDEX) \
			(*dispatch->value.typedArray.dispatch->setter)(the, data, view->value.dataView.offset + ((INDEX) * delta), the->stack++, EndianNative)
		if (length > 0) {
			txInteger i, j, k;
			txByte* from;
			txByte* to;
			if (length > mxSortThreshold) {
				txInteger lo = 0, hi = length - 1;
				txSortPartition stack[mxSortPartitionCount];
				txSortPartition *top = stack + 1;
				while (stack < top) {
					txIndex mid = lo + ((hi - lo) >> 1);
					PUSH(mid);
					if (COMPARE(lo) > 0) {
						MOVE(lo, mid);
						PULL(lo);
						PUSH(mid);
					}
					if (COMPARE(hi) < 0) {
						MOVE(hi, mid);
						PULL(hi);
						PUSH(mid);
						if (COMPARE(lo) > 0) {
							MOVE(lo, mid);
							PULL(lo);
							PUSH(mid);
						}
					}
					i = lo + 1;
					j = hi - 1;
					do {
						while ((COMPARE(i) < 0) && (i <= j)) i++;
						while ((COMPARE(j) > 0) && (i <= j)) j--;
						if (i < j) {
							PUSH(i);
							MOVE(j, i);
							PULL(j);
							i++;
							j--;
						}
						else if (i == j) {
							i++;
							j--;
							break;
						}
					} while (i <= j);
					if ((j - lo) <= mxSortThreshold) {
						if ((hi - i) <= mxSortThreshold) {
							top--;
							lo = top->lo; 
							hi = top->hi;
						}
						else {
							lo = i;
						}
					}
					else if ((hi - i) <= mxSortThreshold) {
						hi = j;
					}
					else if ((j - lo) > (hi - i)) {
						top->lo = lo;
						top->hi = j; 
						top++;
						lo = i;
					}
					else {
						top->lo = i;
						top->hi = hi; 
						top++;
						hi = j;
					}
					mxPop();
				}
			}
			for (i = 1; i < length; i++) {
				PUSH(i);
				for (j = i; (j > 0) && (COMPARE(j - 1) > 0); j--) {
					MOVE(j - 1, j);
				}	
				PULL(j);
			}
		}
	}
	else
		c_qsort(data->value.arrayBuffer.address, length, delta, dispatch->value.typedArray.dispatch->compare);
	mxResult->kind = mxThis->kind;
	mxResult->value = mxThis->value;
}
void fx_TypedArray_prototype_sort(txMachine* the)
{
	mxMutableTypedArrayDeclarations;
	txSlot* data = buffer->value.reference->next;
	txInteger delta = dispatch->value.typedArray.dispatch->size;
	txSlot* function = C_NULL;
	if (mxArgc > 0) {
		txSlot* slot = mxArgv(0);
		if (slot->kind != XS_UNDEFINED_KIND) {
			if (fxIsCallable(the, slot))
				function = slot;
			else
				mxTypeError("compare is no function");
		}
	}
	if (function) {
		 
		#define COMPARE(INDEX) \
			fxCompareTypedArrayItem(the, function, dispatch, view, data, INDEX)
		#define MOVE(FROM,TO) \
			from = data->value.arrayBuffer.address + view->value.dataView.offset + ((FROM) * delta); \
			to = data->value.arrayBuffer.address + view->value.dataView.offset + ((TO) * delta); \
			for (k = 0; k < delta; k++) *to++ = *from++
		#define PUSH(INDEX) \
			mxPushUndefined(); \
			(*dispatch->value.typedArray.dispatch->getter)(the, data, view->value.dataView.offset + ((INDEX) * delta), the->stack, EndianNative)
		#define PULL(INDEX) \
			(*dispatch->value.typedArray.dispatch->setter)(the, data, view->value.dataView.offset + ((INDEX) * delta), the->stack++, EndianNative)
		if (length > 0) {
			txInteger i, j, k;
			txByte* from;
			txByte* to;
			if (length > mxSortThreshold) {
				txInteger lo = 0, hi = length - 1;
				txSortPartition stack[mxSortPartitionCount];
				txSortPartition *top = stack + 1;
				while (stack < top) {
					txIndex mid = lo + ((hi - lo) >> 1);
					PUSH(mid);
					if (COMPARE(lo) > 0) {
						MOVE(lo, mid);
						PULL(lo);
						PUSH(mid);
					}
					if (COMPARE(hi) < 0) {
						MOVE(hi, mid);
						PULL(hi);
						PUSH(mid);
						if (COMPARE(lo) > 0) {
							MOVE(lo, mid);
							PULL(lo);
							PUSH(mid);
						}
					}
					i = lo + 1;
					j = hi - 1;
					do {
						while ((COMPARE(i) < 0) && (i <= j)) i++;
						while ((COMPARE(j) > 0) && (i <= j)) j--;
						if (i < j) {
							PUSH(i);
							MOVE(j, i);
							PULL(j);
							i++;
							j--;
						}
						else if (i == j) {
							i++;
							j--;
							break;
						}
					} while (i <= j);
					if ((j - lo) <= mxSortThreshold) {
						if ((hi - i) <= mxSortThreshold) {
							top--;
							lo = top->lo; 
							hi = top->hi;
						}
						else {
							lo = i;
						}
					}
					else if ((hi - i) <= mxSortThreshold) {
						hi = j;
					}
					else if ((j - lo) > (hi - i)) {
						top->lo = lo;
						top->hi = j; 
						top++;
						lo = i;
					}
					else {
						top->lo = i;
						top->hi = hi; 
						top++;
						hi = j;
					}
					mxPop();
				}
			}
			for (i = 1; i < length; i++) {
				PUSH(i);
				for (j = i; (j > 0) && (COMPARE(j - 1) > 0); j--) {
					MOVE(j - 1, j);
				}	
				PULL(j);
			}
		}
	}
	else
		c_qsort(data->value.arrayBuffer.address, length, delta, dispatch->value.typedArray.dispatch->compare);
	mxResult->kind = mxThis->kind;
	mxResult->value = mxThis->value;
}