diff --git a/docs/lib2x-bsearch.md b/docs/lib2x-bsearch.md deleted file mode 100644 index b39c37e4..00000000 --- a/docs/lib2x-bsearch.md +++ /dev/null @@ -1,26 +0,0 @@ -# bsearch - -The `bsearch` function is a general-purpose function to find a value or a list of values in a vector. The vector must be sorted by zyx (from the last index to the first one). - -**Since:** 2.3 - -## Parameters - -- `sorted` : The sorted vector. -- `elem` : a list of values. -- `by` : Can be `"x"`、`"y"`、`"z"`, `"idx"` (Default) or `"vt"`. -- `idx` : When `by` is `"idx"`, the value of `idx` is used. The Default value is 0. - -## Examples - - use ; - use ; - use ; - - points = [[1, 1], [3, 4], [7, 2], [5, 2]]; - sorted = sort(points, by = "vt"); - - echo(sorted); // [[1, 1], [5, 2], [7, 2], [3, 4]] - assert(bsearch(sorted, [5, 4], by = "x") == 1); - assert(bsearch(sorted, [5, 4], by = "y") == 3); - assert(bsearch(sorted, [7, 2], by = "vt") == 2); \ No newline at end of file diff --git a/docs/lib3x-bsearch.md b/docs/lib3x-bsearch.md new file mode 100644 index 00000000..c85fd7c1 --- /dev/null +++ b/docs/lib3x-bsearch.md @@ -0,0 +1,26 @@ +# bsearch + +The `bsearch` function is a general-purpose function to search a value in a list whose elements must be sorted by zyx (from the last index to the first one). + +**Since:** 3.0 + +## Parameters + +- `sorted` : The sorted list. +- `target` : The target vector or a function literal. + +## Examples + + use ; + use ; + + points = [[1, 1], [3, 4], [7, 2], [5, 2]]; + sorted = sort(points, by = "vt"); // [[1, 1], [5, 2], [7, 2], [3, 4]] + + assert(bsearch(sorted, [7, 2]) == 2); + + xIs5 = function(elem) elem[0] - 5; + assert(bsearch(sorted, xIs5) == 1); + + yIs4 = function(elem) elem[1] - 4; + assert(bsearch(sorted, yIs4) == 3); \ No newline at end of file diff --git a/src/util/_impl/_bsearch_impl.scad b/src/util/_impl/_bsearch_impl.scad index bac7d859..2acf475f 100644 --- a/src/util/_impl/_bsearch_impl.scad +++ b/src/util/_impl/_bsearch_impl.scad @@ -1,20 +1,13 @@ use <_vt_default_comparator.scad>; -function _binary_search_by(sorted, elem, low, upper, i) = - low > upper ? -1 : - let(mid = floor((low + upper) / 2)) - sorted[mid][i] < elem[i] ? _binary_search_by(sorted, elem, mid + 1, upper, i) : - sorted[mid][i] > elem[i] ? _binary_search_by(sorted, elem, low, mid - 1, i) : mid; - function _bsearch_vt(sorted, elem, low, upper) = low > upper ? -1 : let(mid = floor((low + upper) / 2)) lessThan(sorted[mid], elem) ? _bsearch_vt(sorted, elem, mid + 1, upper) : greaterThan(sorted[mid], elem) ? _bsearch_vt(sorted, elem, low, mid - 1) : mid; -function _bsearch_by(sorted, elem, by, idx) = - let( - dict = [["x", 0], ["y", 1], ["z", 2], ["i", idx]], - i = dict[search(by == "idx" ? "i" : by, dict)[0]][1] - ) - _binary_search_by(sorted, elem, 0, len(sorted) - 1, i); \ No newline at end of file +function _bsearch_cmp(sorted, cmp, low, upper) = + low > upper ? -1 : + let(mid = floor((low + upper) / 2)) + cmp(sorted[mid]) < 0 ? _bsearch_cmp(sorted, cmp, mid + 1, upper) : + cmp(sorted[mid]) > 0 ? _bsearch_cmp(sorted, cmp, low, mid - 1) : mid; \ No newline at end of file diff --git a/src/util/bsearch.scad b/src/util/bsearch.scad index a8a514db..0bba8f16 100644 --- a/src/util/bsearch.scad +++ b/src/util/bsearch.scad @@ -4,12 +4,12 @@ * @copyright Justin Lin, 2020 * @license https://opensource.org/licenses/lgpl-3.0.html * -* @see https://openhome.cc/eGossip/OpenSCAD/lib2x-bsearch.html +* @see https://openhome.cc/eGossip/OpenSCAD/lib3x-bsearch.html * **/ use <_impl/_bsearch_impl.scad>; -function bsearch(sorted, elem, by = "idx", idx = 0) = - by == "vt" ? _bsearch_vt(sorted, elem, 0, len(sorted) - 1) : // for example, `sorted` is by zyx - _bsearch_by(sorted, elem, by, idx); \ No newline at end of file +function bsearch(sorted, target) = + is_function(target) ? _bsearch_cmp(sorted, target, 0, len(sorted) - 1) : + _bsearch_vt(sorted, target, 0, len(sorted) - 1); // `sorted` is by zyx \ No newline at end of file diff --git a/test/util/test_bsearch.scad b/test/util/test_bsearch.scad new file mode 100644 index 00000000..5cb7cd67 --- /dev/null +++ b/test/util/test_bsearch.scad @@ -0,0 +1,19 @@ +use ; +use ; + +module test_bsearch() { + echo("==== test_bsearch ===="); + + points = [[1, 1], [3, 4], [7, 2], [5, 2]]; + sorted = sort(points, by = "vt"); // [[1, 1], [5, 2], [7, 2], [3, 4]] + + assert(bsearch(sorted, [7, 2]) == 2); + + xIs5 = function(elem) elem[0] - 5; + assert(bsearch(sorted, xIs5) == 1); + + yIs4 = function(elem) elem[1] - 4; + assert(bsearch(sorted, yIs4) == 3); +} + +test_bsearch(); \ No newline at end of file