Fix bug in skin, add some complex stuff to math and tests

This commit is contained in:
Adrian Mariano
2021-03-12 20:36:34 -05:00
parent d8f1581149
commit 4dc2d4cfe5
4 changed files with 177 additions and 27 deletions

114
math.scad
View File

@@ -1465,19 +1465,52 @@ function deriv3(data, h=1, closed=false) =
// Section: Complex Numbers
// Function: complex()
// Usage:
// z = complex(list)
// Description:
// Converts a real valued number, vector or matrix into its complex analog
// by replacing all entries with a 2-vector that has zero imaginary part.
function complex(list) =
is_num(list) ? [list,0] :
[for(entry=list) is_num(entry) ? [entry,0] : complex(entry)];
// Function: c_mul()
// Usage:
// c = c_mul(z1,z2)
// Description:
// Multiplies two complex numbers represented by 2D vectors.
// Returns a complex number as a 2D vector [REAL, IMAGINARY].
// Multiplies two complex numbers, vectors or matrices, where complex numbers
// or entries are represented as vectors: [REAL, IMAGINARY]. Note that all
// entries in both arguments must be complex.
// Arguments:
// z1 = First complex number, given as a 2D vector [REAL, IMAGINARY]
// z2 = Second complex number, given as a 2D vector [REAL, IMAGINARY]
function c_mul(z1,z2) =
assert( is_matrix([z1,z2],2,2), "Complex numbers should be represented by 2D vectors" )
// z1 = First complex number, vector or matrix
// z2 = Second complex number, vector or matrix
function _split_complex(data) =
is_vector(data,2) ? data
: is_num(data[0][0]) ? [data*[1,0], data*[0,1]]
: [
[for(vec=data) vec * [1,0]],
[for(vec=data) vec * [0,1]]
];
function _combine_complex(data) =
is_vector(data,2) ? data
: is_num(data[0][0]) ? [for(i=[0:len(data[0])-1]) [data[0][i],data[1][i]]]
: [for(i=[0:1:len(data[0])-1])
[for(j=[0:1:len(data[0][0])-1])
[data[0][i][j], data[1][i][j]]]];
function _c_mul(z1,z2) =
[ z1.x*z2.x - z1.y*z2.y, z1.x*z2.y + z1.y*z2.x ];
function c_mul(z1,z2) =
is_matrix([z1,z2],2,2) ? _c_mul(z1,z2) :
_combine_complex(_c_mul(_split_complex(z1), _split_complex(z2)));
// Function: c_div()
// Usage:
// x = c_div(z1,z2)
@@ -1493,7 +1526,52 @@ function c_div(z1,z2) =
let(den = z2.x*z2.x + z2.y*z2.y)
[(z1.x*z2.x + z1.y*z2.y)/den, (z1.y*z2.x - z1.x*z2.y)/den];
// For the sake of consistence with Q_mul and vmul, c_mul should be called C_mul
// Function: c_conj()
// Usage:
// w = c_conj(z)
// Description:
// Computes the complex conjugate of the input, which can be a complex number,
// complex vector or complex matrix.
function c_conj(z) =
is_vector(z,2) ? [z.x,-z.y] :
[for(entry=z) c_conj(entry)];
// Function: c_real()
// Usage:
// x = c_real(z)
// Description:
// Returns real part of a complex number, vector or matrix.
function c_real(z) =
is_vector(z,2) ? z.x
: is_num(z[0][0]) ? z*[1,0]
: [for(vec=z) vec * [1,0]];
// Function: c_imag()
// Usage:
// x = c_imag(z)
// Description:
// Returns imaginary part of a complex number, vector or matrix.
function c_imag(z) =
is_vector(z,2) ? z.y
: is_num(z[0][0]) ? z*[0,1]
: [for(vec=z) vec * [0,1]];
// Function: c_ident()
// Usage:
// I = c_ident(n)
// Description:
// Produce an n by n complex identity matrix
function c_ident(n) = [for (i = [0:1:n-1]) [for (j = [0:1:n-1]) (i==j)?[1,0]:[0,0]]];
// Function: c_norm()
// Usage:
// n = c_norm(z)
// Description:
// Compute the norm of a complex number or vector.
function c_norm(z) = norm_fro(z);
// Section: Polynomials
@@ -1539,12 +1617,12 @@ function quadratic_roots(a,b,c,real=false) =
// 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_mul(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_mul(total,z)+[p[k],0]);
// Function: poly_mult()
// Usage:
@@ -1554,12 +1632,12 @@ 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) ?
        len(p)==2
is_undef(q) ?
len(p)==2
? poly_mult(p[0],p[1])
        : poly_mult(p[0], poly_mult(select(p,1,-1)))
    :
    assert( is_vector(p) && is_vector(q),"Invalid arguments to poly_mult")
: poly_mult(p[0], poly_mult(select(p,1,-1)))
:
assert( is_vector(p) && is_vector(q),"Invalid arguments to poly_mult")
p*p==0 || q*q==0
? [0]
: _poly_trim(convolve(p,q));