diff --git a/math.scad b/math.scad index 86205af..784bb59 100644 --- a/math.scad +++ b/math.scad @@ -366,49 +366,49 @@ function determinant(M) = // Section: Comparisons and Logic +function _type_num(x) = + is_undef(x)? 0 : + is_bool(x)? 1 : + is_num(x)? 2 : + is_string(x)? 3 : + is_list(x)? 4 : 5; + + // Function: compare_vals() // Usage: // compare_vals(a, b); // Description: // Compares two values. Lists are compared recursively. -// Results are undefined if the two values are not of similar types. +// If types are not the same, then undef < bool < num < str < list < range. // Arguments: // a = First value to compare. // b = Second value to compare. function compare_vals(a, b) = (a==b)? 0 : - (a==undef)? -1 : - (b==undef)? 1 : - ((a==[] || a=="" || a[0]!=undef) && (b==[] || b=="" || b[0]!=undef))? ( - compare_lists(a, b) - ) : (ab)? 1 : 0; + let(t1=_type_num(a), t2=_type_num(b)) (t1!=t2)? (t1-t2) : + is_list(a)? compare_lists(a,b) : + (ab)? 1 : 0; // Function: compare_lists() // Usage: // compare_lists(a, b) // Description: -// Compare contents of two lists. +// Compare contents of two lists using `compare_vals()`. // Returns <0 if `a`<`b`. // Returns 0 if `a`==`b`. // Returns >0 if `a`>`b`. -// Results are undefined if elements are not of similar types. // Arguments: // a = First list to compare. // b = Second list to compare. -function compare_lists(a, b, n=0) = - let( - // This curious construction enables tail recursion optimization. - cmp = (a==b)? 0 : - (len(a)<=n)? -1 : - (len(b)<=n)? 1 : - (a==a[n] || b==b[n])? ( - ab? 1 : 0 - ) : compare_vals(a[n], b[n]) - ) - (cmp != 0 || a==b)? cmp : - compare_lists(a, b, n+1); +function compare_lists(a, b) = + a==b? 0 : let( + cmps = [ + for(i=[0:1:min(len(a),len(b))-1]) let( + cmp = compare_vals(a[i],b[i]) + ) if(cmp!=0) cmp + ] + ) cmps==[]? (len(a)-len(b)) : cmps[0]; // Function: any() diff --git a/tests/test_math.scad b/tests/test_math.scad index a3f897e..776d048 100644 --- a/tests/test_math.scad +++ b/tests/test_math.scad @@ -282,52 +282,101 @@ test_mean(); module test_compare_vals() { - assert(compare_vals(-10,0) == -1); - assert(compare_vals(10,0) == 1); + assert(compare_vals(-10,0) < 0); + assert(compare_vals(10,0) > 0); assert(compare_vals(10,10) == 0); - assert(compare_vals("abc","abcd") == -1); - assert(compare_vals("abcd","abc") == 1); + assert(compare_vals("abc","abcd") < 0); + assert(compare_vals("abcd","abc") > 0); assert(compare_vals("abcd","abcd") == 0); assert(compare_vals(false,false) == 0); - assert(compare_vals(true,false) == 1); - assert(compare_vals(false,true) == -1); + assert(compare_vals(true,false) > 0); + assert(compare_vals(false,true) < 0); assert(compare_vals(true,true) == 0); - assert(compare_vals([2,3,4], [2,3,4,5]) == -1); + assert(compare_vals([2,3,4], [2,3,4,5]) < 0); assert(compare_vals([2,3,4,5], [2,3,4,5]) == 0); - assert(compare_vals([2,3,4,5], [2,3,4]) == 1); - assert(compare_vals([2,3,4,5], [2,3,5,5]) == -1); - assert(compare_vals([[2,3,4,5]], [[2,3,5,5]]) == -1); + assert(compare_vals([2,3,4,5], [2,3,4]) > 0); + assert(compare_vals([2,3,4,5], [2,3,5,5]) < 0); + assert(compare_vals([[2,3,4,5]], [[2,3,5,5]]) < 0); assert(compare_vals([[2,3,4],[3,4,5]], [[2,3,4], [3,4,5]]) == 0); - assert(compare_vals([[2,3,4],[3,4,5]], [[2,3,4,5], [3,4,5]]) == -1); - assert(compare_vals([[2,3,4],[3,4,5]], [[2,3,4], [3,4,5,6]]) == -1); - assert(compare_vals([[2,3,4,5],[3,4,5]], [[2,3,4], [3,4,5]]) == 1); - assert(compare_vals([[2,3,4],[3,4,5,6]], [[2,3,4], [3,4,5]]) == 1); - assert(compare_vals([[2,3,4],[3,5,5]], [[2,3,4], [3,4,5]]) == 1); - assert(compare_vals([[2,3,4],[3,4,5]], [[2,3,4], [3,5,5]]) == -1); + assert(compare_vals([[2,3,4],[3,4,5]], [[2,3,4,5], [3,4,5]]) < 0); + assert(compare_vals([[2,3,4],[3,4,5]], [[2,3,4], [3,4,5,6]]) < 0); + assert(compare_vals([[2,3,4,5],[3,4,5]], [[2,3,4], [3,4,5]]) > 0); + assert(compare_vals([[2,3,4],[3,4,5,6]], [[2,3,4], [3,4,5]]) > 0); + assert(compare_vals([[2,3,4],[3,5,5]], [[2,3,4], [3,4,5]]) > 0); + assert(compare_vals([[2,3,4],[3,4,5]], [[2,3,4], [3,5,5]]) < 0); + + assert(compare_vals(undef, undef) == 0); + assert(compare_vals(undef, true) < 0); + assert(compare_vals(undef, 0) < 0); + assert(compare_vals(undef, "foo") < 0); + assert(compare_vals(undef, [2,3,4]) < 0); + assert(compare_vals(undef, [0:3]) < 0); + + assert(compare_vals(true, undef) > 0); + assert(compare_vals(true, true) == 0); + assert(compare_vals(true, 0) < 0); + assert(compare_vals(true, "foo") < 0); + assert(compare_vals(true, [2,3,4]) < 0); + assert(compare_vals(true, [0:3]) < 0); + + assert(compare_vals(0, undef) > 0); + assert(compare_vals(0, true) > 0); + assert(compare_vals(0, 0) == 0); + assert(compare_vals(0, "foo") < 0); + assert(compare_vals(0, [2,3,4]) < 0); + assert(compare_vals(0, [0:3]) < 0); + + assert(compare_vals(1, undef) > 0); + assert(compare_vals(1, true) > 0); + assert(compare_vals(1, 1) == 0); + assert(compare_vals(1, "foo") < 0); + assert(compare_vals(1, [2,3,4]) < 0); + assert(compare_vals(1, [0:3]) < 0); + + assert(compare_vals("foo", undef) > 0); + assert(compare_vals("foo", true) > 0); + assert(compare_vals("foo", 1) > 0); + assert(compare_vals("foo", "foo") == 0); + assert(compare_vals("foo", [2,3,4]) < 0); + assert(compare_vals("foo", [0:3]) < 0); + + assert(compare_vals([2,3,4], undef) > 0); + assert(compare_vals([2,3,4], true) > 0); + assert(compare_vals([2,3,4], 1) > 0); + assert(compare_vals([2,3,4], "foo") > 0); + assert(compare_vals([2,3,4], [2,3,4]) == 0); + assert(compare_vals([2,3,4], [0:3]) < 0); + + assert(compare_vals([0:3], undef) > 0); + assert(compare_vals([0:3], true) > 0); + assert(compare_vals([0:3], 1) > 0); + assert(compare_vals([0:3], "foo") > 0); + assert(compare_vals([0:3], [2,3,4]) > 0); + assert(compare_vals([0:3], [0:3]) == 0); } test_compare_vals(); module test_compare_lists() { - assert(compare_lists([2,3,4], [2,3,4,5]) == -1); + assert(compare_lists([2,3,4], [2,3,4,5]) < 0); assert(compare_lists([2,3,4,5], [2,3,4,5]) == 0); - assert(compare_lists([2,3,4,5], [2,3,4]) == 1); - assert(compare_lists([2,3,4,5], [2,3,5,5]) == -1); + assert(compare_lists([2,3,4,5], [2,3,4]) > 0); + assert(compare_lists([2,3,4,5], [2,3,5,5]) < 0); assert(compare_lists([[2,3,4],[3,4,5]], [[2,3,4], [3,4,5]]) == 0); - assert(compare_lists([[2,3,4],[3,4,5]], [[2,3,4,5], [3,4,5]]) == -1); - assert(compare_lists([[2,3,4],[3,4,5]], [[2,3,4], [3,4,5,6]]) == -1); - assert(compare_lists([[2,3,4,5],[3,4,5]], [[2,3,4], [3,4,5]]) == 1); - assert(compare_lists([[2,3,4],[3,4,5,6]], [[2,3,4], [3,4,5]]) == 1); - assert(compare_lists([[2,3,4],[3,5,5]], [[2,3,4], [3,4,5]]) == 1); - assert(compare_lists([[2,3,4],[3,4,5]], [[2,3,4], [3,5,5]]) == -1); + assert(compare_lists([[2,3,4],[3,4,5]], [[2,3,4,5], [3,4,5]]) < 0); + assert(compare_lists([[2,3,4],[3,4,5]], [[2,3,4], [3,4,5,6]]) < 0); + assert(compare_lists([[2,3,4,5],[3,4,5]], [[2,3,4], [3,4,5]]) > 0); + assert(compare_lists([[2,3,4],[3,4,5,6]], [[2,3,4], [3,4,5]]) > 0); + assert(compare_lists([[2,3,4],[3,5,5]], [[2,3,4], [3,4,5]]) > 0); + assert(compare_lists([[2,3,4],[3,4,5]], [[2,3,4], [3,5,5]]) < 0); - assert(compare_lists("cat", "bat") == 1); - assert(compare_lists(["cat"], ["bat"]) == 1); + assert(compare_lists("cat", "bat") > 0); + assert(compare_lists(["cat"], ["bat"]) > 0); } test_compare_lists();