def sym_eig2x2(A, dt): """Compute the eigenvalues and right eigenvectors (Av=lambda v) of a 2x2 real symmetric matrix. Mathematical concept refers to https://en.wikipedia.org/wiki/Eigendecomposition_of_a_matrix. Args: A (ti.Matrix(2, 2)): input 2x2 symmetric matrix `A`. dt (DataType): date type of elements in matrix `A`, typically accepts ti.f32 or ti.f64. Returns: eigenvalues (ti.Vector(2)): The eigenvalues. Each entry store one eigen value. eigenvectors (ti.Matrix(2, 2)): The eigenvectors. Each column stores one eigenvector. """ tr = A.trace() det = A.determinant() gap = tr**2 - 4 * det lambda1 = (tr + ops.sqrt(gap)) * 0.5 lambda2 = (tr - ops.sqrt(gap)) * 0.5 eigenvalues = Vector([lambda1, lambda2], dt=dt) A1 = A - lambda1 * Matrix.identity(dt, 2) A2 = A - lambda2 * Matrix.identity(dt, 2) v1 = Vector.zero(dt, 2) v2 = Vector.zero(dt, 2) if all(A1 == Matrix.zero(dt, 2, 2)) and all(A1 == Matrix.zero(dt, 2, 2)): v1 = Vector([0.0, 1.0]).cast(dt) v2 = Vector([1.0, 0.0]).cast(dt) else: v1 = Vector([A2[0, 0], A2[1, 0]], dt=dt).normalized() v2 = Vector([A1[0, 0], A1[1, 0]], dt=dt).normalized() eigenvectors = Matrix.cols([v1, v2]) return eigenvalues, eigenvectors
def eig2x2(A, dt): """Compute the eigenvalues and right eigenvectors (Av=lambda v) of a 2x2 real matrix. Mathematical concept refers to https://en.wikipedia.org/wiki/Eigendecomposition_of_a_matrix. Args: A (ti.Matrix(2, 2)): input 2x2 matrix `A`. dt (DataType): date type of elements in matrix `A`, typically accepts ti.f32 or ti.f64. Returns: eigenvalues (ti.Matrix(2, 2)): The eigenvalues in complex form. Each row stores one eigenvalue. The first number of the eigenvalue represents the real part and the second number represents the imaginary part. eigenvectors: (ti.Matrix(4, 2)): The eigenvectors in complex form. Each column stores one eigenvector. Each eigenvector consists of 2 entries, each of which is represented by two numbers for its real part and imaginary part. """ tr = A.trace() det = A.determinant() gap = tr**2 - 4 * det lambda1 = Vector.zero(dt, 2) lambda2 = Vector.zero(dt, 2) v1 = Vector.zero(dt, 4) v2 = Vector.zero(dt, 4) if gap > 0: lambda1 = Vector([tr + ops.sqrt(gap), 0.0], dt=dt) * 0.5 lambda2 = Vector([tr - ops.sqrt(gap), 0.0], dt=dt) * 0.5 A1 = A - lambda1[0] * Matrix.identity(dt, 2) A2 = A - lambda2[0] * Matrix.identity(dt, 2) if all(A1 == Matrix.zero(dt, 2, 2)) and all( A1 == Matrix.zero(dt, 2, 2)): v1 = Vector([0.0, 0.0, 1.0, 0.0]).cast(dt) v2 = Vector([1.0, 0.0, 0.0, 0.0]).cast(dt) else: v1 = Vector([A2[0, 0], 0.0, A2[1, 0], 0.0], dt=dt).normalized() v2 = Vector([A1[0, 0], 0.0, A1[1, 0], 0.0], dt=dt).normalized() else: lambda1 = Vector([tr, ops.sqrt(-gap)], dt=dt) * 0.5 lambda2 = Vector([tr, -ops.sqrt(-gap)], dt=dt) * 0.5 A1r = A - lambda1[0] * Matrix.identity(dt, 2) A1i = -lambda1[1] * Matrix.identity(dt, 2) A2r = A - lambda2[0] * Matrix.identity(dt, 2) A2i = -lambda2[1] * Matrix.identity(dt, 2) v1 = Vector([A2r[0, 0], A2i[0, 0], A2r[1, 0], A2i[1, 0]], dt=dt).normalized() v2 = Vector([A1r[0, 0], A1i[0, 0], A1r[1, 0], A1i[1, 0]], dt=dt).normalized() eigenvalues = Matrix.rows([lambda1, lambda2]) eigenvectors = Matrix.cols([v1, v2]) return eigenvalues, eigenvectors