<commit_before>/*
    Weave (Web-based Analysis and Visualization Environment)
    Copyright (C) 2008-2011 University of Massachusetts Lowell

    This file is a part of Weave.

    Weave is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License, Version 3,
    as published by the Free Software Foundation.

    Weave is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with Weave.  If not, see <http://www.gnu.org/licenses/>.
*/

package weave.utils
{
	import flash.utils.getTimer;
	
	import mx.utils.ObjectUtil;
	
	import weave.api.core.ILinkableObject;
	import weave.api.getCallbackCollection;
	
	/**
	 * Asynchronous merge sort.
	 * 
	 * @author adufilie
	 */
	public class AsyncSort implements ILinkableObject
	{
		public static var debug:Boolean = false;
		
		private static var _immediateSorter:AsyncSort; // used by sortImmediately()
		
		/**
		 * This function will sort an Array (or Vector) immediately.
		 * @param array An Array (or Vector) to sort in place.
		 * @param compareFunction The function used to compare items in the array.
		 */
		public static function sortImmediately(array:*, compareFunction:Function = null):void
		{
			if (!_immediateSorter)
			{
				_immediateSorter = new AsyncSort();
				_immediateSorter._immediately = true;
			}
			
			// temporarily set _immediateSorter to null in case sortImmediately is called recursively.
			var sorter:AsyncSort = _immediateSorter;
			_immediateSorter = null;
			
			sorter.beginSort(array, compareFunction);
			
			_immediateSorter = sorter;
		}
		
		/**
		 * This function is a wrapper for ObjectUtil.stringCompare(a, b, true) (case-insensitive String compare).
		 */		
		public static function compareCaseInsensitive(a:String, b:String):int
		{
			return ObjectUtil.stringCompare(a, b, true);
		}
		
		/**
		 * Compares two primitive values.
		 * This function is faster than ObjectUtil.compare(), but does not do deep object compare.
		 */
		public static function primitiveCompare(a:*, b:*):int
		{
			if (a === b)
				return 0;
			if (a == null)
				return 1;
			if (b == null)
				return -1;
			var typeA:String = typeof(a);
			var typeB:String = typeof(b);
			if (typeA != typeB)
				return ObjectUtil.stringCompare(typeA, typeB);
			if (typeA == 'boolean')
				return ObjectUtil.numericCompare(Number(a), Number(b));
			if (typeA == 'number')
				return ObjectUtil.numericCompare(a as Number, b as Number);
			if (typeA == 'string')
				return ObjectUtil.stringCompare(a as String, b as String);
			if (a is Date && b is Date)
				return ObjectUtil.dateCompare(a as Date, b as Date);
			return 1; // not equal
		}
		
		public function AsyncSort():void
		{
		}
		
		/**
		 * This is the sorted Array (or Vector), or null if the sort operation has not completed yet.
		 */
		public function get result():*
		{
			return source ? null : original;
		}
		
		private var original:*; // original array
		private var source:*; // contains sub-arrays currently being merged
		private var destination:*; // buffer to store merged sub-arrays
		private var compare:Function; // compares two array items
		private var length:uint; // length of original array
		private var subArraySize:uint; // size of sub-array
		private var middle:uint; // end of left and start of right sub-array
		private var end:uint; // end of right sub-array
		private var iLeft:uint; // left sub-array source index
		private var iRight:uint; // right sub-array source index
		private var iMerged:uint; // merged destination index
		private var elapsed:int; // keeps track of elapsed time inside iterate()
		private var _immediately:Boolean = false; // set in sortImmediately(), checked in beginSort()
		
		/**
		 * This will begin an asynchronous sorting operation on the specified Array (or Vector).
		 * Only one sort operation can be carried out at a time.
		 * Callbacks will be triggered when the sorting operation completes.
		 * The given Array (or Vector) will be modified in-place.
		 * @param arrayToSort The Array (or Vector) to sort.
		 * @param compareFunction A function that compares two items and returns -1, 0, or 1.
		 * @see mx.utils.ObjectUtil#compare()
		 */
		public function beginSort(arrayToSort:*, compareFunction:Function = null):void
		{
			// initialize
			compare = compareFunction;
			original = arrayToSort || [];
			source = original;
			length = original.length;
			
			// make a buffer of the same type and length
			var Type:Class = (source as Object).constructor;
			destination = new Type();
			destination.length = length;
			
			subArraySize = 1;
			iLeft = 0;
			iRight = 0;
			middle = 0;
			end = 0;
			elapsed = 0;
			
			if (_immediately)
			{
				iterate(int.MAX_VALUE);
				done();
			}
			else
			{
				// high priority because many things cannot continue without sorting results or must be recalculated when sorting finishes
				WeaveAPI.StageUtils.startTask(this, iterate, WeaveAPI.TASK_PRIORITY_HIGH, done);
			}
		}
		
		/**
		 * Aborts the current async sort operation.
		 */
		public function abort():void
		{
			compare = null;
			source = original = destination = null;
			length = subArraySize = iLeft = iRight = middle = end = elapsed = 0;
		}
		
		private function iterate(stopTime:int):Number
		{
			if (original is Array)
			{
				if (compare === ObjectUtil.numericCompare)
				{
					original.sort(Array.NUMERIC);
					return 1;
				}
				
				if (compare === compareCaseInsensitive)
				{
					original.sort(Array.CASEINSENSITIVE);
					return 1;
				}
				
				if (compare === null)
				{
					if (original[0] is Number || original[0] is Date)
						original.sort(Array.NUMERIC);
					else
						original.sort();
					return 1;
				}
			}
			<commit_msg>fixed another crash when sorting a vector.<commit_after>/*
    Weave (Web-based Analysis and Visualization Environment)
    Copyright (C) 2008-2011 University of Massachusetts Lowell

    This file is a part of Weave.

    Weave is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License, Version 3,
    as published by the Free Software Foundation.

    Weave is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with Weave.  If not, see <http://www.gnu.org/licenses/>.
*/

package weave.utils
{
	import flash.utils.getTimer;
	
	import mx.utils.ObjectUtil;
	
	import weave.api.core.ILinkableObject;
	import weave.api.getCallbackCollection;
	
	/**
	 * Asynchronous merge sort.
	 * 
	 * @author adufilie
	 */
	public class AsyncSort implements ILinkableObject
	{
		public static var debug:Boolean = false;
		
		private static var _immediateSorter:AsyncSort; // used by sortImmediately()
		
		/**
		 * This function will sort an Array (or Vector) immediately.
		 * @param array An Array (or Vector) to sort in place.
		 * @param compareFunction The function used to compare items in the array.
		 */
		public static function sortImmediately(array:*, compareFunction:Function = null):void
		{
			if (!_immediateSorter)
			{
				_immediateSorter = new AsyncSort();
				_immediateSorter._immediately = true;
			}
			
			// temporarily set _immediateSorter to null in case sortImmediately is called recursively.
			var sorter:AsyncSort = _immediateSorter;
			_immediateSorter = null;
			
			sorter.beginSort(array, compareFunction);
			
			_immediateSorter = sorter;
		}
		
		/**
		 * This function is a wrapper for ObjectUtil.stringCompare(a, b, true) (case-insensitive String compare).
		 */		
		public static function compareCaseInsensitive(a:String, b:String):int
		{
			return ObjectUtil.stringCompare(a, b, true);
		}
		
		/**
		 * Compares two primitive values.
		 * This function is faster than ObjectUtil.compare(), but does not do deep object compare.
		 */
		public static function primitiveCompare(a:*, b:*):int
		{
			if (a === b)
				return 0;
			if (a == null)
				return 1;
			if (b == null)
				return -1;
			var typeA:String = typeof(a);
			var typeB:String = typeof(b);
			if (typeA != typeB)
				return ObjectUtil.stringCompare(typeA, typeB);
			if (typeA == 'boolean')
				return ObjectUtil.numericCompare(Number(a), Number(b));
			if (typeA == 'number')
				return ObjectUtil.numericCompare(a as Number, b as Number);
			if (typeA == 'string')
				return ObjectUtil.stringCompare(a as String, b as String);
			if (a is Date && b is Date)
				return ObjectUtil.dateCompare(a as Date, b as Date);
			return 1; // not equal
		}
		
		public function AsyncSort():void
		{
		}
		
		/**
		 * This is the sorted Array (or Vector), or null if the sort operation has not completed yet.
		 */
		public function get result():*
		{
			return source ? null : original;
		}
		
		private var original:*; // original array
		private var source:*; // contains sub-arrays currently being merged
		private var destination:*; // buffer to store merged sub-arrays
		private var compare:Function; // compares two array items
		private var length:uint; // length of original array
		private var subArraySize:uint; // size of sub-array
		private var middle:uint; // end of left and start of right sub-array
		private var end:uint; // end of right sub-array
		private var iLeft:uint; // left sub-array source index
		private var iRight:uint; // right sub-array source index
		private var iMerged:uint; // merged destination index
		private var elapsed:int; // keeps track of elapsed time inside iterate()
		private var _immediately:Boolean = false; // set in sortImmediately(), checked in beginSort()
		
		/**
		 * This will begin an asynchronous sorting operation on the specified Array (or Vector).
		 * Only one sort operation can be carried out at a time.
		 * Callbacks will be triggered when the sorting operation completes.
		 * The given Array (or Vector) will be modified in-place.
		 * @param arrayToSort The Array (or Vector) to sort.
		 * @param compareFunction A function that compares two items and returns -1, 0, or 1.
		 * @see mx.utils.ObjectUtil#compare()
		 */
		public function beginSort(arrayToSort:*, compareFunction:Function = null):void
		{
			// initialize
			compare = compareFunction;
			original = arrayToSort || [];
			source = original;
			length = original.length;
			
			// make a buffer of the same type and length
			var Type:Class = (source as Object).constructor;
			destination = new Type();
			destination.length = length;
			
			subArraySize = 1;
			iLeft = 0;
			iRight = 0;
			middle = 0;
			end = 0;
			elapsed = 0;
			
			if (_immediately)
			{
				iterate(int.MAX_VALUE);
				done();
			}
			else
			{
				// high priority because many things cannot continue without sorting results or must be recalculated when sorting finishes
				WeaveAPI.StageUtils.startTask(this, iterate, WeaveAPI.TASK_PRIORITY_HIGH, done);
			}
		}
		
		/**
		 * Aborts the current async sort operation.
		 */
		public function abort():void
		{
			compare = null;
			source = original = destination = null;
			length = subArraySize = iLeft = iRight = middle = end = elapsed = 0;
		}
		
		private function iterate(stopTime:int):Number
		{
			if (original is Array)
			{
				if (compare === ObjectUtil.numericCompare)
				{
					original.sort(Array.NUMERIC);
					return 1;
				}
				
				if (compare === compareCaseInsensitive)
				{
					original.sort(Array.CASEINSENSITIVE);
					return 1;
				}
				
				if (compare === null)
				{
					if (original[0] is Number || original[0] is Date)
						original.sort(Array.NUMERIC);
					else
						original.sort();
					return 1;
				}
			}
			else if (compare === null)
			{
				compare = primitiveCompare;
			}
			
{'fraction_non_alphanumeric': 0.09268009616181713, 'fraction_numerical': 0.004642294619912128, 'mean_word_length': 3.0253586920253586, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '395365', 'n_tokens_mistral': 4221, 'n_tokens_neox': 3389, 'n_words': 1286}