mirror of
https://github.com/BelfrySCAD/BOSL2.git
synced 2024-12-29 16:29:40 +00:00
improved back_substitute, cleaned up a few other functions, removed
some non-breaking space characters.
This commit is contained in:
parent
a2e177ecf4
commit
046266778c
1 changed files with 41 additions and 60 deletions
101
math.scad
101
math.scad
|
@ -773,26 +773,26 @@ function _qr_factor(A,Q, column, m, n) =
|
||||||
// You can supply a compatible matrix b and it will produce the solution for every column of b. Note that if you want to
|
// You can supply a compatible matrix b and it will produce the solution for every column of b. Note that if you want to
|
||||||
// solve Rx=b1 and Rx=b2 you must set b to transpose([b1,b2]) and then take the transpose of the result. If the matrix
|
// solve Rx=b1 and Rx=b2 you must set b to transpose([b1,b2]) and then take the transpose of the result. If the matrix
|
||||||
// is singular (e.g. has a zero on the diagonal) then it returns [].
|
// is singular (e.g. has a zero on the diagonal) then it returns [].
|
||||||
function back_substitute(R, b, x=[],transpose = false) =
|
function back_substitute(R, b, transpose = false) =
|
||||||
assert(is_matrix(R, square=true))
|
assert(is_matrix(R, square=true))
|
||||||
let(n=len(R))
|
let(n=len(R))
|
||||||
assert(is_vector(b,n) || is_matrix(b,n),str("R and b are not compatible in back_substitute ",n, len(b)))
|
assert(is_vector(b,n) || is_matrix(b,n),str("R and b are not compatible in back_substitute ",n, len(b)))
|
||||||
!is_vector(b) ? transpose([for(i=[0:len(b[0])-1]) back_substitute(R,subindex(b,i),transpose=transpose)]) :
|
transpose
|
||||||
transpose?
|
? reverse(_back_substitute([for(i=[0:n-1]) [for(j=[0:n-1]) R[n-1-j][n-1-i]]],
|
||||||
reverse(back_substitute(
|
reverse(b)))
|
||||||
[for(i=[0:n-1]) [for(j=[0:n-1]) R[n-1-j][n-1-i]]],
|
: _back_substitute(R,b);
|
||||||
reverse(b), x, false
|
|
||||||
)) :
|
function _back_substitute(R, b, x=[]) =
|
||||||
len(x) == n ? x :
|
let(n=len(R))
|
||||||
let(
|
len(x) == n ? x
|
||||||
ind = n - len(x) - 1
|
: let(ind = n - len(x) - 1)
|
||||||
)
|
R[ind][ind] == 0 ? []
|
||||||
R[ind][ind] == 0 ? [] :
|
: let(
|
||||||
let(
|
newvalue = len(x)==0
|
||||||
newvalue =
|
? b[ind]/R[ind][ind]
|
||||||
len(x)==0? b[ind]/R[ind][ind] :
|
: (b[ind]-select(R[ind],ind+1,-1) * x)/R[ind][ind]
|
||||||
(b[ind]-select(R[ind],ind+1,-1) * x)/R[ind][ind]
|
)
|
||||||
) back_substitute(R, b, concat([newvalue],x));
|
_back_substitute(R, b, concat([newvalue],x));
|
||||||
|
|
||||||
|
|
||||||
// Function: det2()
|
// Function: det2()
|
||||||
|
@ -1120,19 +1120,21 @@ function _deriv_nonuniform(data, h, closed) =
|
||||||
// closed = boolean to indicate if the data set should be wrapped around from the end to the start.
|
// closed = boolean to indicate if the data set should be wrapped around from the end to the start.
|
||||||
function deriv2(data, h=1, closed=false) =
|
function deriv2(data, h=1, closed=false) =
|
||||||
assert( is_consistent(data) , "Input list is not consistent or not numerical.")
|
assert( is_consistent(data) , "Input list is not consistent or not numerical.")
|
||||||
assert( len(data)>=3, "Input list has less than 3 elements.")
|
|
||||||
assert( is_finite(h), "The sampling `h` must be a number." )
|
assert( is_finite(h), "The sampling `h` must be a number." )
|
||||||
let( L = len(data) )
|
let( L = len(data) )
|
||||||
closed? [
|
assert( L>=3, "Input list has less than 3 elements.")
|
||||||
|
closed
|
||||||
|
? [
|
||||||
for(i=[0:1:L-1])
|
for(i=[0:1:L-1])
|
||||||
(data[(i+1)%L]-2*data[i]+data[(L+i-1)%L])/h/h
|
(data[(i+1)%L]-2*data[i]+data[(L+i-1)%L])/h/h
|
||||||
] :
|
]
|
||||||
|
:
|
||||||
let(
|
let(
|
||||||
first = L<3? undef :
|
first =
|
||||||
L==3? data[0] - 2*data[1] + data[2] :
|
L==3? data[0] - 2*data[1] + data[2] :
|
||||||
L==4? 2*data[0] - 5*data[1] + 4*data[2] - data[3] :
|
L==4? 2*data[0] - 5*data[1] + 4*data[2] - data[3] :
|
||||||
(35*data[0] - 104*data[1] + 114*data[2] - 56*data[3] + 11*data[4])/12,
|
(35*data[0] - 104*data[1] + 114*data[2] - 56*data[3] + 11*data[4])/12,
|
||||||
last = L<3? undef :
|
last =
|
||||||
L==3? data[L-1] - 2*data[L-2] + data[L-3] :
|
L==3? data[L-1] - 2*data[L-2] + data[L-3] :
|
||||||
L==4? -2*data[L-1] + 5*data[L-2] - 4*data[L-3] + data[L-4] :
|
L==4? -2*data[L-1] + 5*data[L-2] - 4*data[L-3] + data[L-4] :
|
||||||
(35*data[L-1] - 104*data[L-2] + 114*data[L-3] - 56*data[L-4] + 11*data[L-5])/12
|
(35*data[L-1] - 104*data[L-2] + 114*data[L-3] - 56*data[L-4] + 11*data[L-5])/12
|
||||||
|
@ -1212,34 +1214,13 @@ function C_div(z1,z2) =
|
||||||
// The polynomial is specified as p=[a_n, a_{n-1},...,a_1,a_0]
|
// The polynomial is specified as p=[a_n, a_{n-1},...,a_1,a_0]
|
||||||
// where a_n is the z^n coefficient. Polynomial coefficients are real.
|
// 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.
|
// The result is a number if `z` is a number and a complex number otherwise.
|
||||||
|
|
||||||
// Note: this should probably be recoded to use division by [1,-z], which is more accurate
|
|
||||||
// and avoids overflow with large coefficients, but requires poly_div to support complex coefficients.
|
|
||||||
function polynomial(p, z, _k, _zk, _total) =
|
|
||||||
is_undef(_k)
|
|
||||||
? assert( is_vector(p), "Input polynomial coefficients must be a vector." )
|
|
||||||
let(p = _poly_trim(p))
|
|
||||||
assert( is_finite(z) || is_vector(z,2), "The value of `z` must be a real or a complex number." )
|
|
||||||
polynomial( p,
|
|
||||||
z,
|
|
||||||
len(p)-1,
|
|
||||||
is_num(z)? 1 : [1,0],
|
|
||||||
is_num(z) ? 0 : [0,0])
|
|
||||||
: _k==0
|
|
||||||
? _total + +_zk*p[0]
|
|
||||||
: polynomial( p,
|
|
||||||
z,
|
|
||||||
_k-1,
|
|
||||||
is_num(z) ? _zk*z : C_times(_zk,z),
|
|
||||||
_total+_zk*p[_k]);
|
|
||||||
|
|
||||||
function polynomial(p,z,k,total) =
|
function polynomial(p,z,k,total) =
|
||||||
is_undef(k)
|
is_undef(k)
|
||||||
? assert( is_vector(p) , "Input polynomial coefficients must be a vector." )
|
? 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." )
|
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])
|
polynomial( _poly_trim(p), z, 0, is_num(z) ? 0 : [0,0])
|
||||||
: k==len(p) ? total
|
: k==len(p) ? total
|
||||||
: polynomial(p,z,k+1, is_num(z) ? total*z+p[k] : C_times(total,z)+[p[k],0]);
|
: polynomial(p,z,k+1, is_num(z) ? total*z+p[k] : C_times(total,z)+[p[k],0]);
|
||||||
|
|
||||||
// Function: poly_mult()
|
// Function: poly_mult()
|
||||||
// Usage:
|
// Usage:
|
||||||
|
@ -1266,18 +1247,18 @@ function poly_mult(p,q) =
|
||||||
]);
|
]);
|
||||||
|
|
||||||
function poly_mult(p,q) =
|
function poly_mult(p,q) =
|
||||||
is_undef(q) ?
|
is_undef(q) ?
|
||||||
len(p)==2 ? poly_mult(p[0],p[1])
|
len(p)==2 ? poly_mult(p[0],p[1])
|
||||||
: poly_mult(p[0], poly_mult(select(p,1,-1)))
|
: poly_mult(p[0], poly_mult(select(p,1,-1)))
|
||||||
:
|
:
|
||||||
assert( is_vector(p) && is_vector(q),"Invalid arguments to poly_mult")
|
assert( is_vector(p) && is_vector(q),"Invalid arguments to poly_mult")
|
||||||
_poly_trim( [
|
_poly_trim( [
|
||||||
for(n = [len(p)+len(q)-2:-1:0])
|
for(n = [len(p)+len(q)-2:-1:0])
|
||||||
sum( [for(i=[0:1:len(p)-1])
|
sum( [for(i=[0:1:len(p)-1])
|
||||||
let(j = len(p)+len(q)- 2 - n - i)
|
let(j = len(p)+len(q)- 2 - n - i)
|
||||||
if (j>=0 && j<len(q)) p[i]*q[j]
|
if (j>=0 && j<len(q)) p[i]*q[j]
|
||||||
])
|
])
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|
||||||
// Function: poly_div()
|
// Function: poly_div()
|
||||||
|
|
Loading…
Reference in a new issue