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:
 | // This will return:
 | ||||||
| // 	- 0 if a is equal to position i
 | // 	- 0 if a is equal to position i
 | ||||||
| // 	- -1 if a is less position i
 | // 	- -1 if a is less than position i
 | ||||||
| // 	- +1 if a is greater position i
 | // 	- +1 if a is greater than position i
 | ||||||
| //
 | //
 | ||||||
| // NOTE: the signature is different from the traditional cmp(a, b) so as 
 | // NOTE: the signature is different from the traditional cmp(a, b) so as 
 | ||||||
| // 		to enable more complex comparisons involving adjacent elements
 | // 		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...
 | // NOTE: this is here mostly to make debuging easy...
 | ||||||
| function isBetween(a, i, lst){ | function isBetween(a, i, lst){ | ||||||
| 	//console.log('>>>', a, i, lst)
 |  | ||||||
| 	var b = lst[i] | 	var b = lst[i] | ||||||
|  | 
 | ||||||
|  | 	// special case: tail...
 | ||||||
|  | 	if(i == lst.length-1 && a >= b){ | ||||||
|  | 		return 0 | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	var c = lst[i+1] | 	var c = lst[i+1] | ||||||
|  | 	 | ||||||
| 	// hit...
 | 	// hit...
 | ||||||
| 	if(a == b || (a > b && a < c)){ | 	if(a == b || (a > b && a < c)){ | ||||||
| 		return 0 | 		return 0 | ||||||
| @ -130,18 +136,8 @@ function isBetween(a, i, lst){ | |||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| // Basic liner search...
 | // Basic liner search...
 | ||||||
| function linSearch(target, lst, check, return_position, disable_direct_indexing){ | function linSearch(target, lst, check, return_position){ | ||||||
| 	// XXX is this the correct default?
 | 	check = check == null ? cmp : check | ||||||
| 	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] |  | ||||||
| 	} |  | ||||||
| 
 | 
 | ||||||
| 	for(var i=0; i < lst.length; i++){ | 	for(var i=0; i < lst.length; i++){ | ||||||
| 		if(check(target, i, lst) == 0){ | 		if(check(target, i, lst) == 0){ | ||||||
| @ -152,78 +148,88 @@ function linSearch(target, lst, check, return_position, disable_direct_indexing) | |||||||
| 	// no hit...
 | 	// no hit...
 | ||||||
| 	return return_position ? -1 : null | 	return return_position ? -1 : null | ||||||
| } | } | ||||||
|  | Array.prototype.linSearch = function(target, cmp){ | ||||||
|  | 	return linSearch(target, this, cmp, true) | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| // Basic binary search implementation...
 | // Basic binary search implementation...
 | ||||||
| //
 | //
 | ||||||
| // NOTE: this will return the object by default, to return position set
 | // NOTE: this will return the object by default, to return position set
 | ||||||
| // 		return_position to true.
 | // 		return_position to true.
 | ||||||
| // NOTE: by default this will use isBetween as a predicate.
 | // NOTE: by default this will use cmp as a predicate.
 | ||||||
| // NOTE: this still depends on .indexOf(...), to disable set
 | function binSearch(target, lst, check, return_position){ | ||||||
| // 		disable_direct_indexing to true
 | 	check = check == null ? cmp : check | ||||||
| // XXX BUGGY
 | 	var h = 0 | ||||||
| // XXX this is a mess, needs revision...
 | 	var t = lst.length - 1 | ||||||
| function binSearch(target, lst, check, return_position, disable_direct_indexing){ | 	var m, res | ||||||
| 	// 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 |  | ||||||
| 	} |  | ||||||
| 
 | 
 | ||||||
| 	var l = Math.ceil(lst.length/2) | 	while(h <= t){ | ||||||
| 	var i = l | 		m = Math.floor((h + t)/2) | ||||||
|  | 		res = check(target, m, lst) | ||||||
| 		 | 		 | ||||||
| 	while(l > 0){ | 		// match...
 | ||||||
| 		// XXX this is a hack -- should we reach 0 using floor(..) instead?
 | 		if(res == 0){ | ||||||
| 		l = l <= 1 ? 0 : Math.ceil(l/2) | 			return return_position ? m : lst[m] | ||||||
| 		res = check(target, i, lst) | 
 | ||||||
| 		// right branch...
 | 		// below...
 | ||||||
| 		if(res > 0){ |  | ||||||
| 			i += l |  | ||||||
| 		// left branch...
 |  | ||||||
| 		} else if(res < 0){ | 		} else if(res < 0){ | ||||||
| 			i -= l | 			t = m - 1 | ||||||
| 		// hit...
 | 
 | ||||||
|  | 		// above...
 | ||||||
| 		} else { | 		} else { | ||||||
| 			return return_position ? i : lst[i] | 			h = m + 1 | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	// no hit...
 | 
 | ||||||
|  | 	// no result...
 | ||||||
| 	return return_position ? -1 : null | 	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...
 | // Same as getImageBefore, but uses gids and searches in DATA...
 | ||||||
|  | //
 | ||||||
|  | // NOTE: this uses it's own predicate...
 | ||||||
| function getGIDBefore(gid, ribbon, search){ | 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] | 	ribbon = DATA.ribbons[ribbon] | ||||||
| 	var order = DATA.order | 	var order = DATA.order | ||||||
| 
 | 
 | ||||||
| 	var target = order.indexOf(gid) | 	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]) | 		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]) | 		var c = order.indexOf(lst[i+1]) | ||||||
|  | 	 | ||||||
| 		// hit...
 | 		// hit...
 | ||||||
| 		if(a == b || (a > b && a < c)){ | 		if(a == b || (a > b && a < c)){ | ||||||
| 			return 0 | 			return 0 | ||||||
|  | 
 | ||||||
| 		// before...
 | 		// before...
 | ||||||
| 		} else if(a < b){ | 		} else if(a < b){ | ||||||
| 			return -1 | 			return -1 | ||||||
|  | 
 | ||||||
| 		// later...
 | 		// later...
 | ||||||
| 		} else { | 		} else { | ||||||
| 			return 1 | 			return 1 | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user