Added all_nonzero(). Added is_vector(all_nonzero=).

This commit is contained in:
Garth Minette 2020-09-07 23:10:39 -07:00
parent a9b8f5618a
commit b2121fbfb3
5 changed files with 76 additions and 18 deletions

View file

@ -905,7 +905,7 @@ function norm_fro(A) =
// Usage: // Usage:
// all_zero(x); // all_zero(x);
// Description: // Description:
// Returns true if the number passed to it is approximately zero, to within `eps`. // Returns true if the finite number passed to it is approximately zero, to within `eps`.
// If passed a list, recursively checks if all items in the list are approximately zero. // If passed a list, recursively checks if all items in the list are approximately zero.
// Otherwise, returns false. // Otherwise, returns false.
// Arguments: // Arguments:
@ -917,8 +917,30 @@ function norm_fro(A) =
// all_zero([0,0,0]); // Returns: true. // all_zero([0,0,0]); // Returns: true.
// all_zero([0,0,1e-3]); // Returns: false. // all_zero([0,0,1e-3]); // Returns: false.
function all_zero(x, eps=EPSILON) = function all_zero(x, eps=EPSILON) =
is_finite(x)? approx(x,eps) :
is_list(x)? (x != [] && [for (xx=x) if(!all_zero(xx,eps=eps)) 1] == []) : is_list(x)? (x != [] && [for (xx=x) if(!all_zero(xx,eps=eps)) 1] == []) :
is_num(x)? approx(x,eps) : false;
// Function: all_nonzero()
// Usage:
// all_nonzero(x);
// Description:
// Returns true if the finite number passed to it is not almost zero, to within `eps`.
// If passed a list, recursively checks if all items in the list are not almost zero.
// Otherwise, returns false.
// Arguments:
// x = The value to check.
// eps = The maximum allowed variance. Default: `EPSILON` (1e-9)
// Example:
// all_nonzero(0); // Returns: false.
// all_nonzero(1e-3); // Returns: true.
// all_nonzero([0,0,0]); // Returns: false.
// all_nonzero([0,0,1e-3]); // Returns: false.
// all_nonzero([1e-3,1e-3,1e-3]); // Returns: true.
function all_nonzero(x, eps=EPSILON) =
is_finite(x)? !approx(x,eps) :
is_list(x)? (x != [] && [for (xx=x) if(!all_nonzero(xx,eps=eps)) 1] == []) :
false; false;
@ -926,7 +948,7 @@ function all_zero(x, eps=EPSILON) =
// Usage: // Usage:
// all_positive(x); // all_positive(x);
// Description: // Description:
// Returns true if the number passed to it is greater than zero. // Returns true if the finite number passed to it is greater than zero.
// If passed a list, recursively checks if all items in the list are positive. // If passed a list, recursively checks if all items in the list are positive.
// Otherwise, returns false. // Otherwise, returns false.
// Arguments: // Arguments:
@ -940,8 +962,8 @@ function all_zero(x, eps=EPSILON) =
// all_positive([3,1,2]); // Returns: true. // all_positive([3,1,2]); // Returns: true.
// all_positive([3,-1,2]); // Returns: false. // all_positive([3,-1,2]); // Returns: false.
function all_positive(x) = function all_positive(x) =
is_list(x)? (x != [] && [for (xx=x) if(!all_positive(xx)) 1] == []) :
is_num(x)? x>0 : is_num(x)? x>0 :
is_list(x)? (x != [] && [for (xx=x) if(!all_positive(xx)) 1] == []) :
false; false;
@ -949,7 +971,7 @@ function all_positive(x) =
// Usage: // Usage:
// all_negative(x); // all_negative(x);
// Description: // Description:
// Returns true if the number passed to it is less than zero. // Returns true if the finite number passed to it is less than zero.
// If passed a list, recursively checks if all items in the list are negative. // If passed a list, recursively checks if all items in the list are negative.
// Otherwise, returns false. // Otherwise, returns false.
// Arguments: // Arguments:
@ -964,8 +986,8 @@ function all_positive(x) =
// all_negative([3,-1,2]); // Returns: false. // all_negative([3,-1,2]); // Returns: false.
// all_negative([-3,-1,-2]); // Returns: true. // all_negative([-3,-1,-2]); // Returns: true.
function all_negative(x) = function all_negative(x) =
is_list(x)? (x != [] && [for (xx=x) if(!all_negative(xx)) 1] == []) :
is_num(x)? x<0 : is_num(x)? x<0 :
is_list(x)? (x != [] && [for (xx=x) if(!all_negative(xx)) 1] == []) :
false; false;
@ -973,7 +995,7 @@ function all_negative(x) =
// Usage: // Usage:
// all_nonpositive(x); // all_nonpositive(x);
// Description: // Description:
// Returns true if the number passed to it is less than or equal to zero. // Returns true if the finite number passed to it is less than or equal to zero.
// If passed a list, recursively checks if all items in the list are nonpositive. // If passed a list, recursively checks if all items in the list are nonpositive.
// Otherwise, returns false. // Otherwise, returns false.
// Arguments: // Arguments:
@ -988,8 +1010,8 @@ function all_negative(x) =
// all_nonpositive([3,-1,2]); // Returns: false. // all_nonpositive([3,-1,2]); // Returns: false.
// all_nonpositive([-3,-1,-2]); // Returns: true. // all_nonpositive([-3,-1,-2]); // Returns: true.
function all_nonpositive(x) = function all_nonpositive(x) =
is_list(x)? (x != [] && [for (xx=x) if(!all_nonpositive(xx)) 1] == []) :
is_num(x)? x<=0 : is_num(x)? x<=0 :
is_list(x)? (x != [] && [for (xx=x) if(!all_nonpositive(xx)) 1] == []) :
false; false;
@ -997,7 +1019,7 @@ function all_nonpositive(x) =
// Usage: // Usage:
// all_nonnegative(x); // all_nonnegative(x);
// Description: // Description:
// Returns true if the number passed to it is greater than or equal to zero. // Returns true if the finite number passed to it is greater than or equal to zero.
// If passed a list, recursively checks if all items in the list are nonnegative. // If passed a list, recursively checks if all items in the list are nonnegative.
// Otherwise, returns false. // Otherwise, returns false.
// Arguments: // Arguments:
@ -1013,8 +1035,8 @@ function all_nonpositive(x) =
// all_nonnegative([3,-1,2]); // Returns: false. // all_nonnegative([3,-1,2]); // Returns: false.
// all_nonnegative([-3,-1,-2]); // Returns: false. // all_nonnegative([-3,-1,-2]); // Returns: false.
function all_nonnegative(x) = function all_nonnegative(x) =
is_list(x)? (x != [] && [for (xx=x) if(!all_nonnegative(xx)) 1] == []) :
is_num(x)? x>=0 : is_num(x)? x>=0 :
is_list(x)? (x != [] && [for (xx=x) if(!all_nonnegative(xx)) 1] == []) :
false; false;

View file

@ -122,6 +122,30 @@ module test_all_zero() {
test_all_zero(); test_all_zero();
module test_all_nonzero() {
assert(!all_nonzero(0));
assert(!all_nonzero([0,0,0]));
assert(!all_nonzero([[0,0,0],[0,0]]));
assert(!all_nonzero([EPSILON/2,EPSILON/2,EPSILON/2]));
assert(all_nonzero(1e-3));
assert(!all_nonzero([0,0,1e-3]));
assert(!all_nonzero([EPSILON*10,0,0]));
assert(!all_nonzero([0,EPSILON*10,0]));
assert(!all_nonzero([0,0,EPSILON*10]));
assert(all_nonzero([1e-3,1e-3,1e-3]));
assert(all_nonzero([EPSILON*10,EPSILON*10,EPSILON*10]));
assert(!all_nonzero(true));
assert(!all_nonzero(false));
assert(!all_nonzero(INF));
assert(!all_nonzero(-INF));
assert(!all_nonzero(NAN));
assert(!all_nonzero("foo"));
assert(!all_nonzero([]));
assert(!all_nonzero([0:1:2]));
}
test_all_nonzero();
module test_all_positive() { module test_all_positive() {
assert(!all_positive(-2)); assert(!all_positive(-2));
assert(!all_positive(0)); assert(!all_positive(0));

View file

@ -14,6 +14,14 @@ module test_is_vector() {
assert(is_vector([0,0,0],zero=false) == false); assert(is_vector([0,0,0],zero=false) == false);
assert(is_vector([0,1,0],zero=true) == false); assert(is_vector([0,1,0],zero=true) == false);
assert(is_vector([0,0,1],zero=false) == true); assert(is_vector([0,0,1],zero=false) == true);
assert(is_vector([1,1,1],zero=false) == true);
assert(is_vector([0,0,0],all_nonzero=true) == false);
assert(is_vector([0,1,0],all_nonzero=true) == false);
assert(is_vector([0,0,1],all_nonzero=true) == false);
assert(is_vector([1,1,1],all_nonzero=true) == true);
assert(is_vector([-1,1,1],all_nonzero=true) == true);
assert(is_vector([-1,-1,-1],all_nonzero=true) == true);
} }
test_is_vector(); test_is_vector();

View file

@ -19,7 +19,8 @@
// Arguments: // Arguments:
// v = The value to test to see if it is a vector. // v = The value to test to see if it is a vector.
// length = If given, make sure the vector is `length` items long. // length = If given, make sure the vector is `length` items long.
// zero = If false, require that the length of the vector is not approximately zero. If true, require the length of the vector to be approximately zero-length. Default: `undef` (don't check vector length.) // zero = If false, require that the length/`norm()` of the vector is not approximately zero. If true, require the length/`norm()` of the vector to be approximately zero-length. Default: `undef` (don't check vector length/`norm()`.)
// all_nonzero = If true, requires all elements of the vector to be more than `eps` different from zero. Default: `false`
// eps = The minimum vector length that is considered non-zero. Default: `EPSILON` (`1e-9`) // eps = The minimum vector length that is considered non-zero. Default: `EPSILON` (`1e-9`)
// Example: // Example:
// is_vector(4); // Returns false // is_vector(4); // Returns false
@ -30,14 +31,17 @@
// is_vector([3,4,5],3); // Returns true // is_vector([3,4,5],3); // Returns true
// is_vector([3,4,5],4); // Returns true // is_vector([3,4,5],4); // Returns true
// is_vector([]); // Returns false // is_vector([]); // Returns false
// is_vector([0,4,0],3,zero=false); // Returns true // is_vector([0,4,0],3,zero=false); // Returns true
// is_vector([0,0,0],zero=false); // Returns false // is_vector([0,0,0],zero=false); // Returns false
// is_vector([0,0,1e-12],zero=false); // Returns false // is_vector([0,0,1e-12],zero=false); // Returns false
// is_vector([],zero=false); // Returns false // is_vector([0,1,0],all_nonzero=false); // Returns false
function is_vector(v,length,zero,eps=EPSILON) = // is_vector([1,1,1],all_nonzero=false); // Returns true
// is_vector([],zero=false); // Returns false
function is_vector(v, length, zero, all_nonzero=false, eps=EPSILON) =
is_list(v) && is_num(0*(v*v)) is_list(v) && is_num(0*(v*v))
&& (is_undef(length) || len(v)==length) && (is_undef(length) || len(v)==length)
&& (is_undef(zero) || ((norm(v) >= eps) == !zero)); && (is_undef(zero) || ((norm(v) >= eps) == !zero))
&& (!all_nonzero || all_nonzero(v)) ;
// Function: vang() // Function: vang()

View file

@ -8,7 +8,7 @@
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
BOSL_VERSION = [2,0,420]; BOSL_VERSION = [2,0,421];
// Section: BOSL Library Version Functions // Section: BOSL Library Version Functions