/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.apache.datasketches.vector.decomposition;

import static org.testng.Assert.assertEquals;
import static org.testng.Assert.fail;

import org.testng.annotations.Test;

import org.apache.datasketches.vector.matrix.Matrix;
import org.apache.datasketches.vector.matrix.MatrixBuilder;
import org.apache.datasketches.vector.matrix.MatrixType;

public class MatrixOpsTest {

  @Test
  public void compareSVDAccuracy() {
    final int d = 10;
    final int k = 6;
    final Matrix input = generateIncreasingEye(d, 2 * k);

    final MatrixOps moFull  = MatrixOps.newInstance(input, SVDAlgo.FULL, k);
    final MatrixOps moSym   = MatrixOps.newInstance(input, SVDAlgo.SYM, k);
    final MatrixOps moSISVD = MatrixOps.newInstance(input, SVDAlgo.SISVD, k);
    moSISVD.setNumSISVDIter(50 * k); // intentionally run many extra iterations for tighter convegence

    // just singular values first
    moFull.svd(input, false);
    moSym.svd(input, false);
    moSISVD.svd(input, false);
    final double[] fullSv = moFull.getSingularValues();
    compareSingularValues(fullSv, moSym.getSingularValues(), fullSv.length);
    compareSingularValues(fullSv, moSISVD.getSingularValues(), k); // SISVD only produces k values

    // now with vectors
    moFull.svd(input, true);
    moSym.svd(input, true);
    moSISVD.svd(input, true);
    // TODO: better comparison is vector-wise, testing that sign changes are consistent but that
    // requires non-zero elements
    final Matrix fullVt = moFull.getVt();
    compareMatrixElementMagnitudes(fullVt, moSym.getVt(), (int) fullVt.getNumRows());
    compareMatrixElementMagnitudes(fullVt, moSISVD.getVt(), k); // SISVD only produces k vectors

    // just to be sure
    compareMatrixElementMagnitudes(fullVt, moFull.getVt(input), (int) fullVt.getNumRows());
  }

  @Test
  public void checkInvalidMatrixSize() {
    final int d = 10;
    final int k = 6;
    final Matrix A = generateIncreasingEye(d, 2 * k);
    final MatrixOps mo = MatrixOps.newInstance(A, SVDAlgo.FULL, k);

    Matrix B = generateIncreasingEye(d, 2 * k + 1);
    try {
      mo.svd(B, true);
      fail();
    } catch (final IllegalArgumentException e) {
      // expected
    }

    B = generateIncreasingEye(d - 1, 2 * k);
    try {
      mo.svd(B, false);
      fail();
    } catch (final IllegalArgumentException e) {
      // expected
    }

  }

  private void compareSingularValues(final double[] A, final double[] B, final int n) {
    assertEquals(A.length, B.length);

    for (int i = 0; i < n; ++i) {
      assertEquals(A[i], B[i], 1e-6);
    }
  }


  private void compareMatrixElementMagnitudes(final Matrix A, final Matrix B, final int n) {
    assertEquals(A.getNumColumns(), B.getNumColumns());
    assertEquals(A.getNumRows(), B.getNumRows());

    for (int i = 0; i < n; ++i) {
      for (int j = 0; j < A.getNumColumns(); ++j) {
        assertEquals(Math.abs(A.getElement(i, j)), Math.abs(B.getElement(i, j)), 1e-6);
      }
    }
  }

  /**
   * Creates a scaled I matrix, where the diagonal consists of increasing integers,
   * starting with 1.0.
   * @param nRows number of rows
   * @param nCols number of columns
   * @return PrimitiveDenseStore, suitable for direct use or wrapping
   */
  private static Matrix generateIncreasingEye(final int nRows, final int nCols) {
    final Matrix m = new MatrixBuilder().setType(MatrixType.OJALGO).build(nRows, nCols);
    for (int i = 0; (i < nRows) && (i < nCols); ++i) {
      m.setElement(i, i, 1.0 + i);
    }
    return m;
  }

}
