Conjugate transpose: Difference between revisions
Content added Content deleted
(add FreeBASIC) |
|||
Line 1,813: | Line 1,813: | ||
{HermitianMatrixQ@#, NormalMatrixQ@#, UnitaryQ@#}&@m |
{HermitianMatrixQ@#, NormalMatrixQ@#, UnitaryQ@#}&@m |
||
-> {False, False, False}</lang> |
-> {False, False, False}</lang> |
||
=={{header|Nim}}== |
|||
The complex type is defined as generic regarding the type of real an imaginary part. We have chosen to use Complex[float] and make only our Matrix type generic regarding the dimensions. Thus, a Matrix has a two dimensions M and N which are static, i.e. known at compile time. We have enforced the condition M = N for square matrices (also at compile time). |
|||
<lang Nim>import complex, strformat |
|||
type Matrix[M, N: static Positive] = array[M, array[N, Complex[float]]] |
|||
const Eps = 1e-10 # Tolerance used for float comparisons. |
|||
#################################################################################################### |
|||
# Templates. |
|||
template `[]`(m: Matrix; i, j: Natural): Complex[float] = |
|||
## Allow to get value of an element using m[i, j] syntax. |
|||
m[i][j] |
|||
template `[]=`(m: var Matrix; i, j: Natural; val: Complex[float]) = |
|||
## Allow to set value of an element using m[i, j] syntax. |
|||
m[i][j] = val |
|||
#################################################################################################### |
|||
# General operations. |
|||
func `$`(m: Matrix): string = |
|||
## Return the string representation of a matrix using one line per row. |
|||
for i, row in m: |
|||
result.add(if i == 0: '[' else: ' ') |
|||
for j, val in row: |
|||
if j != 0: result.add(' ') |
|||
result.add(&"({val.re:7.4f}, {val.im:7.4f})") |
|||
result.add(if i == m.high: ']' else: '\n') |
|||
#--------------------------------------------------------------------------------------------------- |
|||
func conjugateTransposed[M, N: static int](m: Matrix[M, N]): Matrix[N, M] = |
|||
## Return the conjugate transpose of a matrix. |
|||
for i in 0..<m.M: |
|||
for j in 0..<m.N: |
|||
result[j, i] = m[i, j].conjugate() |
|||
#--------------------------------------------------------------------------------------------------- |
|||
func `*`[M, K, N: static int](m1: Matrix[M, K]; m2: Matrix[K, N]): Matrix[M, N] = |
|||
# Compute the product of two matrices. |
|||
for i in 0..<M: |
|||
for j in 0..<N: |
|||
for k in 0..<K: |
|||
result[i, j] = result[i, j] + m1[i, k] * m2[k, j] |
|||
#################################################################################################### |
|||
# Properties. |
|||
func isHermitian(m: Matrix): bool = |
|||
## Check if a matrix is hermitian. |
|||
when m.M != m.N: |
|||
{.error: "hermitian test only allowed for square matrices".} |
|||
else: |
|||
for i in 0..<m.M: |
|||
for j in i..<m.N: |
|||
if m[i, j] != m[j, i].conjugate: |
|||
return false |
|||
result = true |
|||
#--------------------------------------------------------------------------------------------------- |
|||
func isNormal(m: Matrix): bool = |
|||
## Check if a matrix is normal. |
|||
when m.M != m.N: |
|||
{.error: "normal test only allowed for square matrices".} |
|||
else: |
|||
let h = m.conjugateTransposed |
|||
result = m * h == h * m |
|||
#--------------------------------------------------------------------------------------------------- |
|||
func isIdentity(m: Matrix): bool = |
|||
## Check if a matrix is the identity matrix. |
|||
when m.M != m.N: |
|||
{.error: "identity test only allowed for square matrices".} |
|||
else: |
|||
for i in 0..<m.M: |
|||
for j in 0..<m.N: |
|||
if i == j: |
|||
if abs(m[i, j] - 1.0) > Eps: |
|||
return false |
|||
else: |
|||
if abs(m[i, j]) > Eps: |
|||
return false |
|||
result = true |
|||
#--------------------------------------------------------------------------------------------------- |
|||
func isUnitary(m: Matrix): bool = |
|||
## Check if a matrix is unitary. |
|||
when m.M != m.N: |
|||
{.error: "unitary test only allowed for square matrices".} |
|||
else: |
|||
let h = m.conjugateTransposed |
|||
result = (m * h).isIdentity and (h * m).isIdentity |
|||
#——————————————————————————————————————————————————————————————————————————————————————————————————— |
|||
when isMainModule: |
|||
import math |
|||
proc test(m: Matrix) = |
|||
echo "\n" |
|||
echo "Matrix" |
|||
echo "------" |
|||
echo m |
|||
echo "" |
|||
echo "Conjugate transposed" |
|||
echo "--------------------" |
|||
echo m.conjugateTransposed |
|||
when m.M == m.N: |
|||
# Only for squares matrices. |
|||
echo "" |
|||
echo "Hermitian: ", m.isHermitian |
|||
echo "Normal: ", m.isNormal |
|||
echo "Unitary: ", m.isUnitary |
|||
#------------------------------------------------------------------------------------------------- |
|||
# Non square matrix. |
|||
const M1: Matrix[2, 3] = [[1.0 + im 2.0, 3.0 + im 0.0, 2.0 + im 5.0], |
|||
[3.0 - im 1.0, 2.0 + im 0.0, 0.0 + im 3.0]] |
|||
# Square matrices. |
|||
const M2: Matrix[2, 2] = [[3.0 + im 0.0, 2.0 + im 1.0], |
|||
[2.0 - im 1.0, 1.0 + im 0.0]] |
|||
const M3: Matrix[3, 3] = [[1.0 + im 0.0, 1.0 + im 0.0, 0.0 + im 0.0], |
|||
[0.0 + im 0.0, 1.0 + im 0.0, 1.0 + im 0.0], |
|||
[1.0 + im 0.0, 0.0 + im 0.0, 1.0 + im 0.0]] |
|||
const SR2 = 1 / sqrt(2.0) |
|||
const M4: Matrix[3, 3] = [[SR2 + im 0.0, SR2 + im 0.0, 0.0 + im 0.0], |
|||
[0.0 + im SR2, 0.0 - im SR2, 0.0 + im 0.0], |
|||
[0.0 + im 0.0, 0.0 + im 0.0, 0.0 + im 1.0]] |
|||
test(M1) |
|||
test(M2) |
|||
test(M3) |
|||
test(M4)</lang> |
|||
{{out}} |
|||
<pre>Matrix |
|||
------ |
|||
[( 1.0000, 2.0000) ( 3.0000, 0.0000) ( 2.0000, 5.0000) |
|||
( 3.0000, -1.0000) ( 2.0000, 0.0000) ( 0.0000, 3.0000)] |
|||
Conjugate transposed |
|||
-------------------- |
|||
[( 1.0000, -2.0000) ( 3.0000, 1.0000) |
|||
( 3.0000, -0.0000) ( 2.0000, -0.0000) |
|||
( 2.0000, -5.0000) ( 0.0000, -3.0000)] |
|||
Matrix |
|||
------ |
|||
[( 3.0000, 0.0000) ( 2.0000, 1.0000) |
|||
( 2.0000, -1.0000) ( 1.0000, 0.0000)] |
|||
Conjugate transposed |
|||
-------------------- |
|||
[( 3.0000, -0.0000) ( 2.0000, 1.0000) |
|||
( 2.0000, -1.0000) ( 1.0000, -0.0000)] |
|||
Hermitian: true |
|||
Normal: true |
|||
Unitary: false |
|||
Matrix |
|||
------ |
|||
[( 1.0000, 0.0000) ( 1.0000, 0.0000) ( 0.0000, 0.0000) |
|||
( 0.0000, 0.0000) ( 1.0000, 0.0000) ( 1.0000, 0.0000) |
|||
( 1.0000, 0.0000) ( 0.0000, 0.0000) ( 1.0000, 0.0000)] |
|||
Conjugate transposed |
|||
-------------------- |
|||
[( 1.0000, -0.0000) ( 0.0000, -0.0000) ( 1.0000, -0.0000) |
|||
( 1.0000, -0.0000) ( 1.0000, -0.0000) ( 0.0000, -0.0000) |
|||
( 0.0000, -0.0000) ( 1.0000, -0.0000) ( 1.0000, -0.0000)] |
|||
Hermitian: false |
|||
Normal: true |
|||
Unitary: false |
|||
Matrix |
|||
------ |
|||
[( 0.7071, 0.0000) ( 0.7071, 0.0000) ( 0.0000, 0.0000) |
|||
( 0.0000, 0.7071) ( 0.0000, -0.7071) ( 0.0000, 0.0000) |
|||
( 0.0000, 0.0000) ( 0.0000, 0.0000) ( 0.0000, 1.0000)] |
|||
Conjugate transposed |
|||
-------------------- |
|||
[( 0.7071, -0.0000) ( 0.0000, -0.7071) ( 0.0000, -0.0000) |
|||
( 0.7071, -0.0000) ( 0.0000, 0.7071) ( 0.0000, -0.0000) |
|||
( 0.0000, -0.0000) ( 0.0000, -0.0000) ( 0.0000, -1.0000)] |
|||
Hermitian: false |
|||
Normal: true |
|||
Unitary: true</pre> |
|||
=={{header|PARI/GP}}== |
=={{header|PARI/GP}}== |