Example #1
0
        /// <summary>
        /// Raise this <c>Complex</c> to the given value.
        /// </summary>
        /// <param name="complex">The <see cref="Complex"/> number to perform this operation on.</param>
        /// <param name="exponent">
        /// The exponent.
        /// </param>
        /// <returns>
        /// The complex number raised to the given exponent.
        /// </returns>
        public static Complex Power(this Complex complex, Complex exponent)
        {
            if (complex.IsZero())
            {
                if (exponent.IsZero())
                {
                    return(Complex.One);
                }

                if (exponent.Real > 0d)
                {
                    return(Complex.Zero);
                }

                if (exponent.Real < 0d)
                {
                    return(exponent.Imaginary.IsZero()
                        ? new Complex(double.PositiveInfinity, 0d)
                        : new Complex(double.PositiveInfinity, double.PositiveInfinity));
                }

                return(new Complex(double.NaN, double.NaN));
            }

            return(Complex.Pow(complex, exponent));
        }
    void Compensate()
    {
        if (targetPort.voltage.IsZero())
        {
            compensateLevel = 0;
            return;
        }

        Complex loadCurrent = targetPort.current - inputPower.current;
        Complex project     = loadCurrent.Project(targetPort.voltage);
        //Target compensate current
        Complex target = project - loadCurrent;

        if (target.IsZero())//no need to compensate
        {
            compensateLevel = 0;
        }
        else
        {
            float t  = target.magnitude;
            float v  = targetPort.voltage.magnitude;
            float tc = t / v;

            compensateLevel = Mathf.FloorToInt(tc / compensateValue);

            if (compensateLevel > 7)
            {
                compensateLevel = 7;
            }
        }
    }
        /// <summary>
        /// Adds a scaled vector to another: <c>result = y + alpha*x</c>.
        /// </summary>
        /// <param name="y">The vector to update.</param>
        /// <param name="alpha">The value to scale <paramref name="x"/> by.</param>
        /// <param name="x">The vector to add to <paramref name="y"/>.</param>
        /// <param name="result">The result of the addition.</param>
        /// <remarks>This is similar to the AXPY BLAS routine.</remarks>
        public virtual void AddVectorToScaledVector(Complex[] y, Complex alpha, Complex[] x, Complex[] result)
        {
            if (y == null)
            {
                throw new ArgumentNullException("y");
            }

            if (x == null)
            {
                throw new ArgumentNullException("x");
            }

            if (y.Length != x.Length)
            {
                throw new ArgumentException(Resources.ArgumentVectorsSameLength);
            }

            if (y.Length != x.Length)
            {
                throw new ArgumentException(Resources.ArgumentVectorsSameLength);
            }

            if (alpha.IsZero())
            {
                CommonParallel.For(0, y.Length, index => result[index] = y[index]);
            }
            else if (alpha.IsOne())
            {
                CommonParallel.For(0, y.Length, index => result[index] = y[index] + x[index]);
            }
            else
            {
                CommonParallel.For(0, y.Length, index => result[index] = y[index] + (alpha * x[index]));
            }
        }
Example #4
0
        public void IsZeroTest()
        {
            Assert.IsFalse(a.IsZero());
            Complex zero = new Complex(field, BigInt.ZERO);

            Assert.IsTrue(zero.IsZero());
        }
Example #5
0
 /// <summary>Sets the scaling factor \alpha in the Fourier Transformation.
 /// </summary>
 /// <param name="alpha">The scaling factor \alpha.</param>
 /// <exception cref="InvalidOperationException">Thrown if <see cref="FFT.IOneDimensional.FourierExponentialFactorRestriction"/> indicates that the parameter \alpha can not be changed in this way or <paramref name="alpha"/> contains an invalid value.</exception>
 public void SetParameterAlpha(Complex alpha)
 {
     if (alpha.IsZero(MachineConsts.Epsilon) == true)
     {
         throw new InvalidOperationException();
     }
     m_Alpha = alpha;
 }
Example #6
0
        public static Complex Divide(Complex x, Complex y)
        {
            if (y.IsZero())
            {
                throw new DivideByZeroException("complex division by zero");
            }

            return(x / y);
        }
        /// <summary>
        /// Adds a scaled vector to another: <c>result = y + alpha*x</c>.
        /// </summary>
        /// <param name="y">The vector to update.</param>
        /// <param name="alpha">The value to scale <paramref name="x"/> by.</param>
        /// <param name="x">The vector to add to <paramref name="y"/>.</param>
        /// <param name="result">The result of the addition.</param>
        /// <remarks>This is similar to the AXPY BLAS routine.</remarks>
        public virtual void AddVectorToScaledVector(Complex[] y, Complex alpha, Complex[] x, Complex[] result)
        {
            if (y == null)
            {
                throw new ArgumentNullException("y");
            }

            if (x == null)
            {
                throw new ArgumentNullException("x");
            }

            if (y.Length != x.Length)
            {
                throw new ArgumentException(Resources.ArgumentVectorsSameLength);
            }

            if (y.Length != x.Length)
            {
                throw new ArgumentException(Resources.ArgumentVectorsSameLength);
            }

            if (alpha.IsZero())
            {
                y.Copy(result);
            }
            else if (alpha.IsOne())
            {
                if (Control.ParallelizeOperation(x.Length))
                {
                    CommonParallel.For(0, y.Length, index => result[index] = y[index] + x[index]);
                }
                else
                {
                    for (var index = 0; index < x.Length; index++)
                    {
                        result[index] = y[index] + x[index];
                    }
                }
            }
            else
            {
                if (Control.ParallelizeOperation(x.Length))
                {
                    CommonParallel.For(0, y.Length, index => result[index] = y[index] + (alpha * x[index]));
                }
                else
                {
                    for (var index = 0; index < x.Length; index++)
                    {
                        result[index] = y[index] + (alpha * x[index]);
                    }
                }
            }
        }
Example #8
0
        public static Complex atanh([NotNone] object x)
        {
            Complex num = GetComplexNum(x);

            if (num.IsZero())
            {
                return(num);
            }

            return((log(1 + num) - log(1 - num)) * 0.5);
        }
Example #9
0
        public static Complex atan([NotNone] object x)
        {
            Complex num = GetComplexNum(x);

            if (num.IsZero())
            {
                return(num);
            }
            Complex i = Complex.ImaginaryOne;

            return(i * 0.5 * (log(i + num) - log(i - num)));
        }
Example #10
0
        //asin(x) = ln( x + (x*x +1)^1/2)
        public static Complex asinh(object x)
        {
            Complex num = GetComplexNum(x);

            if (num.IsZero())
            {
                // preserve -0.0 imag component
                return(MathUtils.MakeImaginary(num.Imaginary()));
            }

            Complex recip = 1 / num;

            return(log(num) + log(1 + sqrt(recip * recip + 1)));
        }
Example #11
0
        //ln(re^iO) = ln(r) + iO
        public static Complex log(object x)
        {
            Complex num = GetComplexNum(x);

            if (num.IsZero())
            {
                throw PythonOps.ValueError("math domain error");
            }

            double r, theta;

            r     = num.Abs();
            theta = GetAngle(num);

            return(new Complex(Math.Log(r), theta));
        }
Example #12
0
        public void zrotg_TestCaseData(Complex a, Complex b)
        {
            Complex r = a;
            Complex z = b;
            double  c;
            Complex s;

            m_Level1BLAS.zrotg(ref r, ref z, out c, out s);

            Complex actualR = c * a + s * b;

            Assert.That(Complex.Abs(actualR - r) < 1E-9, String.Format("Check for parameter 'r', actual = {0}, expected = {1}", actualR, r));

            Complex actualNull = -Complex.Conjugate(s) * a + c * b;

            Assert.That(actualNull.IsZero(1E-9), String.Format("Check for 0.0, but was {0}", actualNull));
        }
Example #13
0
        public static Complex op_Power(Complex x, Complex y)
        {
            if (x.IsZero())
            {
                if (y.Real < 0.0 || y.Imaginary() != 0.0)
                {
                    throw PythonOps.ZeroDivisionError("0.0 to a negative or complex power");
                }
                return(y.IsZero() ? Complex.One : Complex.Zero);
            }

            // Special case for higher precision with real integer powers
            // TODO: A similar check may get added to CLR 4 upon resolution of Dev10 bug 863171,
            // in which case this code should go away.
            if (y.Imaginary == 0.0)
            {
                int power = (int)y.Real;
                if (power >= 0 && y.Real == power)
                {
                    Complex res = Complex.One;
                    if (power == 0)
                    {
                        return(res);
                    }
                    Complex factor = x;
                    while (power != 0)
                    {
                        if ((power & 1) != 0)
                        {
                            res = res * factor;
                        }
                        factor  = factor * factor;
                        power >>= 1;
                    }
                    return(res);
                }
            }

            return(x.Pow(y));
        }
Example #14
0
        public static Complex tanh([NotNone] object x)
        {
            Complex num = GetComplexNum(x);

            if (num.IsZero())
            {
                return(num);
            }

            // limit as num.Real -> Infinity
            if (double.IsPositiveInfinity(num.Real))
            {
                return(Complex.One);
            }

            // limit as num.Real -> -Infinity
            if (double.IsNegativeInfinity(num.Real))
            {
                return(new Complex(-1.0, 0.0));
            }

            return(sinh(num) / cosh(num));
        }
        /// <summary>
        /// Adds a scaled vector to another: <c>y += alpha*x</c>.
        /// </summary>
        /// <param name="y">The vector to update.</param>
        /// <param name="alpha">The value to scale <paramref name="x"/> by.</param>
        /// <param name="x">The vector to add to <paramref name="y"/>.</param>
        /// <remarks>This equivalent to the AXPY BLAS routine.</remarks>
        public void AddVectorToScaledVector(Complex[] y, Complex alpha, Complex[] x)
        {
            if (y == null)
            {
                throw new ArgumentNullException("y");
            }

            if (x == null)
            {
                throw new ArgumentNullException("x");
            }

            if (y.Length != x.Length)
            {
                throw new ArgumentException(Resources.ArgumentVectorsSameLength);
            }

            if (alpha.IsZero())
            {
                return;
            }

            SafeNativeMethods.z_axpy(y.Length, ref alpha, x, y);
        }
        /// <summary>
        /// Raise this <c>Complex</c> to the given value.
        /// </summary>
        /// <param name="complex">The <see cref="Complex"/> number to perfom this operation on.</param>
        /// <param name="exponent">
        /// The exponent.
        /// </param>
        /// <returns>
        /// The complex number raised to the given exponent.
        /// </returns>
        public static Complex Power(this Complex complex, Complex exponent)
        {
            if (complex.IsZero())
            {
                if (exponent.IsZero())
                {
                    return Complex.One;
                }

                if (exponent.Real > 0d)
                {
                    return Complex.Zero;
                }

                if (exponent.Real < 0d)
                {
                    return exponent.Imaginary == 0d
                        ? new Complex(double.PositiveInfinity, 0d)
                        : new Complex(double.PositiveInfinity, double.PositiveInfinity);
                }

                return new Complex(double.NaN, double.NaN);
            }

            return Complex.Pow(complex, exponent);
        }
Example #17
0
        public void CanDetermineIfZeroValueComplexNumber()
        {
            var complex = new Complex(0, 0);

            Assert.IsTrue(complex.IsZero(), "Zero complex number.");
        }
Example #18
0
 public void CanDetermineIfZeroValueComplexNumber()
 {
     var complex = new Complex(0, 0);
     Assert.IsTrue(complex.IsZero(), "Zero complex number.");
 }
        public SparseMatrix(int rows, int columns, Complex value)
            : this(rows, columns)
        {
            if (value.IsZero())
            {
                return;
            }

            var rowPointers = _storage.RowPointers;
            var valueCount = _storage.ValueCount = rows * columns;
            var columnIndices = _storage.ColumnIndices = new int[valueCount];
            var values = _storage.Values = new Complex[valueCount];

            for (int i = 0, j = 0; i < values.Length; i++, j++)
            {
                // Reset column position to "0"
                if (j == columns)
                {
                    j = 0;
                }

                values[i] = value;
                columnIndices[i] = j;
            }

            // Set proper row pointers
            for (var i = 0; i < rowPointers.Length; i++)
            {
                rowPointers[i] = ((i + 1) * columns) - columns;
            }
        }
Example #20
0
 public static bool __nonzero__(Complex x)
 {
     return(!x.IsZero());
 }
        /// <summary>
        /// Multiplies two matrices and updates another with the result. <c>c = alpha*op(a)*op(b) + beta*c</c>
        /// </summary>
        /// <param name="transposeA">How to transpose the <paramref name="a"/> matrix.</param>
        /// <param name="transposeB">How to transpose the <paramref name="b"/> matrix.</param>
        /// <param name="alpha">The value to scale <paramref name="a"/> matrix.</param>
        /// <param name="a">The a matrix.</param>
        /// <param name="rowsA">The number of rows in the <paramref name="a"/> matrix.</param>
        /// <param name="columnsA">The number of columns in the <paramref name="a"/> matrix.</param>
        /// <param name="b">The b matrix</param>
        /// <param name="rowsB">The number of rows in the <paramref name="b"/> matrix.</param>
        /// <param name="columnsB">The number of columns in the <paramref name="b"/> matrix.</param>
        /// <param name="beta">The value to scale the <paramref name="c"/> matrix.</param>
        /// <param name="c">The c matrix.</param>
        public virtual void MatrixMultiplyWithUpdate(Transpose transposeA, Transpose transposeB, Complex alpha, Complex[] a, int rowsA, int columnsA, Complex[] b, int rowsB, int columnsB, Complex beta, Complex[] c)
        {
            // Choose nonsensical values for the number of rows in c; fill them in depending
            // on the operations on a and b.
            int rowsC;

            // First check some basic requirement on the parameters of the matrix multiplication.
            if (a == null)
            {
                throw new ArgumentNullException("a");
            }

            if (b == null)
            {
                throw new ArgumentNullException("b");
            }

            if ((int)transposeA > 111 && (int)transposeB > 111)
            {
                if (rowsA != columnsB)
                {
                    throw new ArgumentOutOfRangeException();
                }

                if (columnsA * rowsB != c.Length)
                {
                    throw new ArgumentOutOfRangeException();
                }

                rowsC = columnsA;
            }
            else if ((int)transposeA > 111)
            {
                if (rowsA != rowsB)
                {
                    throw new ArgumentOutOfRangeException();
                }

                if (columnsA * columnsB != c.Length)
                {
                    throw new ArgumentOutOfRangeException();
                }

                rowsC = columnsA;
            }
            else if ((int)transposeB > 111)
            {
                if (columnsA != columnsB)
                {
                    throw new ArgumentOutOfRangeException();
                }

                if (rowsA * rowsB != c.Length)
                {
                    throw new ArgumentOutOfRangeException();
                }

                rowsC = rowsA;
            }
            else
            {
                if (columnsA != rowsB)
                {
                    throw new ArgumentOutOfRangeException();
                }

                if (rowsA * columnsB != c.Length)
                {
                    throw new ArgumentOutOfRangeException();
                }

                rowsC = rowsA;
            }

            if (alpha.IsZero() && beta.IsZero())
            {
                Array.Clear(c, 0, c.Length);
                return;
            }

            // Check whether we will be overwriting any of our inputs and make copies if necessary.
            // TODO - we can don't have to allocate a completely new matrix when x or y point to the same memory
            // as result, we can do it on a row wise basis. We should investigate this.
            Complex[] adata;
            if (ReferenceEquals(a, c))
            {
                adata = (Complex[])a.Clone();
            }
            else
            {
                adata = a;
            }

            Complex[] bdata;
            if (ReferenceEquals(b, c))
            {
                bdata = (Complex[])b.Clone();
            }
            else
            {
                bdata = b;
            }

            if (alpha.IsOne())
            {
                if (beta.IsZero())
                {
                    if ((int)transposeA > 111 && (int)transposeB > 111)
                    {
                        CommonParallel.For(
                            0,
                            columnsA,
                            j =>
                            {
                                var jIndex = j * rowsC;
                                for (var i = 0; i != rowsB; i++)
                                {
                                    var iIndex = i * rowsA;
                                    Complex s = 0;
                                    for (var l = 0; l != columnsB; l++)
                                    {
                                        s += adata[iIndex + l] * bdata[(l * rowsB) + j];
                                    }

                                    c[jIndex + i] = s;
                                }
                            });
                    }
                    else if ((int)transposeA > 111)
                    {
                        CommonParallel.For(
                            0,
                            columnsB,
                            j =>
                            {
                                var jcIndex = j * rowsC;
                                var jbIndex = j * rowsB;
                                for (var i = 0; i != columnsA; i++)
                                {
                                    var iIndex = i * rowsA;
                                    Complex s = 0;
                                    for (var l = 0; l != rowsA; l++)
                                    {
                                        s += adata[iIndex + l] * bdata[jbIndex + l];
                                    }

                                    c[jcIndex + i] = s;
                                }
                            });
                    }
                    else if ((int)transposeB > 111)
                    {
                        CommonParallel.For(
                            0,
                            rowsB,
                            j =>
                            {
                                var jIndex = j * rowsC;
                                for (var i = 0; i != rowsA; i++)
                                {
                                    Complex s = 0;
                                    for (var l = 0; l != columnsA; l++)
                                    {
                                        s += adata[(l * rowsA) + i] * bdata[(l * rowsB) + j];
                                    }

                                    c[jIndex + i] = s;
                                }
                            });
                    }
                    else
                    {
                        CommonParallel.For(
                            0,
                            columnsB,
                            j =>
                            {
                                var jcIndex = j * rowsC;
                                var jbIndex = j * rowsB;
                                for (var i = 0; i != rowsA; i++)
                                {
                                    Complex s = 0;
                                    for (var l = 0; l != columnsA; l++)
                                    {
                                        s += adata[(l * rowsA) + i] * bdata[jbIndex + l];
                                    }

                                    c[jcIndex + i] = s;
                                }
                            });
                    }
                }
                else
                {
                    if ((int)transposeA > 111 && (int)transposeB > 111)
                    {
                        CommonParallel.For(
                            0,
                            columnsA,
                            j =>
                            {
                                var jIndex = j * rowsC;
                                for (var i = 0; i != rowsB; i++)
                                {
                                    var iIndex = i * rowsA;
                                    Complex s = 0;
                                    for (var l = 0; l != columnsB; l++)
                                    {
                                        s += adata[iIndex + l] * bdata[(l * rowsB) + j];
                                    }

                                    c[jIndex + i] = (c[jIndex + i] * beta) + s;
                                }
                            });
                    }
                    else if ((int)transposeA > 111)
                    {
                        CommonParallel.For(
                            0,
                            columnsB,
                            j =>
                            {
                                var jcIndex = j * rowsC;
                                var jbIndex = j * rowsB;
                                for (var i = 0; i != columnsA; i++)
                                {
                                    var iIndex = i * rowsA;
                                    Complex s = 0;
                                    for (var l = 0; l != rowsA; l++)
                                    {
                                        s += adata[iIndex + l] * bdata[jbIndex + l];
                                    }

                                    c[jcIndex + i] = s + (c[jcIndex + i] * beta);
                                }
                            });
                    }
                    else if ((int)transposeB > 111)
                    {
                        CommonParallel.For(
                            0,
                            rowsB,
                            j =>
                            {
                                var jIndex = j * rowsC;
                                for (var i = 0; i != rowsA; i++)
                                {
                                    Complex s = 0;
                                    for (var l = 0; l != columnsA; l++)
                                    {
                                        s += adata[(l * rowsA) + i] * bdata[(l * rowsB) + j];
                                    }

                                    c[jIndex + i] = s + (c[jIndex + i] * beta);
                                }
                            });
                    }
                    else
                    {
                        CommonParallel.For(
                            0,
                            columnsB,
                            j =>
                            {
                                var jcIndex = j * rowsC;
                                var jbIndex = j * rowsB;
                                for (var i = 0; i != rowsA; i++)
                                {
                                    Complex s = 0;
                                    for (var l = 0; l != columnsA; l++)
                                    {
                                        s += adata[(l * rowsA) + i] * bdata[jbIndex + l];
                                    }

                                    c[jcIndex + i] = s + (c[jcIndex + i] * beta);
                                }
                            });
                    }
                }
            }
            else
            {
                if ((int)transposeA > 111 && (int)transposeB > 111)
                {
                    CommonParallel.For(
                        0,
                        columnsA,
                        j =>
                        {
                            var jIndex = j * rowsC;
                            for (var i = 0; i != rowsB; i++)
                            {
                                var iIndex = i * rowsA;
                                Complex s = 0;
                                for (var l = 0; l != columnsB; l++)
                                {
                                    s += adata[iIndex + l] * bdata[(l * rowsB) + j];
                                }

                                c[jIndex + i] = (c[jIndex + i] * beta) + (alpha * s);
                            }
                        });
                }
                else if ((int)transposeA > 111)
                {
                    CommonParallel.For(
                        0,
                        columnsB,
                        j =>
                        {
                            var jcIndex = j * rowsC;
                            var jbIndex = j * rowsB;
                            for (var i = 0; i != columnsA; i++)
                            {
                                var iIndex = i * rowsA;
                                Complex s = 0;
                                for (var l = 0; l != rowsA; l++)
                                {
                                    s += adata[iIndex + l] * bdata[jbIndex + l];
                                }

                                c[jcIndex + i] = (alpha * s) + (c[jcIndex + i] * beta);
                            }
                        });
                }
                else if ((int)transposeB > 111)
                {
                    CommonParallel.For(
                        0,
                        rowsB,
                        j =>
                        {
                            var jIndex = j * rowsC;
                            for (var i = 0; i != rowsA; i++)
                            {
                                Complex s = 0;
                                for (var l = 0; l != columnsA; l++)
                                {
                                    s += adata[(l * rowsA) + i] * bdata[(l * rowsB) + j];
                                }

                                c[jIndex + i] = (alpha * s) + (c[jIndex + i] * beta);
                            }
                        });
                }
                else
                {
                    CommonParallel.For(
                        0,
                        columnsB,
                        j =>
                        {
                            var jcIndex = j * rowsC;
                            var jbIndex = j * rowsB;
                            for (var i = 0; i != rowsA; i++)
                            {
                                Complex s = 0;
                                for (var l = 0; l != columnsA; l++)
                                {
                                    s += adata[(l * rowsA) + i] * bdata[jbIndex + l];
                                }

                                c[jcIndex + i] = (alpha * s) + (c[jcIndex + i] * beta);
                            }
                        });
                }
            }
        }
        /// <summary>
        /// Raise this <c>Complex</c> to the given value.
        /// </summary>
        /// <param name="complex">The <see cref="Complex"/> number to perfom this operation on.</param>
        /// <param name="exponent">
        /// The exponent.
        /// </param>
        /// <returns>
        /// The complex number raised to the given exponent.
        /// </returns>
        public static Complex Power(this Complex complex, Complex exponent)
        {
            if (complex.IsZero())
            {
                if (exponent.IsZero())
                {
                    return Complex.One;
                }

                if (exponent.Real > 0.0)
                {
                    return Complex.Zero;
                }

                if (exponent.Real < 0)
                {
                    if (exponent.Imaginary == 0.0)
                    {
                        return new Complex(double.PositiveInfinity, 0.0);
                    }

                    return new Complex(double.PositiveInfinity, double.PositiveInfinity);
                }

                return double.NaN;
            }

            return (exponent * complex.NaturalLogarithm()).Exponential();
        }
        /// <summary>
        /// Scales an array. Can be used to scale a vector and a matrix.
        /// </summary>
        /// <param name="alpha">The scalar.</param>
        /// <param name="x">The values to scale.</param>
        /// <param name="result">This result of the scaling.</param>
        /// <remarks>This is similar to the SCAL BLAS routine.</remarks>
        public virtual void ScaleArray(Complex alpha, Complex[] x, Complex[] result)
        {
            if (x == null)
            {
                throw new ArgumentNullException("x");
            }

            if (alpha.IsZero())
            {
                CommonParallel.For(0, x.Length, index => result[index] = Complex.Zero);
            }
            else if (alpha.IsOne())
            {
                CommonParallel.For(0, x.Length, index => result[index] = x[index]);
            }
            else
            {
                CommonParallel.For(0, x.Length, index => { result[index] = alpha * x[index]; });
            }
        }
        /// <summary>
        /// Multiplies two matrices and updates another with the result. <c>c = alpha*op(a)*op(b) + beta*c</c>
        /// </summary>
        /// <param name="transposeA">How to transpose the <paramref name="a"/> matrix.</param>
        /// <param name="transposeB">How to transpose the <paramref name="b"/> matrix.</param>
        /// <param name="alpha">The value to scale <paramref name="a"/> matrix.</param>
        /// <param name="a">The a matrix.</param>
        /// <param name="rowsA">The number of rows in the <paramref name="a"/> matrix.</param>
        /// <param name="columnsA">The number of columns in the <paramref name="a"/> matrix.</param>
        /// <param name="b">The b matrix</param>
        /// <param name="rowsB">The number of rows in the <paramref name="b"/> matrix.</param>
        /// <param name="columnsB">The number of columns in the <paramref name="b"/> matrix.</param>
        /// <param name="beta">The value to scale the <paramref name="c"/> matrix.</param>
        /// <param name="c">The c matrix.</param>
        public virtual void MatrixMultiplyWithUpdate(Transpose transposeA, Transpose transposeB, Complex alpha, Complex[] a, int rowsA, int columnsA, Complex[] b, int rowsB, int columnsB, Complex beta, Complex[] c)
        {
            int m; // The number of rows of matrix op(A) and of the matrix C.
            int n; // The number of columns of matrix op(B) and of the matrix C.
            int k; // The number of columns of matrix op(A) and the rows of the matrix op(B). 

            // First check some basic requirement on the parameters of the matrix multiplication.
            if (a == null)
            {
                throw new ArgumentNullException("a");
            }

            if (b == null)
            {
                throw new ArgumentNullException("b");
            }

            if ((int)transposeA > 111 && (int)transposeB > 111)
            {
                if (rowsA != columnsB)
                {
                    throw new ArgumentOutOfRangeException();
                }

                if (columnsA * rowsB != c.Length)
                {
                    throw new ArgumentOutOfRangeException();
                }

                m = columnsA;
                n = rowsB;
                k = rowsA;
            }
            else if ((int)transposeA > 111)
            {
                if (rowsA != rowsB)
                {
                    throw new ArgumentOutOfRangeException();
                }

                if (columnsA * columnsB != c.Length)
                {
                    throw new ArgumentOutOfRangeException();
                }

                m = columnsA;
                n = columnsB;
                k = rowsA;
            }
            else if ((int)transposeB > 111)
            {
                if (columnsA != columnsB)
                {
                    throw new ArgumentOutOfRangeException();
                }

                if (rowsA * rowsB != c.Length)
                {
                    throw new ArgumentOutOfRangeException();
                }

                m = rowsA;
                n = rowsB;
                k = columnsA;
            }
            else
            {
                if (columnsA != rowsB)
                {
                    throw new ArgumentOutOfRangeException();
                }

                if (rowsA * columnsB != c.Length)
                {
                    throw new ArgumentOutOfRangeException();
                }

                m = rowsA;
                n = columnsB;
                k = columnsA;
            }

            if (alpha.IsZero() && beta.IsZero())
            {
                Array.Clear(c, 0, c.Length);
                return;
            }

            // Check whether we will be overwriting any of our inputs and make copies if necessary.
            // TODO - we can don't have to allocate a completely new matrix when x or y point to the same memory
            // as result, we can do it on a row wise basis. We should investigate this.
            Complex[] adata;
            if (ReferenceEquals(a, c))
            {
                adata = (Complex[])a.Clone();
            }
            else
            {
                adata = a;
            }

            Complex[] bdata;
            if (ReferenceEquals(b, c))
            {
                bdata = (Complex[])b.Clone();
            }
            else
            {
                bdata = b;
            }

            if (beta.IsZero())
            {
                Array.Clear(c, 0, c.Length);
            }
            else if (!beta.IsOne())
            {
                Control.LinearAlgebraProvider.ScaleArray(beta, c, c);
            }

            if (alpha.IsZero())
            {
                return;
            }

            CacheObliviousMatrixMultiply(transposeA, transposeB, alpha, adata, 0, 0, bdata, 0, 0, c, 0, 0, m, n, k, m, n, k, true);
        }
        /// <summary>
        /// Scales an array. Can be used to scale a vector and a matrix.
        /// </summary>
        /// <param name="alpha">The scalar.</param>
        /// <param name="x">The values to scale.</param>
        /// <param name="result">This result of the scaling.</param>
        /// <remarks>This is similar to the SCAL BLAS routine.</remarks>
        public virtual void ScaleArray(Complex alpha, Complex[] x, Complex[] result)
        {
            if (x == null)
            {
                throw new ArgumentNullException("x");
            }

            if (alpha.IsZero())
            {
                Array.Clear(result, 0, result.Length);
            }
            else if (alpha.IsOne())
            {
                x.Copy(result);
            }
            else
            {
                if (Control.ParallelizeOperation(x.Length))
                {
                    CommonParallel.For(0, x.Length, index => { result[index] = alpha * x[index]; });
                }
                else
                {
                    for (var index = 0; index < x.Length; index++)
                    {
                        result[index] = alpha * x[index];
                    }
                }
            }
        }