Conjugate transpose: Difference between revisions

m
syntax highlighting fixup automation
(Realize in F#)
m (syntax highlighting fixup automation)
Line 38:
{{trans|Nim}}
 
<langsyntaxhighlight lang="11l">-V eps = 1e-10
 
F to_str(m)
Line 131:
test(M3)
print("\n")
test(M4)</langsyntaxhighlight>
 
{{out}}
Line 185:
 
=={{header|Ada}}==
<langsyntaxhighlight Adalang="ada">with Ada.Text_IO; use Ada.Text_IO;
with Ada.Complex_Text_IO; use Ada.Complex_Text_IO;
with Ada.Numerics.Complex_Types; use Ada.Numerics.Complex_Types;
Line 231:
Put_Line("nmat:"); Examine(nmat); New_Line;
Put_Line("umat:"); Examine(umat);
end ConTrans;</langsyntaxhighlight>
{{out}}
<pre>hmat:
Line 269:
=={{header|ALGOL 68}}==
Uses the same test cases as the Ada sample.
<langsyntaxhighlight lang="algol68">BEGIN # find and classify the complex conjugate transpose of a complex matrix #
# returns the conjugate transpose of m #
OP CONJUGATETRANSPOSE = ( [,]COMPL m )[,]COMPL:
Line 367:
)
)
END</langsyntaxhighlight>
{{out}}
<pre>
Line 399:
 
=={{header|C}}==
<langsyntaxhighlight lang="c">/* Uses C99 specified complex.h, complex datatype has to be defined and operation provided if used on non-C99 compilers */
 
#include<stdlib.h>
Line 579:
 
return 0;
}</langsyntaxhighlight>
{{out}}
<pre>
Line 600:
 
=={{header|C++}}==
<langsyntaxhighlight lang="cpp">#include <cassert>
#include <cmath>
#include <complex>
Line 790:
test(matrix3);
return 0;
}</langsyntaxhighlight>
 
{{out}}
Line 832:
 
=={{header|Common Lisp}}==
<syntaxhighlight lang="lisp">
<lang Lisp>
(defun matrix-multiply (m1 m2)
(mapcar
Line 863:
(defun unitary-p (m)
(identity-p (matrix-multiply m (conjugate-transpose m))) )
</syntaxhighlight>
</lang>
 
{{out}}
Line 886:
=={{header|D}}==
{{trans|Python}} A well typed and mostly imperative version:
<langsyntaxhighlight lang="d">import std.stdio, std.complex, std.math, std.range, std.algorithm,
std.numeric;
 
Line 992:
writefln("Unitary? %s.\n", isUnitary(mat, ct));
}
}</langsyntaxhighlight>
{{out}}
<pre>Matrix:
Line 1,031:
===Alternative Version===
A more functional version that contains some typing problems (same output).
<langsyntaxhighlight lang="d">import std.stdio, std.complex, std.math, std.range, std.algorithm,
std.numeric, std.exception, std.traits;
 
Line 1,120:
writefln("Unitary? %s.\n", isUnitary(mat, ct));
}
}</langsyntaxhighlight>
 
=={{header|F_Sharp|F#}}==
<langsyntaxhighlight lang="fsharp">
// Conjugate transpose. Nigel Galloway: January 10th., 2022
let fN g=let g=g|>List.map(List.map(fun(n,g)->System.Numerics.Complex(n,g)))|>MathNet.Numerics.LinearAlgebra.MatrixExtensions.matrix in (g,g.ConjugateTranspose())
Line 1,129:
let test=[fN [[(3.0,0.0);(2.0,1.0)];[(2.0,-1.0);(1.0,0.0)]];fN [[(1.0,0.0);(1.0,0.0);(0.0,0.0)];[(0.0,0.0);(1.0,0.0);(1.0,0.0)];[(1.0,0.0);(0.0,0.0);(1.0,0.0)]];fN [[(1.0/sqrt 2.0,0.0);(1.0/sqrt 2.0,0.0);(0.0,0.0)];[(0.0,1.0/sqrt 2.0);(0.0,-1.0/sqrt 2.0);(0.0,0.0)];[(0.0,0.0);(0.0,0.0);(0.0,1.0)]]]
test|>List.iter(fun(n,g)->printfn $"Matrix\n------\n%A{n}\nConjugate transposed\n--------------------\n%A{g}\nIs hermitian: %A{n.IsHermitian()}\nIs normal: %A{n*g=g*n}\nIs unitary: %A{fG n g}\n")
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 1,188:
 
{{works with|Factor|development (future 0.95)}}
<langsyntaxhighlight lang="factor">USING: kernel math.functions math.matrices sequences ;
IN: rosetta.hermitian
 
Line 1,201:
 
: unitary-matrix? ( matrix -- ? )
[ dup conj-t m. ] [ length identity-matrix ] bi = ;</langsyntaxhighlight>
 
Usage:
Line 1,219:
The examples and algorithms are taken from the j solution, except for UnitaryQ. The j solution uses the matrix inverse verb. Compilation on linux, assuming the program is file f.f08 :<pre>
gfortran -std=f2008 -Wall -fopenmp -ffree-form -fall-intrinsics -fimplicit-none f.f08 -o f</pre>
<syntaxhighlight lang="fortran">
<lang FORTRAN>
program conjugate_transpose
 
Line 1,284:
 
end program conjugate_transpose
</syntaxhighlight>
</lang>
<pre>
-*- mode: compilation; default-directory: "/tmp/" -*-
Line 1,331:
 
=={{header|FreeBASIC}}==
<langsyntaxhighlight lang="freebasic">'complex type and operators for it
type complex
real as double
Line 1,460:
print is_hermitian(A), is_normal(A), is_unitary(A)
print is_hermitian(B), is_normal(B), is_unitary(B)
print is_hermitian(C), is_normal(C), is_unitary(C)</langsyntaxhighlight>
{{out}}
<pre>true true true
Line 1,467:
 
=={{header|Go}}==
<langsyntaxhighlight lang="go">package main
 
import (
Line 1,578:
}
return m3
}</langsyntaxhighlight>
Output:
<pre>
Line 1,621:
=={{header|Haskell}}==
Slow implementation using lists.
<langsyntaxhighlight lang="haskell">import Data.Complex (Complex(..), conjugate)
import Data.List (transpose)
 
Line 1,695:
:: Num a
=> Matrix (Complex a) -> Matrix (Complex a)
conjTranspose = map (map conjugate) . transpose</langsyntaxhighlight>
Output:
<pre>
Line 1,735:
=={{header|J}}==
 
'''Solution''': <langsyntaxhighlight lang="j"> ct =: +@|: NB. Conjugate transpose (ct A is A_ct)</langsyntaxhighlight>
'''Examples''': <langsyntaxhighlight lang="j"> X =: +/ . * NB. Matrix Multiply (x)
 
HERMITIAN =: 3 2j1 ,: 2j_1 1
Line 1,748:
UNITARY =: (-:%:2) * 1 1 0 , 0j_1 0j1 0 ,: 0 0 0j1 * %:2
(ct -: %.) UNITARY NB. A_ct = A^-1
1</langsyntaxhighlight>
 
'''Reference''' (example matrices for other langs to use):<langsyntaxhighlight lang="j"> HERMITIAN;NORMAL;UNITARY
+--------+-----+--------------------------+
| 3 2j1|1 1 0| 0.707107 0.707107 0|
Line 1,765:
+-----+-----+-----+
|1 1 0|0 1 0|0 1 1|
+-----+-----+-----+</langsyntaxhighlight>
 
=={{header|jq}}==
Line 1,777:
 
If your jq does not have "transpose" then the following may be used:
<langsyntaxhighlight lang="jq"># transpose/0 expects its input to be a rectangular matrix
# (an array of equal-length arrays):
def transpose:
if (.[0] | length) == 0 then []
else [map(.[0])] + (map(.[1:]) | transpose)
end ;</langsyntaxhighlight>
'''(2) Operations on real/complex numbers'''
<langsyntaxhighlight lang="jq"># x must be real or complex, and ditto for y;
# always return complex
def plus(x; y):
Line 1,810:
if type == "number" then [.,0]
else [.[0], -(.[1]) ]
end;</langsyntaxhighlight>
'''(3) Array operations'''
<langsyntaxhighlight lang="jq"># a and b are arrays of real/complex numbers
def dot_product(a; b):
a as $a | b as $b
| reduce range(0;$a|length) as $i
(0; . as $s | plus($s; multiply($a[$i]; $b[$i]) ));</langsyntaxhighlight>
'''(4) Matrix operations'''
<langsyntaxhighlight lang="jq"># convert a matrix of mixed real/complex entries to all complex entries
def to_complex:
def toc: if type == "number" then [.,0] else . end;
Line 1,855:
reduce range(0;M|length) as $i
(0; reduce range(0; M[0]|length) as $j
(.; 0 + sqdiff( M[$i][$j]; N[$i][$j] ) ) ) <= epsilon;</langsyntaxhighlight>
====Conjugate transposition====
<langsyntaxhighlight lang="jq"># (entries may be real and/or complex)
def conjugate_transpose:
map( map(conjugate) ) | transpose;
Line 1,879:
| complex_identity(length) as $I
| approximately_equal( $I; matrix_multiply($H;$M); 1e-10)
and approximately_equal( $I ; matrix_multiply($M;$H); 1e-10) ; </langsyntaxhighlight>
 
====Examples====
<langsyntaxhighlight lang="jq">def hermitian_example:
[ [ 3, [2,1]],
[[2,-1], 1 ] ];
Line 1,910:
;
 
demo</langsyntaxhighlight>
{{out}}
<langsyntaxhighlight lang="sh">$ jq -r -c -n -f Conjugate_transpose.jq
Hermitian example:
 
Line 1,927:
Normal example: true
 
Unitary example: true</langsyntaxhighlight>
 
=={{header|Julia}}==
Julia has a built-in matrix type, and the conjugate-transpose of a complex matrix <code>A</code> is simply:
<syntaxhighlight lang ="julia">A'</langsyntaxhighlight>
(similar to Matlab). You can check whether <code>A</code> is Hermitian via the built-in function
<syntaxhighlight lang ="julia">ishermitian(A)</langsyntaxhighlight>
Ignoring the possibility of roundoff errors for floating-point matrices (like most of the examples in the other languages), you can check whether a matrix is normal or unitary by the following functions
<langsyntaxhighlight lang="julia">eye(A) = A^0
isnormal(A) = size(A,1) == size(A,2) && A'*A == A*A'
isunitary(A) = size(A,1) == size(A,2) && A'*A == eye(A)</langsyntaxhighlight>
 
=={{header|Kotlin}}==
As Kotlin doesn't have built in classes for complex numbers or matrices, some basic functionality needs to be coded in order to tackle this task:
<langsyntaxhighlight lang="scala">// version 1.1.3
 
typealias C = Complex
Line 2,065:
println("Unitary? ${mct.isUnitary()}\n")
}
}</langsyntaxhighlight>
 
{{out}}
Line 2,112:
=={{header|Maple}}==
The commands <code>HermitianTranspose</code> and <code>IsUnitary</code> are provided by the <code>LinearAlgebra</code> package.
<langsyntaxhighlight Maplelang="maple">M:=<<3|2+I>,<2-I|1>>:
 
with(LinearAlgebra):
Line 2,121:
type(M,'Matrix'(hermitian));
IsNormal(M);
IsUnitary(M);</langsyntaxhighlight>
Output:
<pre> [ 3 2 + I]
Line 2,138:
 
=={{header|Mathematica}} / {{header|Wolfram Language}}==
<langsyntaxhighlight Mathematicalang="mathematica">NormalMatrixQ[a_List?MatrixQ] := Module[{b = Conjugate@Transpose@a},a.b === b.a]
UnitaryQ[m_List?MatrixQ] := (Conjugate@Transpose@m.m == IdentityMatrix@Length@m)
 
Line 2,154:
 
{HermitianMatrixQ@#, NormalMatrixQ@#, UnitaryQ@#}&@m
-> {False, False, False}</langsyntaxhighlight>
 
=={{header|Nim}}==
Line 2,160:
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).
 
<langsyntaxhighlight Nimlang="nim">import complex, strformat
 
type Matrix[M, N: static Positive] = array[M, array[N, Complex[float]]]
Line 2,312:
test(M2)
test(M3)
test(M4)</langsyntaxhighlight>
 
{{out}}
Line 2,376:
 
=={{header|PARI/GP}}==
<syntaxhighlight lang="text">conjtranspose(M)=conj(M~)
isHermitian(M)=M==conj(M~)
isnormal(M)=my(H=conj(M~));H*M==M*H
isunitary(M)=M*conj(M~)==1</langsyntaxhighlight>
 
=={{header|Perl}}==
In general, using two or more modules which overload operators can be problematic. For this task, using both Math::Complex and Math::MatrixReal gives us the behavior we want for everything except matrix I/O, i.e. parsing and stringification.
<langsyntaxhighlight lang="perl">use strict;
use English;
use Math::Complex;
Line 2,466:
$m->assign(3, 3, cplx(0, 1));
return $m;
}</langsyntaxhighlight>
{{out}}
<pre>
Line 2,506:
=={{header|Phix}}==
Note this code has no testing for non-square matrices.
<!--<langsyntaxhighlight Phixlang="phix">(phixonline)-->
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
<span style="color: #008080;">include</span> <span style="color: #004080;">complex</span><span style="color: #0000FF;">.</span><span style="color: #000000;">e</span>
Line 2,605:
<span style="color: #7060A8;">papply</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tests</span><span style="color: #0000FF;">,</span><span style="color: #000000;">test</span><span style="color: #0000FF;">)</span>
<!--</langsyntaxhighlight>-->
{{out}}
<pre>
Line 2,676:
 
=={{header|PL/I}}==
<syntaxhighlight lang="pl/i">
<lang PL/I>
test: procedure options (main); /* 1 October 2012 */
declare n fixed binary;
Line 2,726:
end MMULT;
end test;
</syntaxhighlight>
</lang>
Outputs from separate runs:
<pre>
Line 2,770:
 
=={{header|PowerShell}}==
<syntaxhighlight lang="powershell">
<lang PowerShell>
function conjugate-transpose($a) {
$arr = @()
Line 2,847:
"Normal? `$m = $(are-eq $mhm $hmm)"
"Unitary? `$m = $((are-eq $id2 $hmm) -and (are-eq $id2 $mhm))"
</syntaxhighlight>
</lang>
<b>Output:</b>
<pre>
Line 2,873:
=={{header|Python}}==
Internally, matrices must be represented as rectangular tuples of tuples of complex numbers.
<langsyntaxhighlight lang="python">def conjugate_transpose(m):
return tuple(tuple(n.conjugate() for n in row) for row in zip(*m))
 
Line 2,944:
print('Hermitian? %s.' % ishermitian(matrix, ct))
print('Normal? %s.' % isnormal(matrix, ct))
print('Unitary? %s.' % isunitary(matrix, ct))</langsyntaxhighlight>
 
{{out}}
Line 2,982:
 
=={{header|Racket}}==
<langsyntaxhighlight lang="racket">
#lang racket
(require math)
Line 2,999:
(define (hermitian? M)
(equal? (H M) M))
</syntaxhighlight>
</lang>
Test:
<langsyntaxhighlight lang="racket">
(define M (matrix [[3.000+0.000i +2.000+1.000i]
[2.000-1.000i +1.000+0.000i]]))
Line 3,008:
(unitary? M)
(hermitian? M)
</syntaxhighlight>
</lang>
Output:
<langsyntaxhighlight lang="racket">
(array #[#[3.0-0.0i 2.0+1.0i] #[2.0-1.0i 1.0-0.0i]])
#t
#f
#f
</syntaxhighlight>
</lang>
 
=={{header|Raku}}==
(formerly Perl 6)
{{works with|Rakudo|2015-12-13}}
<syntaxhighlight lang="raku" perl6line>for [ # Test Matrices
[ 1, 1+i, 2i],
[ 1-i, 5, -3],
Line 3,071:
}
 
sub say-it (@array) { $_».fmt("%9s").say for @array }</langsyntaxhighlight>
{{out}}
<pre>Matrix:
Line 3,114:
 
=={{header|REXX}}==
<langsyntaxhighlight lang="rexx">/*REXX program performs a conjugate transpose on a complex square matrix. */
parse arg N elements; if N==''|N=="," then N=3 /*Not specified? Then use the default.*/
k= 0; do r=1 for N
Line 3,192:
numeric digits; parse value format(x,2,1,,0) 'E0' with g 'E' _ .; g=g *.5'e'_ % 2
m.=9; do j=0 while h>9; m.j=h; h=h%2+1; end /*j*/
do k=j+5 to 0 by -1; numeric digits m.k; g=(g+x/g)*.5; end /*k*/; return g</langsyntaxhighlight>
{{out|output|text=&nbsp; when using the default input:}}
<pre>
Line 3,235:
=={{header|Ruby}}==
{{works with|Ruby|2.0}}
<langsyntaxhighlight lang="ruby">require 'matrix'
 
# Start with some matrix.
Line 3,259:
print ' normal? false'
print ' unitary? false'
end</langsyntaxhighlight>
Note: Ruby 1.9 had a bug in the Matrix#hermitian? method. It's fixed in 2.0.
 
=={{header|Rust}}==
Uses external crate 'num', version 0.1.34
<langsyntaxhighlight lang="rust">
extern crate num; // crate for complex numbers
 
Line 3,344:
println!("Unitary?: FALSE");
}
}</langsyntaxhighlight>
Output:
<pre>
Line 3,368:
 
=={{header|Scala}}==
<langsyntaxhighlight Scalalang="scala">object ConjugateTranspose {
case class Complex(re: Double, im: Double) {
Line 3,444:
}
}</langsyntaxhighlight>
{{out}}
<pre>
Line 3,464:
=={{header|Sidef}}==
{{trans|Raku}}
<langsyntaxhighlight lang="ruby">func is_Hermitian (Array m, Array t) -> Bool { m == t }
 
func mat_mult (Array a, Array b, Number ε = -3) {
Line 3,529:
say "Is Normal?\t#{is_Normal(m, t)}"
say "Is Unitary?\t#{is_Unitary(m, t)}"
}</langsyntaxhighlight>
{{out}}
<pre>
Line 3,575:
Sparkling has support for basic complex algebraic operations, but complex matrix operations are not in the standard library.
 
<langsyntaxhighlight lang="sparkling"># Computes conjugate transpose of M
let conjTransp = function conjTransp(M) {
return map(range(sizeof M[0]), function(row) {
Line 3,675:
print("U x U* = ");
printCplxMat(cplxMatMul(U, conjTransp(U)));
print();</langsyntaxhighlight>
 
=={{header|Stata}}==
In Mata, the ' operator is always the conjugate transpose. To get only the matrix transpose without complex conjugate, use the [ transposeonly] function.
 
<langsyntaxhighlight lang="stata">
: a=1,2i\3i,4
 
Line 3,712:
: a'*a==I(rows(a))
0
</syntaxhighlight>
</lang>
 
=={{header|Tcl}}==
Line 3,718:
{{tcllib|math::complexnumbers}}
{{tcllib|struct::matrix}}
<langsyntaxhighlight lang="tcl">package require struct::matrix
package require math::complexnumbers
 
Line 3,774:
}
return $mat
}</langsyntaxhighlight>
Using these tools to test for the properties described in the task:
<langsyntaxhighlight lang="tcl">proc isHermitian {matrix {epsilon 1e-14}} {
if {[$matrix rows] != [$matrix columns]} {
# Must be square!
Line 3,827:
$mmh destroy
return $result
}</langsyntaxhighlight>
<!-- Wot, no demonstration? -->
 
Line 3,838:
 
However, if we use the ''almostEquals'' method with the default tolerance of 1.0e-14, then we do get a ''true'' result.
<langsyntaxhighlight lang="ecmascript">import "/complex" for Complex, CMatrix
import "/fmt" for Fmt
 
Line 3,871:
var cm4 = cm3 * cm3.conjTranspose
var id = CMatrix.identity(3)
System.print("Unitary : %(cm4.almostEquals(id))")</langsyntaxhighlight>
 
{{out}}
10,333

edits