code: package zemberek.core.math;
  
  import java.io.DataInputStream;
  import java.io.DataOutputStream;
  import java.io.File;
  import java.io.FileInputStream;
  import java.io.FileOutputStream;
  import java.io.IOException;
  import java.util.Arrays;
  import org.junit.Assert;
  import org.junit.Test;
  
  public class DoubleArraysTest {
  
    static double delta = 0.0001;
  
    public static boolean inDelta(double result, double actual) {
      return Math.abs(result - actual) < delta;
    }
  
    public static boolean inDelta(double[] result, double[] actual) {
      for (int i = 0; i < result.length; i++) {
        if (Math.abs(result[i] - actual[i]) > delta) {
          return false;
        }
      }
      return true;
    }
  
    @Test
    public void testSum() {
      double[] da = {1, 2, 0, -1, -3};
      double[] da2 = {0.5, -2, 30, 1, -30};
      Assert.assertTrue(inDelta(DoubleArrays.sum(da), -1));
      Assert.assertTrue(inDelta(DoubleArrays.sum(da, da2), new double[]{1.5, 0, 30, 0, -33}));
      DoubleArrays.addToFirst(da, da2);
      Assert.assertTrue(inDelta(da, new double[]{1.5, 0, 30, 0, -33}));
    }
  
    @Test
    public void addToFirstScaledTest() {
      double[] da1 = {1, 2, 0, -1, -30};
      double[] da2 = {-0.5, -1, 0, 0.5, 15};
      DoubleArrays.addToFirstScaled(da1, da2, 2);
      Assert.assertEquals(DoubleArrays.max(da1), 0d, 0.0001);
      Assert.assertEquals(DoubleArrays.min(da1), 0d, 0.0001);
    }
  
    @Test
    public void testDotProduct() {
      double[] da = {1, 2, 0, -1, -3};
      double[] da2 = {0.5, -2, 30, 1, -30};
      Assert.assertTrue(inDelta(DoubleArrays.dotProduct(da, da2), 85.5));
    }
  
    @Test
    public void testSubstract() {
      double[] da = {1, 2, 0, -1, -3};
      double[] da2 = {0.5, -2, 30, 1, -30};
      Assert.assertTrue(inDelta(DoubleArrays.subtract(da, da2), new double[]{0.5, 4, -30, -2, 27}));
      DoubleArrays.subtractFromFirst(da, da2);
      Assert.assertTrue(inDelta(da, new double[]{0.5, 4, -30, -2, 27}));
    }
  
    @Test
    public void testAppendZeros() {
      double[] da = {1, 2, 0, -1, -3};
      double[] da2 = {1, 2, 0, -1, -3, 0, 0, 0, 0, 0, 0};
      Assert.assertTrue(inDelta(DoubleArrays.appendZeros(da, 6), da2));
      Assert.assertTrue(inDelta(DoubleArrays.appendZeros(da2, 0), da2));
    }
  
    @Test(expected = IllegalArgumentException.class)
    public void testAppendZerosExc() {
      double[] da = {1, 2, 0, -1, -3};
      DoubleArrays.appendZeros(da, -10);
    }
  
    @Test
    public void testMaxMinValue() {
      double[] da = {1, 2, 0, -1, -3};
      Assert.assertTrue(inDelta(DoubleArrays.max(da), 2));
      Assert.assertTrue(inDelta(DoubleArrays.min(da), -3));
    }
  
    @Test
    public void testMaxMinIndex() {
      double[] da = {1, 2, 0, -1, -3};
      Assert.assertEquals(DoubleArrays.maxIndex(da), 1);
      Assert.assertEquals(DoubleArrays.minIndex(da), 4);
      double[] da2 = {2, 2, 0, -1, -3, 2, -3};
      Assert.assertEquals(DoubleArrays.maxIndex(da2), 0);
      Assert.assertEquals(DoubleArrays.minIndex(da2), 4);
    }
  
    @Test
    public void testSquare() {
      double[] da = {1, 2, 0, -1, -3};
      Assert.assertTrue(inDelta(DoubleArrays.square(da), new double[]{1, 4, 0, 1, 9}));
    }
  
    @Test
    public void testSquaredSum() {
      double[] da = {1, 2, 0, -1, -3};
      Assert.assertTrue(inDelta(DoubleArrays.squaredSum(da), 15));
      double[] da2 = {0, 1, 1, -2, 1};
      Assert.assertTrue(inDelta(DoubleArrays.squaredSumOfDifferences(da, da2), 20));
      Assert
          .assertTrue(inDelta(DoubleArrays.absoluteDifference(da, da2), new double[]{1, 1, 1, 1, 4}));
    }
  
    @Test
    public void testAddToAll() {
      double[] da = {1, 2, 0, -1, -3};
      double[] expected = {2, 3, 1, 0, -2};
      DoubleArrays.addToAll(da, 1);
      Assert.assertTrue(Arrays.equals(expected, da));
    }
  
    @Test
    public void testMean() {
      double[] da = {1, 2, 0, -1, -3};
      Assert.assertTrue(inDelta(DoubleArrays.mean(da), -1d / 5d));
    }
  
    @Test
    public void testInRange() {
      double d = 3;
      double d2 = 2.5;
      double d3 = 7;
      Assert.assertTrue(DoubleArrays.inRange(d, d2, 1));
      Assert.assertFalse(DoubleArrays.inRange(d2, d3, 4));
      Assert.assertTrue(DoubleArrays.inRange(d, d2, 0.5));
    }
  
    @Test
    public void testReverse() {
      double[] da = {1, 3, 7, 2.5, 0};
      double[] da2 = DoubleArrays.reverse(DoubleArrays.reverse(da));
      Assert.assertNotNull(da2);
      Assert.assertEquals(da.length, da2.length);
      Assert.assertTrue(inDelta(da, da2));
    }
  
    @Test
    public void testConvertInt() {
      int[] ia = {1, 3, -1, 0, 9, 12};
      double[] da2 = {1, 3, -1, 0, 9.0, 12.0};
      double[] da = DoubleArrays.convert(ia);
      Assert.assertNotNull(da);
      Assert.assertTrue(inDelta(da, da2));
    }
  
    @Test
    public void testConvert2d() {
      int[][] ia = {{1, 2}, {4, 3}, {-1, 5}};
      double[][] da = {{1, 2}, {4, 3}, {-1, 5}};
      double[][] da2 = DoubleArrays.convert(ia);
      Assert.assertEquals(ia.length, da2.length);
      Assert.assertNotNull(da2);
      int k = 0;
      for (double[] i : da) {
        int j = 0;
        for (double ii : i) {
          Assert.assertEquals(da2[k][j++], ii, 0.0001);
        }
        k++;
      }
    }
  
    @Test
    public void testConvertFloat() {
      float[] fa = {1, 3, -1, 0, 9, 12};
      double[] da2 = {1, 3, -1, 0, 9.0, 12.0};
      double[] da = DoubleArrays.convert(fa);
      Assert.assertNotNull(da);
      Assert.assertTrue(inDelta(da, da2));
    }
  
    @Test
    public void testArrayEqualsInRange() {
      double[] da = {0, 3.5, 7, -2, 19};
      double[] da2 = {0, 4.5, 4, 2, -18};
      Assert.assertTrue(DoubleArrays.arrayEqualsInRange(da, da2, 37));
      Assert.assertFalse(DoubleArrays.arrayEqualsInRange(da, da2, 15));
      Assert.assertTrue(DoubleArrays.arrayEqualsInRange(da, da2, 45));
    }
  
    @Test
    public void testArrayEquals() {
      double[] da = {-1, 0, 3.4, 7};
      double[] da2 = {-1, 0.0, 3.4, 7};
      double[] da3 = {7, 9.0, 12.3, -5.6};
      Assert.assertTrue(DoubleArrays.arrayEquals(da, da2));
      Assert.assertFalse(DoubleArrays.arrayEquals(da2, da3));
    }
  
    @Test
    public void testMultiply() {
      double[] da = {-1, 1.3, 8.2, 10, 90};
      double[] da2 = {-1, 3, 2, 2, -1};
      Assert.assertTrue(inDelta(DoubleArrays.multiply(da, da2), new double[]{1, 3.9, 16.4, 20, -90}));
      DoubleArrays.multiplyToFirst(da, da2);
      Assert.assertTrue(inDelta(da, new double[]{1, 3.9, 16.4, 20, -90}));
    }
  
    @Test
    public void testScale() {
      double[] da = {1, -1, 3.1, 0.0, 0};
      Assert.assertTrue(inDelta(DoubleArrays.scale(da, 0), new double[]{0, 0, 0, 0, 0}));
      Assert.assertTrue(inDelta(DoubleArrays.scale(da, -1), new double[]{-1, 1, -3.1, 0, 0.0}));
      Assert.assertTrue(inDelta(DoubleArrays.scale(da, 4), new double[]{4, -4, 12.4, 0.0, 0.0}));
  
      DoubleArrays.scaleInPlace(da, 4);
      Assert.assertTrue(inDelta(da, new double[]{4, -4, 12.4, 0.0, 0.0}));
      DoubleArrays.scaleInPlace(da, 0);
      Assert.assertTrue(inDelta(da, new double[]{0, 0, 0, 0, 0}));
    }
  
    @Test
    public void testAbsoluteDifference() {
      double[] da = {1, 2, 4.5, -2, 4};
      double[] da2 = {1, 1, 2.5, 5, -15.2};
      Assert.assertTrue(
          inDelta(DoubleArrays.absoluteDifference(da, da2), new double[]{0, 1, 2, 7, 19.2}));
      Assert.assertEquals(DoubleArrays.absoluteSumOfDifferences(da, da2), 29.2, 0.0001);
    }
  
    @Test
    public void testVariance() {
      double[] da = {0, 2, 4};
      Assert.assertEquals(DoubleArrays.variance(da), 4d, 0.0001);
      Assert.assertEquals(DoubleArrays.standardDeviation(da), 2d, 0.0001);
    }
  
    @Test
    public void testContainsNaN() {
      double[] da = {-1, 1, 3, 5, 7, 9, Double.NaN};
      Assert.assertTrue(DoubleArrays.containsNaN(da));
  
      double[] da2 = {-1, 1, 3, 5, 7, 9};
      Assert.assertFalse(DoubleArrays.containsNaN(da2));
    }
  
    @Test
    public void testFloorInPlace() {
      double[] da = {0, -7, 2, 1.1123, -10, -22, 56};
      DoubleArrays.floorInPlace(da, -7);
      Assert.assertTrue(inDelta(da, new double[]{0, -7, 2, 1.1123, -7, -7, 56}));
  
    }
  
    @Test
    public void testNonZeroFloorInPlace() {
      double[] da = {0, -7, 2, 1.1123, -10, -22, 56};
      DoubleArrays.nonZeroFloorInPlace(da, 3);
      Assert.assertTrue(inDelta(da, new double[]{0, 3, 3, 3, 3, 3, 56}));
  
    }
  
    @Test
    public void testNormalizeInPlace() {
      double[] da = {1, 5.6, 2.4, -1, -3.0, 5};
      DoubleArrays.normalizeInPlace(da);
      Assert.assertTrue(inDelta(da, new double[]{0.1, 0.56, 0.24, -0.1, -0.3, 0.5}));
    }
  
    @Test
    public void testValidateArray() {
      double[] da = null;
      try {
        DoubleArrays.validateArray(da);
      } catch (IllegalArgumentException e) {
        Assert.assertTrue(true);
      }
  
      da = new double[0];
      try {
        DoubleArrays.validateArray(da);
      } catch (IllegalArgumentException e) {
        Assert.assertTrue(true);
      }
    }
  
    @Test
    public void testValidateArrays() {
      double[] da1 = {1, 2, 3};
      double[] da2 = null;
      try {
        DoubleArrays.validateArrays(da1, da2);
      } catch (NullPointerException e) {
        Assert.assertTrue(true);
      }
  
      double[] da3 = {5, 6, 2.33, 2};
      try {
        DoubleArrays.validateArrays(da1, da3);
      } catch (IllegalArgumentException e) {
        Assert.assertTrue(true);
      }
    }
  
    @Test
    public void testNormalize16bitLittleEndian() {
      byte[] ba = {0x10, 0x71, 0x18, 0x54};
      double[] da = DoubleArrays.normalize16bitLittleEndian(ba);
      Assert.assertEquals(da[0] * Short.MAX_VALUE, 28944d, 0.0001);
      Assert.assertEquals(da[1] * Short.MAX_VALUE, 21528d, 0.0001);
  
      byte[] ba2 = DoubleArrays.denormalize16BitLittleEndian(da);
      Assert.assertEquals(ba2[0], 0x10);
      Assert.assertEquals(ba2[3], 0x54);
  
      byte[] ba3 = DoubleArrays.denormalizeLittleEndian(da, 16);
      Assert.assertEquals(ba3[0], 0x10);
      Assert.assertEquals(ba3[3], 0x54);
  
      byte[] ba4 = {(byte) 0xCC, (byte) 0xAB};
      da = DoubleArrays.normalize16bitLittleEndian(ba4);
      Assert.assertEquals(da[0] * Short.MIN_VALUE, 21556d, 0.0001);
    }
  
    @Test
    public void testToUnsignedInteger() {
      double[] da = {0.2, -0.4, 0.6};
      int[] ia = DoubleArrays.toUnsignedInteger(da, 6);
      Assert.assertEquals((int) (0.2 * 3.0), ia[0]);
      Assert.assertEquals((int) (-0.4 * 3.0), ia[1]);
    }
  
    @Test(expected = IllegalArgumentException.class)
    public void testValidateArrayExc() {
      double[] da1 = new double[0];
      DoubleArrays.validateArray(da1);
    }
  
    @Test(expected = NullPointerException.class)
    public void testValidateArraysNullExc() {
      double[] da1 = null;
      double[] da2 = null;
      DoubleArrays.validateArrays(da1, da2);
    }
  
    @Test(expected = IllegalArgumentException.class)
    public void testValidateArraysArgExc() {
      double[] da1 = new double[2];
      double[] da2 = new double[3];
      DoubleArrays.validateArrays(da1, da2);
    }
  
    @Test(expected = IllegalArgumentException.class)
    public void testNormalize16bitExc() {
      byte[] ba = {-10, 45, 120};
      DoubleArrays.normalize16bitLittleEndian(ba);
    }
  
    @Test
    public void testSerialization1D() throws IOException {
      serialization1D(new double[]{0.2, -0.4, 0.6});
      serialization1D(new double[]{0.256});
      serialization1D(new double[]{});
    }
  
    @Test
    public void testSerialization2D() throws IOException {
      serialization2D(new double[][]{{0.2}, {-0.4}, {0.6}});
      serialization2D(new double[][]{{0.2, 1}, {-0.4, 2}, {0.6, 3}});
      serialization2D(new double[][]{{0.2, 1}, {-0.4}, {0.6, 3, 6}});
      serialization2D(new double[][]{{}, {}, {0.6, 3, 6}});
      serialization2D(new double[][]{{}, {}, {}});
    }
  
    private void serialization1D(double[] da) throws IOException {
      File f = File.createTempFile("blah", "foo");
      f.deleteOnExit();
      try (DataOutputStream dos = new DataOutputStream(new FileOutputStream(f))) {
        DoubleArrays.serialize(dos, da);
      }
  
      try (DataInputStream dis = new DataInputStream(new FileInputStream(f))) {
        double[] read = DoubleArrays.deserialize(dis);
        Assert.assertTrue(DoubleArrays.arrayEquals(da, read));
      }
    }
  
    private void serialization2D(double[][] da) throws IOException {
      File f = File.createTempFile("blah", "foo");
      f.deleteOnExit();
      try (DataOutputStream dos = new DataOutputStream(new FileOutputStream(f))) {
        DoubleArrays.serialize(dos, da);
      }
  
      try (DataInputStream dis = new DataInputStream(new FileInputStream(f))) {
        double[][] read = DoubleArrays.deserialize2d(dis);
        for (int i = 0; i < read.length; i++) {
          Assert.assertTrue(DoubleArrays.arrayEquals(da[i], read[i]));
        }
      }
    }
  }
  