gt:             assertEquals(2, x2.get(1, 1), EPSILON);
context: /**
   * Copyright (c) 2017, RTE (http://www.rte-france.com)
   * This Source Code Form is subject to the terms of the Mozilla Public
   * License, v. 2.0. If a copy of the MPL was not distributed with this
   * file, You can obtain one at http://mozilla.org/MPL/2.0/.
   */
  package com.powsybl.math.matrix;
  
  import com.google.common.collect.ImmutableList;
  import com.google.common.testing.EqualsTester;
  import org.junit.Test;
  
  import java.io.ByteArrayOutputStream;
  import java.io.IOException;
  import java.io.PrintStream;
  import java.nio.charset.StandardCharsets;
  import java.util.ArrayList;
  import java.util.List;
  
  import static org.junit.Assert.*;
  
  /**
   * @author Geoffroy Jamgotchian <geoffroy.jamgotchian at rte-france.com>
   */
  public abstract class AbstractMatrixTest {
  
      protected static final double EPSILON = Math.pow(10, -15);
  
      protected abstract MatrixFactory getMatrixFactory();
  
      protected abstract MatrixFactory getOtherMatrixFactory();
  
      protected Matrix createA(MatrixFactory matrixFactory) {
          Matrix a = matrixFactory.create(3, 2, 3);
          a.set(0, 0, 1);
          a.set(2, 0, 2);
          a.set(1, 1, 3);
          return a;
      }
  
      @Test
      public void checkBoundsTest() {
          try {
              getMatrixFactory().create(-1, 1, 1);
              fail();
          } catch (IllegalArgumentException ignored) {
          }
          try {
              getMatrixFactory().create(1, -1, 1);
              fail();
          } catch (IllegalArgumentException ignored) {
          }
  
          Matrix a = getMatrixFactory().create(1, 1, 1);
          try {
              a.set(-1, 0, 0);
              fail();
          } catch (IllegalArgumentException ignored) {
          }
          try {
              a.set(0, -1, 0);
              fail();
          } catch (IllegalArgumentException ignored) {
          }
          try {
              a.set(2, 0, 0);
              fail();
          } catch (IllegalArgumentException ignored) {
          }
          try {
              a.set(0, 1, 0);
              fail();
          } catch (IllegalArgumentException ignored) {
          }
          try {
              a.add(2, 0, 0);
              fail();
          } catch (IllegalArgumentException ignored) {
          }
          try {
              a.add(0, 1, 0);
              fail();
          } catch (IllegalArgumentException ignored) {
          }
  
      }
  
      @Test
      public void testMultiplication() {
          Matrix a = createA(getMatrixFactory());
          Matrix b = getMatrixFactory().create(2, 1, 2);
          b.set(0, 0, 4);
          b.set(1, 0, 5);
  
          Matrix cs = a.times(b);
          DenseMatrix c = cs.toDense();
  
          assertEquals(3, c.getRowCount());
          assertEquals(1, c.getColumnCount());
          assertEquals(4, c.get(0, 0), EPSILON);
          assertEquals(15, c.get(1, 0), EPSILON);
          assertEquals(8, c.get(2, 0), EPSILON);
      }
  
      @Test
      public void testAddition() {
          /*
          1 0
          0 3
          2 0
           */
          Matrix a = createA(getMatrixFactory());
          /*
          4 0
          5 0
          0 0
           */
          Matrix b = getMatrixFactory().create(3, 2, 3);
          b.set(0, 0, 4);
          b.set(1, 0, 5);
  
          Matrix cs = a.add(b);
          DenseMatrix c = cs.toDense();
  
          assertEquals(3, c.getRowCount());
          assertEquals(2, c.getColumnCount());
          assertEquals(5, c.get(0, 0), EPSILON);
          assertEquals(5, c.get(1, 0), EPSILON);
          assertEquals(2, c.get(2, 0), EPSILON);
          assertEquals(0, c.get(0, 1), EPSILON);
          assertEquals(3, c.get(1, 1), EPSILON);
          assertEquals(0, c.get(2, 1), EPSILON);
  
          // in case of sparse matrix check, we only have 4 values
          if (cs instanceof SparseMatrix) {
              assertEquals(4, ((SparseMatrix) cs).getValues().length);
          }
      }
  
      @Test
      public void testAdditionWithEmptyColumnInTheMiddle() {
          /*
          1 0 0
          0 0 3
          2 0 0
           */
          Matrix a = getMatrixFactory().create(3, 3, 3);
          a.set(0, 0, 1);
          a.set(2, 0, 2);
          a.set(1, 2, 3);
  
          /*
          4 0 6
          5 0 0
          0 0 0
           */
          Matrix b = getMatrixFactory().create(3, 3, 3);
          b.set(0, 0, 4);
          b.set(1, 0, 5);
          b.set(0, 2, 6);
  
          Matrix cs = a.add(b);
          DenseMatrix c = cs.toDense();
  
          assertEquals(3, c.getRowCount());
          assertEquals(3, c.getColumnCount());
          assertEquals(5, c.get(0, 0), EPSILON);
          assertEquals(5, c.get(1, 0), EPSILON);
          assertEquals(2, c.get(2, 0), EPSILON);
          assertEquals(0, c.get(0, 1), EPSILON);
          assertEquals(0, c.get(1, 1), EPSILON);
          assertEquals(0, c.get(2, 1), EPSILON);
          assertEquals(6, c.get(0, 2), EPSILON);
          assertEquals(3, c.get(1, 2), EPSILON);
          assertEquals(0, c.get(2, 2), EPSILON);
      }
  
      @Test
      public void testIterateNonZeroValue() {
          Matrix a = createA(getMatrixFactory());
          a.iterateNonZeroValue((i, j, value) -> {
              if (i == 0 && j == 0) {
                  assertEquals(1d, value, 0d);
              } else if (i == 1 && j == 1) {
                  assertEquals(3d, value, 0d);
              } else if (i == 2 && j == 0) {
                  assertEquals(2d, value, 0d);
              } else {
                  fail();
              }
          });
      }
  
      @Test
      public void testIterateNonZeroValueOfColumn() {
          Matrix a = createA(getMatrixFactory());
          List<Double> nonZeroValues = new ArrayList<>();
          a.iterateNonZeroValueOfColumn(0, (i, j, value) -> {
              nonZeroValues.add(value);
          });
          assertEquals(ImmutableList.of(1d, 2d), nonZeroValues);
      }
  
      protected String print(Matrix matrix, List<String> rowNames, List<String> columnNames) throws IOException {
          ByteArrayOutputStream bos = new ByteArrayOutputStream();
          try {
              matrix.print(new PrintStream(bos), rowNames, columnNames);
          } finally {
              bos.close();
          }
          return bos.toString(StandardCharsets.UTF_8.name());
      }
  
      protected String print(Matrix matrix) throws IOException {
          ByteArrayOutputStream bos = new ByteArrayOutputStream();
          try {
              matrix.print(new PrintStream(bos));
          } finally {
              bos.close();
          }
          return bos.toString(StandardCharsets.UTF_8.name());
      }
  
      @Test
      public void testDecompose() {
          // 2  3  0  0  0
          // 3  0  4  0  6
          // 0 -1 -3  2  0
          // 0  0  1  0  0
          // 0  4  2  0  1
          Matrix matrix = getMatrixFactory().create(5, 5, 12);
  
          matrix.set(0, 0, 2);
          matrix.set(1, 0, 3);
  
          matrix.set(0, 1, 3);
          matrix.set(2, 1, -1);
          matrix.set(4, 1, 4);
  
          matrix.set(1, 2, 4);
          matrix.set(2, 2, -3);
          Matrix.Element e = matrix.addAndGetElement(3, 2, 1);
          matrix.set(4, 2, 2);
  
          matrix.set(2, 3, 2);
  
          matrix.set(1, 4, 6);
          matrix.set(4, 4, 1);
  
          try (LUDecomposition decomposition = matrix.decomposeLU()) {
              double[] x = {8, 45, -3, 3, 19};
              decomposition.solve(x);
              assertArrayEquals(new double[]{1, 2, 3, 4, 5}, x, EPSILON);
  
              DenseMatrix x2 = new DenseMatrix(5, 2);
              x2.set(0, 0, 8);
              x2.set(1, 0, 45);
              x2.set(2, 0, -3);
              x2.set(3, 0, 3);
              x2.set(4, 0, 19);
              x2.set(0, 1, 8);
              x2.set(1, 1, 45);
              x2.set(2, 1, -3);
              x2.set(3, 1, 3);
              x2.set(4, 1, 19);
  
              decomposition.solve(x2);
              assertEquals(1, x2.get(0, 0), EPSILON);
              assertEquals(2, x2.get(1, 0), EPSILON);
              assertEquals(3, x2.get(2, 0), EPSILON);
              assertEquals(4, x2.get(3, 0), EPSILON);
              assertEquals(5, x2.get(4, 0), EPSILON);
              assertEquals(1, x2.get(0, 1), EPSILON);
              assertEquals(2, x2.get(1, 1), EPSILON);
              assertEquals(3, x2.get(2, 1), EPSILON);
              assertEquals(4, x2.get(3, 1), EPSILON);
              assertEquals(5, x2.get(4, 1), EPSILON);
  
              e.set(4);
              e.add(1);
              decomposition.update();
              double[] x3 = {8, 45, -3, 3, 19};
              decomposition.solve(x3);
              assertArrayEquals(new double[]{-0.010526315789474902, 2.673684210526316, 0.6, 0.7368421052631579, 7.105263157894737}, x3, EPSILON);
          }
      }
  
      @Test
      public void testTransposedDecompose() {
          // 2  3  0  0  0
          // 3  0 -1  0  4
          // 0  4 -3  1  2
          // 0  0  2  0  0
          // 0  6  0  0  1
          Matrix matrix = getMatrixFactory().create(5, 5, 12);
  
          matrix.set(0, 0, 2);
          matrix.set(1, 0, 3);
  
          matrix.set(0, 1, 3);
          matrix.set(2, 1, 4);
          matrix.set(4, 1, 6);
  
          matrix.set(1, 2, -1);
          matrix.set(2, 2, -3);
          matrix.set(3, 2, 2);
  
          matrix.set(2, 3, 1);
  
          matrix.set(1, 4, 4);
          matrix.set(2, 4, 2);
          matrix.set(4, 4, 1);
  
          try (LUDecomposition decomposition = matrix.decomposeLU()) {
              double[] x = {8, 45, -3, 3, 19};
              decomposition.solveTransposed(x);
              assertArrayEquals(new double[]{1, 2, 3, 4, 5}, x, EPSILON);
  
              DenseMatrix x2 = new DenseMatrix(5, 2);
              x2.set(0, 0, 8);
              x2.set(1, 0, 45);
              x2.set(2, 0, -3);
              x2.set(3, 0, 3);
              x2.set(4, 0, 19);
              x2.set(0, 1, 8);
              x2.set(1, 1, 45);
              x2.set(2, 1, -3);
              x2.set(3, 1, 3);
              x2.set(4, 1, 19);
  
              decomposition.solveTransposed(x2);
              assertEquals(1, x2.get(0, 0), EPSILON);
              assertEquals(2, x2.get(1, 0), EPSILON);
              assertEquals(3, x2.get(2, 0), EPSILON);
              assertEquals(4, x2.get(3, 0), EPSILON);
              assertEquals(5, x2.get(4, 0), EPSILON);
              assertEquals(1, x2.get(0, 1), EPSILON);
  