public void ComplexMatrixMultiplication()
        {
            /*
             * MATLAB:
             * prod_cc = ca3x2 * cd2x4
             * prod_cm = ca3x2 * md2x4
             * prod_cs = ca3x2 * s
             * prod_cc2 = cc2x2 * cc2x2
             * prod_cm2 = cc2x2 * mc2x2
             * prod_cs2 = cc2x2 * s
             * prod_ccv = ca3x2 * cv2.'
             * prod_cv = ca3x2 * v2.'
             * prod_ccvdl = diag(cv2) * cc2x2
             * prod_ccvdr = cc2x2 * diag(cv2)
             * prod_cvdl = diag(v2) * cc2x2
             * prod_cvdr = cc2x2 * diag(v2)
             */

            // ComplexMatrix * ComplexMatrix
            ComplexMatrix prodCmCm = new ComplexMatrix(new Complex[][] {
                new Complex[] { -66 + (12 * j), -66 + (72 * j), -66 - (228 * j), -66 + (672 * j) },
                new Complex[] { -154 + (268 * j), -154 + (300 * j), -154 + (308 * j), -154 + (368 * j) },
                new Complex[] { -352 + (424 * j), -352 + (582 * j), -352 + (44 * j), -352 + (1784 * j) }
            });

            Assert.That(_ca3X2 * _cd2X4, NumericIs.AlmostEqualTo(prodCmCm), "prod cc 1");
            Assert.That(_ca3X2.Multiply(_cd2X4), NumericIs.AlmostEqualTo(prodCmCm), "prod cc 2");

            // ComplexMatrix * Matrix
            ComplexMatrix prodCmM = new ComplexMatrix(new Complex[][] {
                new Complex[] { 6 - (12 * j), 12 - (24 * j), -18 + (36 * j), 72 - (144 * j) },
                new Complex[] { 38 - (76 * j), 41.2 - (82.4 * j), 42 - (84 * j), 48 - (96 * j) },
                new Complex[] { 68 - (136 * j), 83.8 - (167.6 * j), 30 - (60 * j), 204 - (408 * j) }
            });

            Assert.That(_ca3X2 * _md2X4, NumericIs.AlmostEqualTo(prodCmM), "prod cm 1");
            Assert.That(_ca3X2.Multiply(_md2X4), NumericIs.AlmostEqualTo(prodCmM), "prod cm 2");

            // ComplexMatrix * Complex
            ComplexMatrix prodCmC = new ComplexMatrix(new Complex[][] {
                new Complex[] { 18 - (6 * j), 0 },
                new Complex[] { 6 - (2 * j), 36 - (12 * j) },
                new Complex[] { 42 - (14 * j), 54 - (18 * j) }
            });

            Assert.That(_ca3X2 * _s, NumericIs.AlmostEqualTo(prodCmC), "prod cs 1");
            Assert.That(_ca3X2.Multiply(_s), NumericIs.AlmostEqualTo(prodCmC), "prod cs 2");

            // ComplexMatrix * ComplexMatrix (Square)
            ComplexMatrix prodCmCmSquare = new ComplexMatrix(new Complex[][] {
                new Complex[] { -1232 - (924 * j), -1368 - (1026 * j) },
                new Complex[] { -1520 - (1140 * j), -1688 - (1266 * j) }
            });

            Assert.That(_cc2X2 * _cc2X2, NumericIs.AlmostEqualTo(prodCmCmSquare), "prod cc2 1");
            Assert.That(_cc2X2.Multiply(_cc2X2), NumericIs.AlmostEqualTo(prodCmCmSquare), "prod cc2 2");
            ComplexMatrix prodCmCmSquareInplace = _cc2X2.Clone();

            prodCmCmSquareInplace.MultiplyInplace(_cc2X2);
            Assert.That(prodCmCmSquareInplace, NumericIs.AlmostEqualTo(prodCmCmSquare), "prod cc2 3");

            // ComplexMatrix * Matrix (Square)
            ComplexMatrix prodCmMSquare = new ComplexMatrix(new Complex[][] {
                new Complex[] { 35 - (105 * j), 52 - (156 * j) },
                new Complex[] { 43 - (129 * j), 64 - (192 * j) }
            });

            Assert.That(_cc2X2 * _mc2X2, NumericIs.AlmostEqualTo(prodCmMSquare), "prod cm2 1");
            Assert.That(_cc2X2.Multiply(_mc2X2), NumericIs.AlmostEqualTo(prodCmMSquare), "prod cm2 2");
            ComplexMatrix prodCmMSquareInplace = _cc2X2.Clone();

            prodCmMSquareInplace.MultiplyInplace(_mc2X2);
            Assert.That(prodCmMSquareInplace, NumericIs.AlmostEqualTo(prodCmMSquare), "prod cm2 3");

            // ComplexMatrix * Complex (Square)
            ComplexMatrix prodCmCSquare = new ComplexMatrix(new Complex[][] {
                new Complex[] { 32 - (16 * j), 36 - (18 * j) },
                new Complex[] { 40 - (20 * j), 44 - (22 * j) }
            });

            Assert.That(_cc2X2 * _s, NumericIs.AlmostEqualTo(prodCmCSquare), "prod cs2 1");
            Assert.That(_cc2X2.Multiply(_s), NumericIs.AlmostEqualTo(prodCmCSquare), "prod cs2 2");
            ComplexMatrix prodCmCSquareInplace = _cc2X2.Clone();

            prodCmCSquareInplace.MultiplyInplace(_s);
            Assert.That(prodCmCSquareInplace, NumericIs.AlmostEqualTo(prodCmCSquare), "prod cs2 3");

            // ComplexMatrix * ComplexVector (Column)
            ComplexVector prodCmCvc = new ComplexVector(new Complex[] { 42 - (54 * j), 62 + (66 * j), 170 });

            Assert.That(_ca3X2 * _cv2, NumericIs.AlmostEqualTo(prodCmCvc), "prod ccv 1");
            Assert.That(_ca3X2.MultiplyRightColumn(_cv2), NumericIs.AlmostEqualTo(prodCmCvc), "prod ccv 2");

            // ComplexMatrix * Vector (Column)
            ComplexVector prodCmVc = new ComplexVector(new Complex[] { 30 - (60 * j), -14 + (28 * j), 34 - (68 * j) });

            Assert.That(_ca3X2 * _v2, NumericIs.AlmostEqualTo(prodCmVc), "prod cv 1");
            Assert.That(_ca3X2.MultiplyRightColumn(_v2), NumericIs.AlmostEqualTo(prodCmVc), "prod cv 2");

            // ComplexMatrix * ComplexVector (Diagonal, Left)
            ComplexMatrix prodCmCvdl = new ComplexMatrix(new Complex[][] {
                new Complex[] { 64 - (112 * j), 72 - (126 * j) },
                new Complex[] { 70 + (90 * j), 77 + (99 * j) }
            });

            Assert.That(_cc2X2.MultiplyLeftDiagonal(_cv2), NumericIs.AlmostEqualTo(prodCmCvdl), "prod ccv dl 1");
            ComplexMatrix prodCmCvdlInplace = _cc2X2.Clone();

            prodCmCvdlInplace.MultiplyLeftDiagonalInplace(_cv2);
            Assert.That(prodCmCvdlInplace, NumericIs.AlmostEqualTo(prodCmCvdl), "prod ccv dl 2");
            Assert.That(ComplexMatrix.Diagonal(_cv2) * _cc2X2, NumericIs.AlmostEqualTo(prodCmCvdl), "prod ccv dl 3");

            // ComplexMatrix * Vector (Diagonal, Left)
            ComplexMatrix prodCmVdl = new ComplexMatrix(new Complex[][] {
                new Complex[] { 40 - (120 * j), 45 - (135 * j) },
                new Complex[] { -20 + (60 * j), -22 + (66 * j) }
            });

            Assert.That(_cc2X2.MultiplyLeftDiagonal(_v2), NumericIs.AlmostEqualTo(prodCmVdl), "prod cv dl 1");
            ComplexMatrix prodCmVdlInplace = _cc2X2.Clone();

            prodCmVdlInplace.MultiplyLeftDiagonalInplace(_v2);
            Assert.That(prodCmVdlInplace, NumericIs.AlmostEqualTo(prodCmVdl), "prod cv dl 2");

            // ComplexMatrix * ComplexVector (Diagonal, Right)
            ComplexMatrix prodCmCvdr = new ComplexMatrix(new Complex[][] {
                new Complex[] { 64 - (112 * j), 63 + (81 * j) },
                new Complex[] { 80 - (140 * j), 77 + (99 * j) }
            });

            Assert.That(_cc2X2.MultiplyRightDiagonal(_cv2), NumericIs.AlmostEqualTo(prodCmCvdr), "prod ccv dr 1");
            ComplexMatrix prodCmCvdrInplace = _cc2X2.Clone();

            prodCmCvdrInplace.MultiplyRightDiagonalInplace(_cv2);
            Assert.That(prodCmCvdrInplace, NumericIs.AlmostEqualTo(prodCmCvdr), "prod ccv dr 2");
            Assert.That(_cc2X2 * ComplexMatrix.Diagonal(_cv2), NumericIs.AlmostEqualTo(prodCmCvdr), "prod ccv dr 3");

            // ComplexMatrix * Vector (Diagonal, Right)
            ComplexMatrix prodCmVdr = new ComplexMatrix(new Complex[][] {
                new Complex[] { 40 - (120 * j), -18 + (54 * j) },
                new Complex[] { 50 - (150 * j), -22 + (66 * j) }
            });

            Assert.That(_cc2X2.MultiplyRightDiagonal(_v2), NumericIs.AlmostEqualTo(prodCmVdr), "prod cv dr 1");
            ComplexMatrix prodCmVdrInplace = _cc2X2.Clone();

            prodCmVdrInplace.MultiplyRightDiagonalInplace(_v2);
            Assert.That(prodCmVdrInplace, NumericIs.AlmostEqualTo(prodCmVdr), "prod cv dr 2");
        }
        public void TestComplexMatrix_Multiplicative()
        {
            /*
             * MATLAB:
             * prod_cc = ca3x2 * cd2x4
             * prod_cm = ca3x2 * md2x4
             * prod_cs = ca3x2 * s
             * prod_cc2 = cc2x2 * cc2x2
             * prod_cm2 = cc2x2 * mc2x2
             * prod_cs2 = cc2x2 * s
             * prod_ccv = ca3x2 * cv2.'
             * prod_cv = ca3x2 * v2.'
             * prod_ccvdl = diag(cv2) * cc2x2
             * prod_ccvdr = cc2x2 * diag(cv2)
             * prod_cvdl = diag(v2) * cc2x2
             * prod_cvdr = cc2x2 * diag(v2)
             */

            // ComplexMatrix * ComplexMatrix
            ComplexMatrix prod_cc = new ComplexMatrix(new Complex[][] {
                new Complex[] { -66 + 12 * j, -66 + 72 * j, -66 - 228 * j, -66 + 672 * j },
                new Complex[] { -154 + 268 * j, -154 + 300 * j, -154 + 308 * j, -154 + 368 * j },
                new Complex[] { -352 + 424 * j, -352 + 582 * j, -352 + 44 * j, -352 + 1784 * j }
            });

            NumericAssert.AreAlmostEqual(prod_cc, ca3x2 * cd2x4, "prod cc 1");
            NumericAssert.AreAlmostEqual(prod_cc, ca3x2.Multiply(cd2x4), "prod cc 2");

            // ComplexMatrix * Matrix
            ComplexMatrix prod_cm = new ComplexMatrix(new Complex[][] {
                new Complex[] { 6 - 12 * j, 12 - 24 * j, -18 + 36 * j, 72 - 144 * j },
                new Complex[] { 38 - 76 * j, 41.2 - 82.4 * j, 42 - 84 * j, 48 - 96 * j },
                new Complex[] { 68 - 136 * j, 83.8 - 167.6 * j, 30 - 60 * j, 204 - 408 * j }
            });

            NumericAssert.AreAlmostEqual(prod_cm, ca3x2 * md2x4, "prod cm 1");
            NumericAssert.AreAlmostEqual(prod_cm, ca3x2.Multiply(md2x4), "prod cm 2");

            // ComplexMatrix * Complex
            ComplexMatrix prod_cs = new ComplexMatrix(new Complex[][] {
                new Complex[] { 18 - 6 * j, 0 },
                new Complex[] { 6 - 2 * j, 36 - 12 * j },
                new Complex[] { 42 - 14 * j, 54 - 18 * j }
            });

            NumericAssert.AreAlmostEqual(prod_cs, ca3x2 * s, "prod cs 1");
            NumericAssert.AreAlmostEqual(prod_cs, ca3x2.Multiply(s), "prod cs 2");

            // ComplexMatrix * ComplexMatrix (Square)
            ComplexMatrix prod_cc2 = new ComplexMatrix(new Complex[][] {
                new Complex[] { -1232 - 924 * j, -1368 - 1026 * j },
                new Complex[] { -1520 - 1140 * j, -1688 - 1266 * j }
            });

            NumericAssert.AreAlmostEqual(prod_cc2, cc2x2 * cc2x2, "prod cc2 1");
            NumericAssert.AreAlmostEqual(prod_cc2, cc2x2.Multiply(cc2x2), "prod cc2 2");
            ComplexMatrix prod_cc2_inplace = cc2x2.Clone();

            prod_cc2_inplace.MultiplyInplace(cc2x2);
            NumericAssert.AreAlmostEqual(prod_cc2, prod_cc2_inplace, "prod cc2 3");

            // ComplexMatrix * Matrix (Square)
            ComplexMatrix prod_cm2 = new ComplexMatrix(new Complex[][] {
                new Complex[] { 35 - 105 * j, 52 - 156 * j },
                new Complex[] { 43 - 129 * j, 64 - 192 * j }
            });

            NumericAssert.AreAlmostEqual(prod_cm2, cc2x2 * mc2x2, "prod cm2 1");
            NumericAssert.AreAlmostEqual(prod_cm2, cc2x2.Multiply(mc2x2), "prod cm2 2");
            ComplexMatrix prod_cm2_inplace = cc2x2.Clone();

            prod_cm2_inplace.MultiplyInplace(mc2x2);
            NumericAssert.AreAlmostEqual(prod_cm2, prod_cm2_inplace, "prod cm2 3");

            // ComplexMatrix * Complex (Square)
            ComplexMatrix prod_cs2 = new ComplexMatrix(new Complex[][] {
                new Complex[] { 32 - 16 * j, 36 - 18 * j },
                new Complex[] { 40 - 20 * j, 44 - 22 * j }
            });

            NumericAssert.AreAlmostEqual(prod_cs2, cc2x2 * s, "prod cs2 1");
            NumericAssert.AreAlmostEqual(prod_cs2, cc2x2.Multiply(s), "prod cs2 2");
            ComplexMatrix prod_cs2_inplace = cc2x2.Clone();

            prod_cs2_inplace.MultiplyInplace(s);
            NumericAssert.AreAlmostEqual(prod_cs2, prod_cs2_inplace, "prod cs2 3");

            // ComplexMatrix * ComplexVector (Column)
            ComplexVector prod_ccv = new ComplexVector(new Complex[] { 42 - 54 * j, 62 + 66 * j, 170 });

            NumericAssert.AreAlmostEqual(prod_ccv, ca3x2 * cv2, "prod ccv 1");
            NumericAssert.AreAlmostEqual(prod_ccv, ca3x2.MultiplyRightColumn(cv2), "prod ccv 2");

            // ComplexMatrix * Vector (Column)
            ComplexVector prod_cv = new ComplexVector(new Complex[] { 30 - 60 * j, -14 + 28 * j, 34 - 68 * j });

            NumericAssert.AreAlmostEqual(prod_cv, ca3x2 * v2, "prod cv 1");
            NumericAssert.AreAlmostEqual(prod_cv, ca3x2.MultiplyRightColumn(v2), "prod cv 2");

            // ComplexMatrix * ComplexVector (Diagonal, Left)
            ComplexMatrix prod_ccvdl = new ComplexMatrix(new Complex[][] {
                new Complex[] { 64 - 112 * j, 72 - 126 * j },
                new Complex[] { 70 + 90 * j, 77 + 99 * j }
            });

            NumericAssert.AreAlmostEqual(prod_ccvdl, cc2x2.MultiplyLeftDiagonal(cv2), "prod ccv dl 1");
            ComplexMatrix prod_ccvdl_inplace = cc2x2.Clone();

            prod_ccvdl_inplace.MultiplyLeftDiagonalInplace(cv2);
            NumericAssert.AreAlmostEqual(prod_ccvdl, prod_ccvdl_inplace, "prod ccv dl 2");
            NumericAssert.AreAlmostEqual(prod_ccvdl, ComplexMatrix.Diagonal(cv2) * cc2x2, "prod ccv dl 3");

            // ComplexMatrix * Vector (Diagonal, Left)
            ComplexMatrix prod_cvdl = new ComplexMatrix(new Complex[][] {
                new Complex[] { 40 - 120 * j, 45 - 135 * j },
                new Complex[] { -20 + 60 * j, -22 + 66 * j }
            });

            NumericAssert.AreAlmostEqual(prod_cvdl, cc2x2.MultiplyLeftDiagonal(v2), "prod cv dl 1");
            ComplexMatrix prod_cvdl_inplace = cc2x2.Clone();

            prod_cvdl_inplace.MultiplyLeftDiagonalInplace(v2);
            NumericAssert.AreAlmostEqual(prod_cvdl, prod_cvdl_inplace, "prod cv dl 2");

            // ComplexMatrix * ComplexVector (Diagonal, Right)
            ComplexMatrix prod_ccvdr = new ComplexMatrix(new Complex[][] {
                new Complex[] { 64 - 112 * j, 63 + 81 * j },
                new Complex[] { 80 - 140 * j, 77 + 99 * j }
            });

            NumericAssert.AreAlmostEqual(prod_ccvdr, cc2x2.MultiplyRightDiagonal(cv2), "prod ccv dr 1");
            ComplexMatrix prod_ccvdr_inplace = cc2x2.Clone();

            prod_ccvdr_inplace.MultiplyRightDiagonalInplace(cv2);
            NumericAssert.AreAlmostEqual(prod_ccvdr, prod_ccvdr_inplace, "prod ccv dr 2");
            NumericAssert.AreAlmostEqual(prod_ccvdr, cc2x2 * ComplexMatrix.Diagonal(cv2), "prod ccv dr 3");

            // ComplexMatrix * Vector (Diagonal, Right)
            ComplexMatrix prod_cvdr = new ComplexMatrix(new Complex[][] {
                new Complex[] { 40 - 120 * j, -18 + 54 * j },
                new Complex[] { 50 - 150 * j, -22 + 66 * j }
            });

            NumericAssert.AreAlmostEqual(prod_cvdr, cc2x2.MultiplyRightDiagonal(v2), "prod cv dr 1");
            ComplexMatrix prod_cvdr_inplace = cc2x2.Clone();

            prod_cvdr_inplace.MultiplyRightDiagonalInplace(v2);
            NumericAssert.AreAlmostEqual(prod_cvdr, prod_cvdr_inplace, "prod cv dr 2");
        }