mirror of
				https://github.com/flynx/ImageGrid.git
				synced 2025-10-31 03:10:07 +00:00 
			
		
		
		
	rewritten binSearch(...) impementation, still needs testing...
Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
		
							parent
							
								
									e7196b76e9
								
							
						
					
					
						commit
						46c3164271
					
				
							
								
								
									
										118
									
								
								ui/data.js
									
									
									
									
									
								
							
							
						
						
									
										118
									
								
								ui/data.js
									
									
									
									
									
								
							| @ -86,8 +86,8 @@ function imageNameCmp(a, b, data){ | ||||
| //
 | ||||
| // This will return:
 | ||||
| // 	- 0 if a is equal to position i
 | ||||
| // 	- -1 if a is less position i
 | ||||
| // 	- +1 if a is greater position i
 | ||||
| // 	- -1 if a is less than position i
 | ||||
| // 	- +1 if a is greater than position i
 | ||||
| //
 | ||||
| // NOTE: the signature is different from the traditional cmp(a, b) so as 
 | ||||
| // 		to enable more complex comparisons involving adjacent elements
 | ||||
| @ -113,9 +113,15 @@ function cmp(a, i, lst){ | ||||
| //
 | ||||
| // NOTE: this is here mostly to make debuging easy...
 | ||||
| function isBetween(a, i, lst){ | ||||
| 	//console.log('>>>', a, i, lst)
 | ||||
| 	var b = lst[i] | ||||
| 
 | ||||
| 	// special case: tail...
 | ||||
| 	if(i == lst.length-1 && a >= b){ | ||||
| 		return 0 | ||||
| 	} | ||||
| 
 | ||||
| 	var c = lst[i+1] | ||||
| 	 | ||||
| 	// hit...
 | ||||
| 	if(a == b || (a > b && a < c)){ | ||||
| 		return 0 | ||||
| @ -130,18 +136,8 @@ function isBetween(a, i, lst){ | ||||
| 
 | ||||
| 
 | ||||
| // Basic liner search...
 | ||||
| function linSearch(target, lst, check, return_position, disable_direct_indexing){ | ||||
| 	// XXX is this the correct default?
 | ||||
| 	check = check == null ? isBetween : check | ||||
| 	// special case: target in the list directly...
 | ||||
| 	if(disable_direct_indexing  | ||||
| 			&& check(target, lst.indexOf(target), lst) == 0){ | ||||
| 		return target | ||||
| 	} | ||||
| 	// special case: tail...
 | ||||
| 	if(check(target, lst.length-1, lst) >= 0){ | ||||
| 		return lst[lst.length-1] | ||||
| 	} | ||||
| function linSearch(target, lst, check, return_position){ | ||||
| 	check = check == null ? cmp : check | ||||
| 
 | ||||
| 	for(var i=0; i < lst.length; i++){ | ||||
| 		if(check(target, i, lst) == 0){ | ||||
| @ -152,78 +148,88 @@ function linSearch(target, lst, check, return_position, disable_direct_indexing) | ||||
| 	// no hit...
 | ||||
| 	return return_position ? -1 : null | ||||
| } | ||||
| Array.prototype.linSearch = function(target, cmp){ | ||||
| 	return linSearch(target, this, cmp, true) | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| // Basic binary search implementation...
 | ||||
| //
 | ||||
| // NOTE: this will return the object by default, to return position set
 | ||||
| // 		return_position to true.
 | ||||
| // NOTE: by default this will use isBetween as a predicate.
 | ||||
| // NOTE: this still depends on .indexOf(...), to disable set
 | ||||
| // 		disable_direct_indexing to true
 | ||||
| // XXX BUGGY
 | ||||
| // XXX this is a mess, needs revision...
 | ||||
| function binSearch(target, lst, check, return_position, disable_direct_indexing){ | ||||
| 	// XXX is this the correct default?
 | ||||
| 	check = check == null ? isBetween : check | ||||
| 	// special case: target in the list directly...
 | ||||
| 	if(disable_direct_indexing  | ||||
| 			&& check(target, lst.indexOf(target), lst) == 0){ | ||||
| 		return target | ||||
| 	} | ||||
| 	// special case: tail...
 | ||||
| 	if(check(target, lst.length-1, lst) >= 0){ | ||||
| 		return lst[lst.length-1] | ||||
| 	} | ||||
| 	// special case: head...
 | ||||
| 	var res = check(target, 0, lst) | ||||
| 	if(res == 0){ | ||||
| 		return lst[0] | ||||
| 	} else if(res < 0){ | ||||
| 		// no hit...
 | ||||
| 		return return_position ? -1 : null | ||||
| 	} | ||||
| // NOTE: by default this will use cmp as a predicate.
 | ||||
| function binSearch(target, lst, check, return_position){ | ||||
| 	check = check == null ? cmp : check | ||||
| 	var h = 0 | ||||
| 	var t = lst.length - 1 | ||||
| 	var m, res | ||||
| 
 | ||||
| 	var l = Math.ceil(lst.length/2) | ||||
| 	var i = l | ||||
| 	while(h <= t){ | ||||
| 		m = Math.floor((h + t)/2) | ||||
| 		res = check(target, m, lst) | ||||
| 		 | ||||
| 	while(l > 0){ | ||||
| 		// XXX this is a hack -- should we reach 0 using floor(..) instead?
 | ||||
| 		l = l <= 1 ? 0 : Math.ceil(l/2) | ||||
| 		res = check(target, i, lst) | ||||
| 		// right branch...
 | ||||
| 		if(res > 0){ | ||||
| 			i += l | ||||
| 		// left branch...
 | ||||
| 		// match...
 | ||||
| 		if(res == 0){ | ||||
| 			return return_position ? m : lst[m] | ||||
| 
 | ||||
| 		// below...
 | ||||
| 		} else if(res < 0){ | ||||
| 			i -= l | ||||
| 		// hit...
 | ||||
| 			t = m - 1 | ||||
| 
 | ||||
| 		// above...
 | ||||
| 		} else { | ||||
| 			return return_position ? i : lst[i] | ||||
| 			h = m + 1 | ||||
| 		} | ||||
| 	} | ||||
| 	// no hit...
 | ||||
| 
 | ||||
| 	// no result...
 | ||||
| 	return return_position ? -1 : null | ||||
| } | ||||
| Array.prototype.binSearch = function(target, cmp){ | ||||
| 	return binSearch(target, this, cmp, true) | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| function match(f0, f1){ | ||||
| 	return function(){ | ||||
| 		var a = f0.apply(f0, arguments) | ||||
| 		var b = f1.apply(f1, arguments) | ||||
| 		if(a != b){ | ||||
| 			console.warn('Result mismatch: f0:'+a+' f1:'+b) | ||||
| 		} | ||||
| 		return a | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // Same as getImageBefore, but uses gids and searches in DATA...
 | ||||
| //
 | ||||
| // NOTE: this uses it's own predicate...
 | ||||
| function getGIDBefore(gid, ribbon, search){ | ||||
| 	search = search == null ? linSearch : search | ||||
| 	search = search == null ? binSearch : search | ||||
| 	//search = search == null ? match(linSearch, binSearch) : search
 | ||||
| 	ribbon = DATA.ribbons[ribbon] | ||||
| 	var order = DATA.order | ||||
| 
 | ||||
| 	var target = order.indexOf(gid) | ||||
| 
 | ||||
| 	return search(target, ribbon, function (a, i, lst){ | ||||
| 	return search(target, ribbon, function(a, i, lst){ | ||||
| 		var b = order.indexOf(lst[i]) | ||||
| 
 | ||||
| 		// special case: tail...
 | ||||
| 		if(i == lst.length-1 && a >= b){ | ||||
| 			return 0 | ||||
| 		} | ||||
| 
 | ||||
| 		var c = order.indexOf(lst[i+1]) | ||||
| 	 | ||||
| 		// hit...
 | ||||
| 		if(a == b || (a > b && a < c)){ | ||||
| 			return 0 | ||||
| 
 | ||||
| 		// before...
 | ||||
| 		} else if(a < b){ | ||||
| 			return -1 | ||||
| 
 | ||||
| 		// later...
 | ||||
| 		} else { | ||||
| 			return 1 | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user