/*
 * Copyright (c) 2020, Peter Abeles. All Rights Reserved.
 *
 * This file is part of Efficient Java Matrix Library (EJML).
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.ejml.dense.row;

import org.ejml.UtilEjml;
import org.ejml.data.ZMatrixRMaj;
import org.junit.jupiter.api.Test;

import java.util.Random;

import static org.junit.jupiter.api.Assertions.*;

/**
 * @author Peter Abeles
 */
public class TestRandomMatrices_ZDRM {

    private final Random rand = new Random(234);

    @Test
    void rectangle_min_max() {
        ZMatrixRMaj A = RandomMatrices_ZDRM.rectangle(30, 20, -1, 1, rand);

        checkRandomRange(A);
    }

    @Test
    void fillUniform() {
        ZMatrixRMaj A = new ZMatrixRMaj(5, 4);

        RandomMatrices_ZDRM.fillUniform(A, rand);

        checkUniform1(A);
    }

    private void checkUniform1( ZMatrixRMaj a ) {
        assertEquals(5, a.numRows);
        assertEquals(4, a.numCols);

        double totalReal = 0;
        double totalImg = 0;
        for (int i = 0; i < a.numRows; i++) {
            for (int j = 0; j < a.numCols; j++) {
                double real = a.getReal(i, j);
                double img = a.getImag(i, j);

                assertTrue(real >= 0);
                assertTrue(real <= 1);
                totalReal += real;

                assertTrue(img >= 0);
                assertTrue(img <= 1);
                totalImg += img;
            }
        }

        assertTrue(totalReal > 0);
        assertTrue(totalImg > 0);
    }

    @Test
    void fillUniform_min_max() {
        ZMatrixRMaj A = new ZMatrixRMaj(30, 20);
        RandomMatrices_ZDRM.fillUniform(A, -1, 1, rand);

        checkRandomRange(A);
    }

    private void checkRandomRange( ZMatrixRMaj a ) {
        assertEquals(30, a.numRows);
        assertEquals(20, a.numCols);

        int numRealNeg = 0;
        int numRealPos = 0;
        int numImgNeg = 0;
        int numImgPos = 0;

        for (int i = 0; i < a.numRows; i++) {
            for (int j = 0; j < a.numCols; j++) {
                double real = a.getReal(i, j);
                double img = a.getImag(i, j);

                if (real < 0)
                    numRealNeg++;
                else
                    numRealPos++;

                if (Math.abs(real) > 1)
                    fail("Out of range");

                if (img < 0)
                    numImgNeg++;
                else
                    numImgPos++;

                if (Math.abs(img) > 1)
                    fail("Out of range");
            }
        }

        assertTrue(numRealNeg > 0);
        assertTrue(numRealPos > 0);

        assertTrue(numImgNeg > 0);
        assertTrue(numImgPos > 0);
    }

    @Test
    void hermitianPosDef() {
        for (int i = 1; i < 20; i++) {
            ZMatrixRMaj A = RandomMatrices_ZDRM.hermitianPosDef(i, rand);

            assertTrue(MatrixFeatures_ZDRM.isPositiveDefinite(A));
        }
    }

    @Test
    void hermitian() {
        ZMatrixRMaj A = RandomMatrices_ZDRM.hermitian(10, -1, 1, rand);

        assertTrue(MatrixFeatures_ZDRM.isHermitian(A, UtilEjml.TEST_F64));

        // see if it has the expected range of elements
        double min = CommonOps_ZDRM.elementMinReal(A);
        double max = CommonOps_ZDRM.elementMaxReal(A);

        assertTrue(min < 0 && min >= -1);
        assertTrue(max > 0 && max <= 1);

        min = CommonOps_ZDRM.elementMinImaginary(A);
        max = CommonOps_ZDRM.elementMaxImaginary(A);

        assertTrue(min < 0 && min >= -1);
        assertTrue(max > 0 && max <= 1);
    }
//
//    @Test
//    void createUpperTriangle() {
//        for( int hess = 0; hess < 3; hess++ ) {
//            ZMatrixRMaj A = RandomMatrices_ZDRM.createUpperTriangle(10,hess,-1,1,rand);
//
//            assertTrue(MatrixFeatures.isUpperTriangle(A,hess,UtilEjml.TEST_F64));
//
//            // quick sanity check to make sure it could be proper
//            assertTrue(A.get(hess,0) != 0 );
//
//            // see if it has the expected range of elements
//            double min = CommonOps.elementMin(A);
//            double max = CommonOps.elementMax(A);
//
//            assertTrue(min < 0 && min >= -1);
//            assertTrue(max > 0 && max <= 1);
//        }
//    }
}
