Skip to content
jcanny edited this page Jan 29, 2013 · 18 revisions

Table of Contents

Basics

BIDMat includes a complex, single precision matrix type called CMat. Internally, real/complex pairs are stored in consecutive memory words as floats which supports the scientific library functions defined for complex matrices. There is however, no complex scalar type. Similar to Matlab, a complex scalar is realized as a 1x1 matrix.

To create a complex value, you can use the "i" method like this:

scala> val b = 3 + 4.i
b: BIDMat.CMat =
  3+4i
which with some Scala magic implicitly casts the integer values as FMats, applies the ".i" operator to the second argument to produce a CMat, and then knows how to apply "+" to an FMat and a CMat. Not that you should know or care how this happens. The result is simply a CMat with a single value.

Note that we used the "." operator to invoke the "i" method rather than using a space:

scala> val b = 3 + 4 i
b: BIDMat.CMat =
  7i
since in Scala's syntax, "+" has a higher precedence than "i".
scala> val b = 3 + (4 i)
b: BIDMat.CMat =
  3+4i
also works, as does (somewhat surprisingly) "3 + 4.0.i" However "3 + 4i" does not parse.

To create a large matrix of complex numbers, you can use any of the random number generators:

scala> val c = rand(4,10) + rand(4,10).i
c: BIDMat.CMat =
   0.21497+0.77080i   0.67449+0.28513i   0.93723+0.71991i...
   0.37809+0.83195i  0.051680+0.89084i  0.038354+0.76330i...
   0.36922+0.82463i   0.78521+0.27711i   0.67254+0.71312i...
   0.87246+0.25732i   0.14137+0.19628i   0.98884+0.96585i...
one syntactic snag is that we cannot access elements of complex matrices using "a(i,j)" syntax. This operation is shared by all matrices and must return the base (element) type. Trying to will produce:
scala> a(1,2)
java.lang.RuntimeException: can't use a(i,j) indexing on CMat, use a.get(i,j) instead
...
Accordingly, we instead apply the get operator:
scala> c.get(1,2)
res1: BIDMat.CMat =
    0.038354+0.76330i
We can however perform element updates with complex or real values:
scala> c(1,2) = 3 + 4.i
res2: BIDMat.CMat =
   3+4i
scala> c
c: BIDMat.CMat =
   0.21497+0.77080i   0.67449+0.28513i   0.93723+0.71991i...
   0.37809+0.83195i  0.051680+0.89084i               3+4i...
   0.36922+0.82463i   0.78521+0.27711i   0.67254+0.71312i...
   0.87246+0.25732i   0.14137+0.19628i   0.98884+0.96585i...
scala> c(1,0) = 5
res3: Float = 5.0
scala> c
c: BIDMat.CMat =
   0.21497+0.77080i   0.67449+0.28513i   0.93723+0.71991i...
                  5  0.051680+0.89084i               3+4i...
   0.36922+0.82463i   0.78521+0.27711i   0.67254+0.71312i...
   0.87246+0.25732i   0.14137+0.19628i   0.98884+0.96585i...

Extracting Parts

To extract the real or imaginary parts of a complex matrix, use the operators ".r" and ".i". Like this:

scala> val a = rand(4,10) + rand(4,10).i
a: BIDMat.CMat =
   0.67636+0.34410i   0.15675+0.46375i   0.43748+0.57167i...
   0.31279+0.63679i   0.69485+0.59093i   0.91233+0.15906i...
   0.10547+0.46058i   0.88596+0.73404i   0.58793+0.86155i...
   0.83065+0.87015i   0.84817+0.18380i  0.080891+0.78927i...

scala> a.r
res1: BIDMat.FMat =
   0.67636   0.15675   0.43748  0.081511   0.46293  0.097704   0.71535...
   0.31279   0.69485   0.91233   0.87120   0.12652   0.71330   0.35587...
   0.10547   0.88596   0.58793   0.90858   0.45308   0.45136  0.069531...
   0.83065   0.84817  0.080891  0.022294   0.73676   0.14168   0.91742...

scala> a.i
res2: BIDMat.FMat =
   0.34410   0.46375   0.57167   0.64560   0.92401   0.32618   0.44249...
   0.63679   0.59093   0.15906   0.68576   0.35331   0.12405   0.16163...
   0.46058   0.73404   0.86155   0.19624   0.87816   0.48652   0.56278...
   0.87015   0.18380   0.78927  0.065433   0.45076   0.87441   0.56792...

The operator ".i" therefore has two different meanings: When applied to an FMat, it returns a CMat which is sqrt(-1) times the original matrix. When applied to a CMat, it extracts the imaginary part and returns it as an FMat. This is done for simplicity but it could be confusing. If so, the operator ".im" is an alias which will extract the imaginary part of a CMat.

Operations

Most of the operations defined for real matrices will work on complex matrices (algebraic operators, concatenation, slicing, find functions). But comparison operators

<,>,==,>=,<=,!=

will not since complex numbers have no linear ordering.

Matrix Functions

Most of the standard matrix functions, exp, log etc., are not yet defined for complex matrices. Complex matrices are primarily used to support linear algebra routines that generate complex values from real ones - e.g. eigenvalues of non-symmetric matrices.