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