/**
         * <p>
         * Adds to A &isin; &real; <sup>m &times; n</sup> the results of an outer product multiplication
         * of the two vectors.  This is also known as a rank 1 update.<br>
         * <br>
         * A = A + &gamma; x * y<sup>T</sup>
         * where x &isin; &real; <sup>m</sup> and y &isin; &real; <sup>n</sup> are vectors.
         * </p>
         * <p>
         * Which is equivalent to: A<sub>ij</sub> = A<sub>ij</sub> + &gamma; x<sub>i</sub>*y<sub>j</sub>
         * </p>
         *
         * <p>
         * These functions are often used inside of highly optimized code and therefor sanity checks are
         * kept to a minimum.  It is not recommended that any of these functions be used directly.
         * </p>
         *
         * @param gamma A multiplication factor for the outer product.
         * @param x A vector with m elements. Not modified.
         * @param y A vector with n elements. Not modified.
         * @param A A Matrix with m by n elements. Modified.
         */
        public static void addOuterProd(double gamma, DMatrixD1 x, DMatrixD1 y, DMatrix1Row A)
        {
            int m = A.numRows;
            int n = A.numCols;

            int index = 0;

            if (gamma == 1.0)
            {
                for (int i = 0; i < m; i++)
                {
                    double xdat = x.get(i);
                    for (int j = 0; j < n; j++)
                    {
                        A.plus(index++, xdat * y.get(j));
                    }
                }
            }
            else
            {
                for (int i = 0; i < m; i++)
                {
                    double xdat = x.get(i);
                    for (int j = 0; j < n; j++)
                    {
                        A.plus(index++, gamma * xdat * y.get(j));
                    }
                }
            }
        }
        /**
         * @see CommonOps_DDRM#multAdd(double, org.ejml.data.DMatrix1Row, org.ejml.data.DMatrix1Row, org.ejml.data.DMatrix1Row)
         */
        public static void multAdd_small(double alpha, DMatrix1Row A, DMatrix1Row B, DMatrix1Row C)
        {
            UtilEjml.assertTrue(A != C && B != C, "Neither 'A' or 'B' can be the same matrix as 'C'");
            UtilEjml.assertShape(A.numCols, B.numRows, "The 'A' and 'B' matrices do not have compatible dimensions");
            UtilEjml.assertShape(A.numRows == C.numRows && B.numCols == C.numCols, "C is not compatible with A and B");

            //CONCURRENT_BELOW EjmlConcurrency.loopFor(0, A.numRows, i -> {
            for (int i = 0; i < A.numRows; i++)
            {
                int cIndex      = i * B.numCols;
                int aIndexStart = i * A.numCols;
                for (int j = 0; j < B.numCols; j++)
                {
                    double total = 0;

                    int indexA = aIndexStart;
                    int indexB = j;
                    int end    = indexA + B.numRows;
                    while (indexA < end)
                    {
                        total  += A.data[indexA++] * B.data[indexB];
                        indexB += B.numCols;
                    }

                    C.plus(cIndex++, alpha * total);
                }
            }
            //CONCURRENT_ABOVE });
        }
        //CONCURRENT_OMIT_END

        /**
         * @see CommonOps_DDRM#multAddTransB(org.ejml.data.DMatrix1Row, org.ejml.data.DMatrix1Row, org.ejml.data.DMatrix1Row)
         */
        public static void multAddTransB(DMatrix1Row A, DMatrix1Row B, DMatrix1Row C)
        {
            UtilEjml.assertTrue(A != C && B != C, "Neither 'A' or 'B' can be the same matrix as 'C'");
            UtilEjml.assertShape(A.numCols, B.numCols, "The 'A' and 'B' matrices do not have compatible dimensions");
            UtilEjml.assertShape(A.numRows == C.numRows && B.numRows == C.numCols, "C is not compatible with A and B");

            //CONCURRENT_BELOW EjmlConcurrency.loopFor(0, A.numRows, xA -> {
            for (int xA = 0; xA < A.numRows; xA++)
            {
                int cIndex      = xA * B.numRows;
                int aIndexStart = xA * B.numCols;
                int end         = aIndexStart + B.numCols;
                int indexB      = 0;
                for (int xB = 0; xB < B.numRows; xB++)
                {
                    int indexA = aIndexStart;

                    double total = 0;
                    while (indexA < end)
                    {
                        total += A.data[indexA++] * B.data[indexB++];
                    }

                    C.plus(cIndex++, total);
                }
            }
            //CONCURRENT_ABOVE });
        }
        //CONCURRENT_OMIT_BEGIN

        /**
         * @see CommonOps_DDRM#multAdd(org.ejml.data.DMatrix1Row, org.ejml.data.DMatrix1Row, org.ejml.data.DMatrix1Row)
         */
        public static void multAdd_aux(DMatrix1Row A, DMatrix1Row B, DMatrix1Row C, double[] aux)
        {
            UtilEjml.assertTrue(A != C && B != C, "Neither 'A' or 'B' can be the same matrix as 'C'");
            UtilEjml.assertShape(A.numCols, B.numRows, "The 'A' and 'B' matrices do not have compatible dimensions");
            UtilEjml.assertShape(A.numRows == C.numRows && B.numCols == C.numCols, "C is not compatible with A and B");

            if (aux == null)
            {
                aux = new double[B.numRows];
            }

            for (int j = 0; j < B.numCols; j++)
            {
                // create a copy of the column in B to avoid cache issues
                for (int k = 0; k < B.numRows; k++)
                {
                    aux[k] = B.unsafe_get(k, j);
                }

                int indexA = 0;
                for (int i = 0; i < A.numRows; i++)
                {
                    double total = 0;
                    for (int k = 0; k < B.numRows;)
                    {
                        total += A.data[indexA++] * aux[k++];
                    }
                    C.plus(i * C.numCols + j, total);
                }
            }
        }
        /**
         * @see CommonOps_DDRM#multAdd(double, org.ejml.data.DMatrix1Row, org.ejml.data.DMatrix1Row, org.ejml.data.DMatrix1Row)
         */
        public static void multAdd_reorder(double alpha, DMatrix1Row A, DMatrix1Row B, DMatrix1Row C)
        {
            UtilEjml.assertTrue(A != C && B != C, "Neither 'A' or 'B' can be the same matrix as 'C'");
            UtilEjml.assertShape(A.numCols, B.numRows, "The 'A' and 'B' matrices do not have compatible dimensions");
            UtilEjml.assertShape(A.numRows == C.numRows && B.numCols == C.numCols, "C is not compatible with A and B");

            if (A.numCols == 0 || A.numRows == 0)
            {
                return;
            }
            int endOfKLoop = B.numRows * B.numCols;

            //CONCURRENT_BELOW EjmlConcurrency.loopFor(0, A.numRows, i -> {
            for (int i = 0; i < A.numRows; i++)
            {
                int indexCbase = i * C.numCols;
                int indexA     = i * A.numCols;

                // need to assign C.data to a value initially
                int indexB = 0;
                int indexC = indexCbase;
                int end    = indexB + B.numCols;

                double valA = alpha * A.data[indexA++];

                while (indexB < end)
                {
                    C.plus(indexC++, valA * B.data[indexB++]);
                }

                // now add to it
                while (indexB != endOfKLoop)
                { // k loop
                    indexC = indexCbase;
                    end    = indexB + B.numCols;

                    valA = alpha * A.data[indexA++];

                    while (indexB < end)
                    { // j loop
                        C.data[indexC++] += valA * B.data[indexB++];
                    }
                }
            }
            //CONCURRENT_ABOVE });
        }
        //CONCURRENT_OMIT_END

        /**
         * @see CommonOps_DDRM#multAddTransA(org.ejml.data.DMatrix1Row, org.ejml.data.DMatrix1Row, org.ejml.data.DMatrix1Row)
         */
        public static void multAddTransA_reorder(DMatrix1Row A, DMatrix1Row B, DMatrix1Row C)
        {
            UtilEjml.assertTrue(A != C && B != C, "Neither 'A' or 'B' can be the same matrix as 'C'");
            UtilEjml.assertShape(A.numRows, B.numRows, "The 'A' and 'B' matrices do not have compatible dimensions");
            UtilEjml.assertShape(A.numCols == C.numRows && B.numCols == C.numCols, "C is not compatible with A and B");

            if (A.numCols == 0 || A.numRows == 0)
            {
                return;
            }
            //CONCURRENT_BELOW EjmlConcurrency.loopFor(0, A.numRows, i -> {
            for (int i = 0; i < A.numCols; i++)
            {
                int indexC_start = i * C.numCols;

                // first assign R
                double valA   = A.data[i];
                int    indexB = 0;
                int    end    = indexB + B.numCols;
                int    indexC = indexC_start;
                while (indexB < end)
                {
                    C.plus(indexC++, valA * B.data[indexB++]);
                }
                // now increment it
                for (int k = 1; k < A.numRows; k++)
                {
                    valA   = A.unsafe_get(k, i);
                    end    = indexB + B.numCols;
                    indexC = indexC_start;
                    // this is the loop for j
                    while (indexB < end)
                    {
                        C.data[indexC++] += valA * B.data[indexB++];
                    }
                }
            }
            //CONCURRENT_ABOVE });
        }
        //CONCURRENT_OMIT_BEGIN

        /**
         * @see CommonOps_DDRM#multAddTransAB(org.ejml.data.DMatrix1Row, org.ejml.data.DMatrix1Row, org.ejml.data.DMatrix1Row)
         */
        public static void multAddTransAB_aux(DMatrix1Row A, DMatrix1Row B, DMatrix1Row C, double[] aux)
        {
            UtilEjml.assertTrue(A != C && B != C, "Neither 'A' or 'B' can be the same matrix as 'C'");
            UtilEjml.assertShape(A.numRows, B.numCols, "The 'A' and 'B' matrices do not have compatible dimensions");
            UtilEjml.assertShape(A.numCols == C.numRows && B.numRows == C.numCols, "C is not compatible with A and B");

            if (aux == null)
            {
                aux = new double[A.numRows];
            }

            if (A.numCols == 0 || A.numRows == 0)
            {
                return;
            }
            int indexC = 0;

            for (int i = 0; i < A.numCols; i++)
            {
                for (int k = 0; k < B.numCols; k++)
                {
                    aux[k] = A.unsafe_get(k, i);
                }

                for (int j = 0; j < B.numRows; j++)
                {
                    double total = 0;

                    for (int k = 0; k < B.numCols; k++)
                    {
                        total += aux[k] * B.unsafe_get(j, k);
                    }
                    C.plus(indexC++, total);
                }
            }
        }