/** * <p> * Sets every element in the matrix to the specified value.<br> * <br> * a<sub>ij</sub> = value * <p> * * @param a A matrix whose elements are about to be set. Modified. * @param real The real component * @param imaginary The imaginary component */ public static void fill(CMatrixD1 a, float real, float imaginary) { int N = a.getDataLength(); for (int i = 0; i < N; i += 2) { a.data[i] = real; a.data[i + 1] = imaginary; } }
/** * <p> * Sets each element in the matrix to a value drawn from an uniform distribution from 'min' to 'max' inclusive. * </p> * * @param min The minimum value each element can be. * @param max The maximum value each element can be. * @param mat The matrix who is to be randomized. Modified. * @param rand Random number generator used to fill the matrix. */ public static void fillUniform(CMatrixD1 mat, float min, float max, IMersenneTwister rand) { float[] d = mat.getData(); int size = mat.getDataLength(); float r = max - min; for (int i = 0; i < size; i++) { d[i] = r * rand.NextFloat() + min; } }
/** * Checks to see all the elements in the matrix are zeros * * @param m A matrix. Not modified. * @return True if all elements are zeros or false if not */ public static bool isZeros(CMatrixD1 m, float tol) { int length = m.getNumElements() * 2; for (int i = 0; i < length; i++) { if (Math.Abs(m.data[i]) > tol) { return(false); } } return(true); }
/** * Checks to see if any element in the matrix is NaN. * * @param m A matrix. Not modified. * @return True if any element in the matrix is NaN. */ public static bool hasNaN(CMatrixD1 m) { int length = m.getDataLength(); for (int i = 0; i < length; i++) { if (float.IsNaN(m.data[i])) { return(true); } } return(false); }
/** * Checks to see if any element in the matrix is NaN of Infinite. * * @param m A matrix. Not modified. * @return True if any element in the matrix is NaN of Infinite. */ public static bool hasUncountable(CMatrixD1 m) { int length = m.getDataLength(); for (int i = 0; i < length; i++) { float a = m.data[i]; if (float.IsNaN(a) || float.IsInfinity(a)) { return(true); } } return(false); }
/** * <p> * Computes the complex conjugate of the input matrix.<br> * <br> * real<sub>i,j</sub> = real<sub>i,j</sub><br> * imaginary<sub>i,j</sub> = -1*imaginary<sub>i,j</sub><br> * </p> * * @param input Input matrix. Not modified. * @param output The complex conjugate of the input matrix. Modified. */ public static void conjugate(CMatrixD1 input, CMatrixD1 output) { if (input.numCols != output.numCols || input.numRows != output.numRows) { throw new ArgumentException("The matrices are not all the same dimension."); } int length = input.getDataLength(); for (int i = 0; i < length; i += 2) { output.data[i] = input.data[i]; output.data[i + 1] = -input.data[i + 1]; } }
/** * <p>Performs the following operation:<br> * <br> * c = a - b <br> * c<sub>ij</sub> = a<sub>ij</sub> - b<sub>ij</sub> <br> * </p> * * <p> * Matrix C can be the same instance as Matrix A and/or B. * </p> * * @param a A Matrix. Not modified. * @param b A Matrix. Not modified. * @param c A Matrix where the results are stored. Modified. */ public static void subtract(CMatrixD1 a, CMatrixD1 b, CMatrixD1 c) { if (a.numCols != b.numCols || a.numRows != b.numRows || a.numCols != c.numCols || a.numRows != c.numRows) { throw new ArgumentException("The matrices are not all the same dimension."); } int length = a.getDataLength(); for (int i = 0; i < length; i++) { c.data[i] = a.data[i] - b.data[i]; } }
/** * <p> * Performs an in-place element by element scalar multiplication.<br> * <br> * a<sub>ij</sub> = α*a<sub>ij</sub> * </p> * * @param a The matrix that is to be scaled. Modified. * @param alphaReal real component of scale factor * @param alphaImag imaginary component of scale factor */ public static void scale(float alphaReal, float alphaImag, CMatrixD1 a) { // on very small matrices (2 by 2) the call to getNumElements() can slow it down // slightly compared to other libraries since it involves an extra multiplication. int size = a.getNumElements() * 2; for (int i = 0; i < size; i += 2) { float real = a.data[i]; float imag = a.data[i + 1]; a.data[i] = real * alphaReal - imag * alphaImag; a.data[i + 1] = real * alphaImag + imag * alphaReal; } }
/** * Converts the real matrix into a complex matrix. * * @param input Real matrix. Not modified. * @param output Complex matrix. Modified. */ public static void convert(FMatrixD1 input, CMatrixD1 output) { if (input.numCols != output.numCols || input.numRows != output.numRows) { throw new ArgumentException("The matrices are not all the same dimension."); } Array.Clear(output.data, 0, output.getDataLength()); int length = output.getDataLength(); for (int i = 0; i < length; i += 2) { output.data[i] = input.data[i / 2]; } }
/** * <p> * Returns the value of the imaginary element in the matrix that has the minimum value.<br> * <br> * Min{ a<sub>ij</sub> } for all i and j<br> * </p> * * @param a A matrix. Not modified. * @return The the minimum value out of all the real values. */ public static float elementMinImaginary(CMatrixD1 a) { int size = a.getDataLength(); float min = a.data[1]; for (int i = 3; i < size; i += 2) { float val = a.data[i]; if (val < min) { min = val; } } return(min); }
/** * <p> * Returns the value of the imaginary element in the matrix that has the minimum value.<br> * <br> * Min{ a<sub>ij</sub> } for all i and j<br> * </p> * * @param a A matrix. Not modified. * @return The the minimum value out of all the real values. */ public static float elementMaxImaginary(CMatrixD1 a) { int size = a.getDataLength(); float max = a.data[1]; for (int i = 3; i < size; i += 2) { float val = a.data[i]; if (val > max) { max = val; } } return(max); }
/** * <p> * Computes the magnitude of the complex number in the input matrix and stores the results in the output * matrix. * </p> * * magnitude = sqrt(real^2 + imaginary^2) * * @param input Complex matrix. Not modified. * @param output real matrix. Modified. */ public static void magnitude(CMatrixD1 input, FMatrixD1 output) { if (input.numCols != output.numCols || input.numRows != output.numRows) { throw new ArgumentException("The matrices are not all the same dimension."); } int length = input.getDataLength(); for (int i = 0; i < length; i += 2) { float real = input.data[i]; float imaginary = input.data[i + 1]; output.data[i / 2] = (float)Math.Sqrt(real * real + imaginary * imaginary); } }
/** * <p> * Checks to see if each corresponding element in the two matrices are * within tolerance of each other or have the some symbolic meaning. This * can handle NaN and Infinite numbers. * <p> * * <p> * If both elements are countable then the following equality test is used:<br> * |a<sub>ij</sub> - b<sub>ij</sub>| ≤ tol.<br> * Otherwise both numbers must both be Float.NaN, Float.POSITIVE_INFINITY, or * Float.NEGATIVE_INFINITY to be identical. * </p> * * @param a A matrix. Not modified. * @param b A matrix. Not modified. * @param tol Tolerance for equality. * @return true if identical and false otherwise. */ public static bool isIdentical(CMatrixD1 a, CMatrixD1 b, float tol) { if (a.numRows != b.numRows || a.numCols != b.numCols) { return(false); } if (tol < 0) { throw new ArgumentException("Tolerance must be greater than or equal to zero."); } int length = a.getDataLength(); for (int i = 0; i < length; i++) { float valA = a.data[i]; float valB = b.data[i]; // if either is negative or positive infinity the result will be positive infinity // if either is NaN the result will be NaN float diff = Math.Abs(valA - valB); // diff = NaN == false // diff = infinity == false if (tol >= diff) { continue; } if (float.IsNaN(valA)) { return(float.IsNaN(valB)); } else if (float.IsInfinity(valA)) { return(valA == valB); } else { return(false); } } return(true); }
/** * <p>Performs element by element multiplication operation with a complex numbert<br> * <br> * output<sub>ij</sub> = input<sub>ij</sub> * (real + imaginary*i) <br> * </p> * @param input The left matrix in the multiplication operation. Not modified. * @param real Real component of the number it is multiplied by * @param imaginary Imaginary component of the number it is multiplied by * @param output Where the results of the operation are stored. Modified. */ public static void elementMultiply(CMatrixD1 input, float real, float imaginary, CMatrixD1 output) { if (input.numCols != output.numCols || input.numRows != output.numRows) { throw new ArgumentException("The 'input' and 'output' matrices do not have compatible dimensions"); } int N = input.getDataLength(); for (int i = 0; i < N; i += 2) { float inReal = input.data[i]; float intImag = input.data[i + 1]; output.data[i] = inReal * real - intImag * imaginary; output.data[i + 1] = inReal * imaginary + intImag * real; } }
/** * <p> * Checks to see if the two matrices are the negative of each other:<br> * <br> * a<sub>ij</sub> = -b<sub>ij</sub> * </p> * * @param a First matrix. Not modified. * @param b Second matrix. Not modified. * @param tol Numerical tolerance. * @return True if they are the negative of each other within tolerance. */ public static bool isNegative(CMatrixD1 a, CMatrixD1 b, float tol) { if (a.numRows != b.numRows || a.numCols != b.numCols) { throw new ArgumentException("Matrix dimensions must match"); } int length = a.getNumElements() * 2; for (int i = 0; i < length; i++) { if (!(Math.Abs(a.data[i] + b.data[i]) <= tol)) { return(false); } } return(true); }
/** * <p> * Checks to see if each element in the two matrices are equal: * a<sub>ij</sub> == b<sub>ij</sub> * <p> * * <p> * NOTE: If any of the elements are NaN then false is returned. If two corresponding * elements are both positive or negative infinity then they are equal. * </p> * * @param a A matrix. Not modified. * @param b A matrix. Not modified. * @return true if identical and false otherwise. */ public static bool isEquals(CMatrixD1 a, CMatrixD1 b) { if (a.numRows != b.numRows || a.numCols != b.numCols) { return(false); } int length = a.getDataLength(); for (int i = 0; i < length; i++) { if (!(a.data[i] == b.data[i])) { return(false); } } return(true); }
/** * Places the imaginary component of the input matrix into the output matrix. * * @param input Complex matrix. Not modified. * @param output real matrix. Modified. */ public static FMatrixRMaj stripImaginary(CMatrixD1 input, FMatrixRMaj output) { if (output == null) { output = new FMatrixRMaj(input.numRows, input.numCols); } else if (input.numCols != output.numCols || input.numRows != output.numRows) { throw new ArgumentException("The matrices are not all the same dimension."); } int length = input.getDataLength(); for (int i = 1; i < length; i += 2) { output.data[i / 2] = input.data[i]; } return(output); }
/** * <p>Performs element by element division operation with a complex number on the right<br> * <br> * output<sub>ij</sub> = (real + imaginary*i) / input<sub>ij</sub> <br> * </p> * @param real Real component of the number it is multiplied by * @param imaginary Imaginary component of the number it is multiplied by * @param input The right matrix in the multiplication operation. Not modified. * @param output Where the results of the operation are stored. Modified. */ public static void elementDivide(float real, float imaginary, CMatrixD1 input, CMatrixD1 output) { if (input.numCols != output.numCols || input.numRows != output.numRows) { throw new ArgumentException("The 'input' and 'output' matrices do not have compatible dimensions"); } int N = input.getDataLength(); for (int i = 0; i < N; i += 2) { float inReal = input.data[i]; float inImag = input.data[i + 1]; float norm = inReal * inReal + inImag * inImag; output.data[i] = (real * inReal + imaginary * inImag) / norm; output.data[i + 1] = (imaginary * inReal - real * inImag) / norm; } }
/** * <p> * Returns the magnitude squared of the complex element with the largest magnitude<br> * <br> * Max{ |a<sub>ij</sub>|^2 } for all i and j<br> * </p> * * @param a A matrix. Not modified. * @return The max magnitude squared */ public static float elementMaxMagnitude2(CMatrixD1 a) { int size = a.getDataLength(); float max = 0; for (int i = 0; i < size;) { float real = a.data[i++]; float imaginary = a.data[i++]; float m = real * real + imaginary * imaginary; if (m > max) { max = m; } } return(max); }
/** * <p> * Checks to see if each element in the two matrices are within tolerance of * each other: tol ≥ |a<sub>ij</sub> - b<sub>ij</sub>|. * <p> * * <p> * NOTE: If any of the elements are not countable then false is returned.<br> * NOTE: If a tolerance of zero is passed in this is equivalent to calling * {@link #isEquals(CMatrixD1, CMatrixD1)} * </p> * * @param a A matrix. Not modified. * @param b A matrix. Not modified. * @param tol How close to being identical each element needs to be. * @return true if equals and false otherwise. */ public static bool isEquals(CMatrixD1 a, CMatrixD1 b, float tol) { if (a.numRows != b.numRows || a.numCols != b.numCols) { return(false); } if (tol == 0.0f) { return(isEquals(a, b)); } int length = a.getDataLength(); for (int i = 0; i < length; i++) { if (!(tol >= Math.Abs(a.data[i] - b.data[i]))) { return(false); } } return(true); }