diff --git a/math.scad b/math.scad index f112c19..7e16bbe 100644 --- a/math.scad +++ b/math.scad @@ -84,7 +84,7 @@ function hypot(x,y,z=0) = // y = factorial(6); // Returns: 720 // z = factorial(9); // Returns: 362880 function factorial(n,d=0) = - assert(is_int(n) && is_int(d) && n>=0 && d>=0, "Factorial is not defined for negative numbers") + assert(is_int(n) && is_int(d) && n>=0 && d>=0, "Factorial is defined only for non negative integers") assert(d<=n, "d cannot be larger than n") product([1,for (i=[n:-1:d+1]) i]); @@ -164,7 +164,7 @@ function binomial_coefficient(n,k) = function lerp(a,b,u) = assert(same_shape(a,b), "Bad or inconsistent inputs to lerp") is_finite(u)? (1-u)*a + u*b : - assert(is_finite(u) || is_vector(u) || valid_range(u), "Input u to lerp must be a number, vector, or range.") + assert(is_finite(u) || is_vector(u) || valid_range(u), "Input u to lerp must be a number, vector, or valid range.") [for (v = u) (1-v)*a + v*b ]; @@ -387,12 +387,13 @@ function modang(x) = // modrange(90,270,360, step=-45); // Returns: [90,45,0,315,270] // modrange(270,90,360, step=-45); // Returns: [270,225,180,135,90] function modrange(x, y, m, step=1) = - assert( is_finite(x+y+step+m) && !approx(m,0), "Input must be finite numbers. The module value cannot be zero.") + assert( is_finite(x+y+step+m) && !approx(m,0), "Input must be finite numbers and the module value cannot be zero." ) let( a = posmod(x, m), b = posmod(y, m), - c = step>0? (a>b? b+m : b) : (a0? (a>b? b+m : b) + : (a=len(v) ? _total : _sum(v,_total+v[_i], _i+1); // cumsum([2,2,2]); // returns [2,4,6] // cumsum([1,2,3]); // returns [1,3,6] // cumsum([[1,2,3], [3,4,5], [5,6,7]]); // returns [[1,2,3], [4,6,8], [9,12,15]] -function cumsum(v,_i=0,_acc=[]) = +function cumsum(v) = + assert(is_consistent(v), "The input is not consistent." ) + _cumsum(v,_i=0,_acc=[]); + +function _cumsum(v,_i=0,_acc=[]) = _i==len(v) ? _acc : - cumsum( + _cumsum( v, _i+1, concat( _acc, @@ -598,7 +603,7 @@ function deltas(v) = // Description: // Returns the product of all entries in the given list. // If passed a list of vectors of same dimension, returns a vector of products of each part. -// If passed a list of square matrices, returns a the resulting product matrix. +// If passed a list of square matrices, returns the resulting product matrix. // Arguments: // v = The list to get the product of. // Example: @@ -606,7 +611,7 @@ function deltas(v) = // product([[1,2,3], [3,4,5], [5,6,7]]); // returns [15, 48, 105] function product(v) = assert( is_vector(v) || is_matrix(v) || ( is_matrix(v[0],square=true) && is_consistent(v)), - "Invalid input.") + "Invalid input.") _product(v, 1, v[0]); function _product(v, i=0, _tot) = @@ -691,9 +696,12 @@ function linear_solve(A,b) = zeros = [for(i=[0:mindim-1]) if (approx(R[i][i],0)) i] ) zeros != [] ? [] : - m=len(l) || succ)? succ : - any( l, - i+1, - succ = is_list(l[i]) ? any(l[i]) : !(!l[i]) - ); +function any(l) = + assert(is_list(l), "The input is not a list." ) + _any(l, i=0, succ=false); +function _any(l, i=0, succ=false) = + (i>=len(l) || succ)? succ : + _any( l, + i+1, + succ = is_list(l[i]) ? _any(l[i]) : !(!l[i]) + ); // Function: all() @@ -972,12 +982,15 @@ function any(l, i=0, succ=false) = // all([[0,0], [1,0]]); // Returns false. // all([[1,1], [1,1]]); // Returns true. function all(l, i=0, fail=false) = - (i>=len(l) || fail)? !fail : - all( l, - i+1, - fail = is_list(l[i]) ? !all(l[i]) : !l[i] - ) ; + assert( is_list(l), "The input is not a list." ) + _all(l, i=0, fail=false); +function _all(l, i=0, fail=false) = + (i>=len(l) || fail)? !fail : + _all( l, + i+1, + fail = is_list(l[i]) ? !_all(l[i]) : !l[i] + ) ; // Function: count_true() @@ -1195,12 +1208,12 @@ function C_div(z1,z2) = // where a_n is the z^n coefficient. Polynomial coefficients are real. // The result is a number if `z` is a number and a complex number otherwise. function polynomial(p,z,k,total) = - is_undef(k) - ? assert( is_vector(p) , "Input polynomial coefficients must be a vector." ) - assert( is_finite(z) || is_vector(z,2), "The value of `z` must be a real or a complex number." ) - polynomial( _poly_trim(p), z, 0, is_num(z) ? 0 : [0,0]) - : k==len(p) ? total - : polynomial(p,z,k+1, is_num(z) ? total*z+p[k] : C_times(total,z)+[p[k],0]); +    is_undef(k) +    ?   assert( is_vector(p) , "Input polynomial coefficients must be a vector." ) +        assert( is_finite(z) || is_vector(z,2), "The value of `z` must be a real or a complex number." ) +        polynomial( _poly_trim(p), z, 0, is_num(z) ? 0 : [0,0]) +    : k==len(p) ? total +    : polynomial(p,z,k+1, is_num(z) ? total*z+p[k] : C_times(total,z)+[p[k],0]); // Function: poly_mult() // Usage: @@ -1210,22 +1223,16 @@ function polynomial(p,z,k,total) = // Given a list of polynomials represented as real coefficient lists, with the highest degree coefficient first, // computes the coefficient list of the product polynomial. function poly_mult(p,q) = - is_undef(q) ? - assert( is_list(p) - && []==[for(pi=p) if( !is_vector(pi) && pi!=[]) 0], - "Invalid arguments to poly_mult") - len(p)==2 ? poly_mult(p[0],p[1]) - : poly_mult(p[0], poly_mult(select(p,1,-1))) - : - _poly_trim( - [ - for(n = [len(p)+len(q)-2:-1:0]) - sum( [for(i=[0:1:len(p)-1]) - let(j = len(p)+len(q)- 2 - n - i) - if (j>=0 && j