Skip to content

Commit cfb7dce

Browse files
committed
Add toFloatArray() and toDoubleArray() converter
refs #30
1 parent b146335 commit cfb7dce

File tree

5 files changed

+217
-1
lines changed

5 files changed

+217
-1
lines changed

CHANGELOG

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
* add `unsecureRandom()` constructor which creates random for e.g. tests or deterministic randoms
66
* adds overwrite method to Bytes (thx @JadePaukkunen)
77
* make project OSGi compatible #36
8+
* add `toFloatArray()` converter #30
9+
* add `toDoubleArray()` converter #30
810

911
## v1.0.0
1012

src/main/java/at/favre/lib/bytes/Bytes.java

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1956,6 +1956,25 @@ public float toFloat() {
19561956
return internalBuffer().getFloat();
19571957
}
19581958

1959+
/**
1960+
* Converts the internal byte array to an float array, that is, every 4 bytes will be packed into a single float.
1961+
* <p>
1962+
* E.g. 4 bytes will be packed to a length 1 float array:
1963+
* <pre>
1964+
* [b1, b2, b3, b4] = [float1]
1965+
* </pre>
1966+
* <p>
1967+
* This conversion respects the internal byte order. Will only work if all bytes can be directly mapped to float,
1968+
* which means the byte array length must be dividable by 4 without rest.
1969+
*
1970+
* @return new float[] instance representing this byte array
1971+
* @throws IllegalArgumentException if internal byte length mod 4 != 0
1972+
*/
1973+
public float[] toFloatArray() {
1974+
Util.Validation.checkModLength(length(), 4, "creating an float array");
1975+
return Util.Converter.toFloatArray(internalArray(), byteOrder);
1976+
}
1977+
19591978
/**
19601979
* If the underlying byte array is exactly 8 byte / 64 bit long, return the
19611980
* representation for a Java double value. The output is dependent on the set {@link #byteOrder()}.
@@ -1969,6 +1988,25 @@ public double toDouble() {
19691988
return internalBuffer().getDouble();
19701989
}
19711990

1991+
/**
1992+
* Converts the internal byte array to an double array, that is, every 8 bytes will be packed into a single double.
1993+
* <p>
1994+
* E.g. 8 bytes will be packed to a length 1 double array:
1995+
* <pre>
1996+
* [b1, b2, b3, b4, b5, b6, b7, b8] = [double1]
1997+
* </pre>
1998+
* <p>
1999+
* This conversion respects the internal byte order. Will only work if all bytes can be directly mapped to double,
2000+
* which means the byte array length must be dividable by 8 without rest.
2001+
*
2002+
* @return new double[] instance representing this byte array
2003+
* @throws IllegalArgumentException if internal byte length mod 8 != 0
2004+
*/
2005+
public double[] toDoubleArray() {
2006+
Util.Validation.checkModLength(length(), 8, "creating an double array");
2007+
return Util.Converter.toDoubleArray(internalArray(), byteOrder);
2008+
}
2009+
19722010
/**
19732011
* Decodes the internal byte array to UTF-8 char array.
19742012
* This implementation will not internally create a {@link String}.

src/main/java/at/favre/lib/bytes/Util.java

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -719,6 +719,60 @@ static long[] toLongArray(byte[] bytes, ByteOrder byteOrder) {
719719
return array;
720720
}
721721

722+
/**
723+
* Converts the byte array to an float array. This will spread 4 bytes into a single float:
724+
*
725+
* <pre>
726+
* [b1, b2, b3, b4] = [float1]
727+
* </pre>
728+
*
729+
* <p>
730+
* <strong>Analysis</strong>
731+
* <ul>
732+
* <li>Time Complexity: <code>O(n)</code></li>
733+
* <li>Space Complexity: <code>O(n)</code></li>
734+
* <li>Alters Parameters: <code>false</code></li>
735+
* </ul>
736+
* </p>
737+
*
738+
* @param bytes to convert to float array, must be % 4 == 0 to work correctly
739+
* @param byteOrder of the byte array
740+
* @return float array
741+
*/
742+
static float[] toFloatArray(byte[] bytes, ByteOrder byteOrder) {
743+
FloatBuffer buffer = ByteBuffer.wrap(bytes).order(byteOrder).asFloatBuffer();
744+
float[] array = new float[buffer.remaining()];
745+
buffer.get(array);
746+
return array;
747+
}
748+
749+
/**
750+
* Converts the byte array to an double array. This will spread 8 bytes into a single double:
751+
*
752+
* <pre>
753+
* [b1, b2, b3, b4, b5, b6, b7, b8] = [double1]
754+
* </pre>
755+
*
756+
* <p>
757+
* <strong>Analysis</strong>
758+
* <ul>
759+
* <li>Time Complexity: <code>O(n)</code></li>
760+
* <li>Space Complexity: <code>O(n)</code></li>
761+
* <li>Alters Parameters: <code>false</code></li>
762+
* </ul>
763+
* </p>
764+
*
765+
* @param bytes to convert to double array, must be % 8 == 0 to work correctly
766+
* @param byteOrder of the byte array
767+
* @return double array
768+
*/
769+
static double[] toDoubleArray(byte[] bytes, ByteOrder byteOrder) {
770+
DoubleBuffer buffer = ByteBuffer.wrap(bytes).order(byteOrder).asDoubleBuffer();
771+
double[] array = new double[buffer.remaining()];
772+
buffer.get(array);
773+
return array;
774+
}
775+
722776
/**
723777
* Convert UUID to a newly generated 16 byte long array representation. Puts the 8 byte most significant bits and
724778
* 8 byte least significant bits into an byte array.

src/test/java/at/favre/lib/bytes/BytesToConvertOtherTypesTest.java

Lines changed: 85 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,6 @@ public void testToLongEmptyArray() {
307307
assertArrayEquals(new long[0], Bytes.empty().toLongArray());
308308
}
309309

310-
311310
@Test
312311
public void testToLongArrayLittleEndian() {
313312
assertArrayEquals(new long[]{1}, Bytes.wrap(new byte[]{1, 0, 0, 0, 0, 0, 0, 0}, ByteOrder.LITTLE_ENDIAN).toLongArray());
@@ -322,4 +321,89 @@ public void testToLongArrayLittleEndian() {
322321
1, 1, 1, 0, 0, 0, 1, 0,
323322
1, 0, 0, 0, 0, 0, 0, 0}, ByteOrder.LITTLE_ENDIAN).toLongArray());
324323
}
324+
325+
@Test
326+
public void testToFloatArray() {
327+
assertArrayEquals(new float[]{1.4E-45f}, Bytes.wrap(new byte[]{0, 0, 0, 1}).toFloatArray(), 0.01f);
328+
assertArrayEquals(new float[]{3.6E-43f}, Bytes.wrap(new byte[]{0, 0, 1, 1}).toFloatArray(), 0.01f);
329+
assertArrayEquals(new float[]{9.2196E-41f}, Bytes.wrap(new byte[]{0, 1, 1, 1}).toFloatArray(), 0.01f);
330+
assertArrayEquals(new float[]{2.3694278E-38f}, Bytes.wrap(new byte[]{1, 1, 1, 1}).toFloatArray(), 0.01f);
331+
assertArrayEquals(new float[]{1.897368E-18f}, Bytes.wrap(new byte[]{34, 12, 0, 69}).toFloatArray(), 0.01f);
332+
assertArrayEquals(new float[]{1.22888184E8f}, Bytes.wrap(new byte[]{76, (byte) 234, 99, (byte) 255}).toFloatArray(), 0.01f);
333+
334+
assertArrayEquals(new float[]{1.4E-45f, 1.4E-45f}, Bytes.wrap(new byte[]{0, 0, 0, 1, 0, 0, 0, 1}).toFloatArray(), 0.01f);
335+
assertArrayEquals(new float[]{3.6E-43f, 1.4E-45f}, Bytes.wrap(new byte[]{0, 0, 1, 1, 0, 0, 0, 1}).toFloatArray(), 0.01f);
336+
assertArrayEquals(new float[]{3.6E-43f, 9.2196E-41f, 1.4E-45f}, Bytes.wrap(new byte[]{0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1}).toFloatArray(), 0.01f);
337+
}
338+
339+
@Test(expected = IllegalArgumentException.class)
340+
public void testToFloatArrayNotMod4Was5Byte() {
341+
Bytes.wrap(new byte[]{1, 0, 0, 0, 1}).toFloatArray();
342+
}
343+
344+
@Test(expected = IllegalArgumentException.class)
345+
public void testToFloatArrayNotMod4Only3Byte() {
346+
Bytes.wrap(new byte[]{0, 0, 1}).toFloatArray();
347+
}
348+
349+
@Test
350+
public void testToFloatEmptyArray() {
351+
assertArrayEquals(new float[0], Bytes.empty().toFloatArray(), 0.01f);
352+
}
353+
354+
@Test
355+
public void testToFloatArrayLittleEndian() {
356+
assertArrayEquals(new float[]{1.4E-45f}, Bytes.wrap(new byte[]{1, 0, 0, 0}, ByteOrder.LITTLE_ENDIAN).toFloatArray(), 0.01f);
357+
assertArrayEquals(new float[]{3.6E-43f}, Bytes.wrap(new byte[]{1, 1, 0, 0}, ByteOrder.LITTLE_ENDIAN).toFloatArray(), 0.01f);
358+
assertArrayEquals(new float[]{1.22888184E8f}, Bytes.wrap(new byte[]{(byte) 255, 99, (byte) 234, 76}, ByteOrder.LITTLE_ENDIAN).toFloatArray(), 0.01f);
359+
360+
assertArrayEquals(new float[]{1.4E-45f, 1.4E-45f}, Bytes.wrap(new byte[]{1, 0, 0, 0, 1, 0, 0, 0}, ByteOrder.LITTLE_ENDIAN).toFloatArray(), 0.01f);
361+
assertArrayEquals(new float[]{3.6E-43f, 1.4E-45f}, Bytes.wrap(new byte[]{1, 1, 0, 0, 1, 0, 0, 0}, ByteOrder.LITTLE_ENDIAN).toFloatArray(), 0.01f);
362+
assertArrayEquals(new float[]{3.6E-43f, 9.2196E-41f, 1.4E-45f}, Bytes.wrap(new byte[]{1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0}, ByteOrder.LITTLE_ENDIAN).toFloatArray(), 0.01f);
363+
}
364+
365+
@Test
366+
public void testToDoubleArray() {
367+
assertArrayEquals(new double[]{1.4E-45}, Bytes.wrap(new byte[]{0, 0, 0, 0, 0, 0, 0, 1}).toDoubleArray(), 0.01);
368+
assertArrayEquals(new double[]{3.6E-43}, Bytes.wrap(new byte[]{0, 0, 0, 0, 0, 0, 1, 1}).toDoubleArray(), 0.01);
369+
assertArrayEquals(new double[]{4.228405109821336E-86}, Bytes.wrap(new byte[]{46, 53, 7, 98, 34, 12, 0, 69}).toDoubleArray(), 0.01);
370+
assertArrayEquals(new double[]{-2.385279556059394E-168}, Bytes.wrap(new byte[]{(byte) 157, 34, 1, 0, 76, (byte) 234, 99, (byte) 255}).toDoubleArray(), 0.01);
371+
372+
assertArrayEquals(new double[]{1.4E-45, 1.4E-45}, Bytes.wrap(new byte[]{0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1}).toDoubleArray(), 0.01);
373+
assertArrayEquals(new double[]{3.6E-43, 1.4E-45}, Bytes.wrap(new byte[]{0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1}).toDoubleArray(), 0.01);
374+
assertArrayEquals(new double[]{5.43230922614E-312, 1.39067116189206E-309, 1.4E-45}, Bytes.wrap(new byte[]{
375+
0, 0, 1, 0, 0, 0, 1, 1,
376+
0, 1, 0, 0, 0, 1, 1, 1,
377+
0, 0, 0, 0, 0, 0, 0, 1}).toDoubleArray(), 0.01);
378+
}
379+
380+
@Test(expected = IllegalArgumentException.class)
381+
public void testToDoubleArrayNotMod4Was9Byte() {
382+
Bytes.wrap(new byte[]{0, 0, 0, 0, 0, 0, 0, 0, 1}).toDoubleArray();
383+
}
384+
385+
@Test(expected = IllegalArgumentException.class)
386+
public void testToDoubleArrayNotMod4Only7Byte() {
387+
Bytes.wrap(new byte[]{0, 0, 0, 0, 0, 0, 1}).toDoubleArray();
388+
}
389+
390+
@Test
391+
public void testToDoubleEmptyArray() {
392+
assertArrayEquals(new double[0], Bytes.empty().toDoubleArray(), 0.01);
393+
}
394+
395+
@Test
396+
public void testToDoubleArrayLittleEndian() {
397+
assertArrayEquals(new double[]{1.4E-45}, Bytes.wrap(new byte[]{1, 0, 0, 0, 0, 0, 0, 0}, ByteOrder.LITTLE_ENDIAN).toDoubleArray(), 0.01);
398+
assertArrayEquals(new double[]{3.6E-43}, Bytes.wrap(new byte[]{1, 1, 0, 0, 0, 0, 0, 0}, ByteOrder.LITTLE_ENDIAN).toDoubleArray(), 0.01);
399+
assertArrayEquals(new double[]{4.228405109821336E-86}, Bytes.wrap(new byte[]{69, 0, 12, 34, 98, 7, 53, 46}, ByteOrder.LITTLE_ENDIAN).toDoubleArray(), 0.01);
400+
assertArrayEquals(new double[]{-2.385279556059394E-168}, Bytes.wrap(new byte[]{(byte) 255, 99, (byte) 234, 76, 0, 1, 34, (byte) 157}, ByteOrder.LITTLE_ENDIAN).toDoubleArray(), 0.01);
401+
402+
assertArrayEquals(new double[]{1.4E-45, 1.4E-45}, Bytes.wrap(new byte[]{1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0}, ByteOrder.LITTLE_ENDIAN).toDoubleArray(), 0.01);
403+
assertArrayEquals(new double[]{3.6E-43f, 1.4E-45}, Bytes.wrap(new byte[]{1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0}, ByteOrder.LITTLE_ENDIAN).toDoubleArray(), 0.01);
404+
assertArrayEquals(new double[]{5.43230922614E-312, 1.39067116189206E-309, 1.4E-45}, Bytes.wrap(new byte[]{
405+
1, 1, 0, 0, 0, 1, 0, 0,
406+
1, 1, 1, 0, 0, 0, 1, 0,
407+
1, 0, 0, 0, 0, 0, 0, 0}, ByteOrder.LITTLE_ENDIAN).toDoubleArray(), 0.01);
408+
}
325409
}

src/test/java/at/favre/lib/bytes/UtilConverterTest.java

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,4 +155,42 @@ public void testToLongArray() {
155155
assertArrayEquals(new long[0], Util.Converter.toLongArray(new byte[0], ByteOrder.LITTLE_ENDIAN));
156156
assertArrayEquals(new long[0], Util.Converter.toLongArray(new byte[0], ByteOrder.BIG_ENDIAN));
157157
}
158+
159+
@Test
160+
public void testToFloatArray() {
161+
assertArrayEquals(new float[]{1.4E-45f}, Util.Converter.toFloatArray(new byte[]{0, 0, 0, 1}, ByteOrder.BIG_ENDIAN), 0.01f);
162+
assertArrayEquals(new float[]{3.6E-43f}, Util.Converter.toFloatArray(new byte[]{0, 0, 1, 1}, ByteOrder.BIG_ENDIAN), 0.01f);
163+
164+
assertArrayEquals(new float[]{1.4E-45f}, Util.Converter.toFloatArray(new byte[]{1, 0, 0, 0}, ByteOrder.LITTLE_ENDIAN), 0.01f);
165+
assertArrayEquals(new float[]{3.6E-43f}, Util.Converter.toFloatArray(new byte[]{1, 1, 0, 0}, ByteOrder.LITTLE_ENDIAN), 0.01f);
166+
167+
assertArrayEquals(new float[]{2.3694278E-38f}, Util.Converter.toFloatArray(new byte[]{1, 1, 1, 1}, ByteOrder.BIG_ENDIAN), 0.01f);
168+
assertArrayEquals(new float[]{1.897368E-18f}, Util.Converter.toFloatArray(new byte[]{34, 12, 0, 69}, ByteOrder.BIG_ENDIAN), 0.01f);
169+
assertArrayEquals(new float[]{1.22888184E8f}, Util.Converter.toFloatArray(new byte[]{76, (byte) 234, 99, (byte) 255}, ByteOrder.BIG_ENDIAN), 0.01f);
170+
assertArrayEquals(new float[]{3.6E-43f, 9.2196E-41f, 1.4E-45f}, Util.Converter.toFloatArray(new byte[]{0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1}, ByteOrder.BIG_ENDIAN), 0.01f);
171+
172+
assertArrayEquals(new float[]{1.22888184E8f}, Util.Converter.toFloatArray(new byte[]{(byte) 255, 99, (byte) 234, 76}, ByteOrder.LITTLE_ENDIAN), 0.01f);
173+
assertArrayEquals(new float[]{3.6E-43f, 9.2196E-41f, 1.4E-45f}, Util.Converter.toFloatArray(new byte[]{1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0}, ByteOrder.LITTLE_ENDIAN), 0.01f);
174+
175+
assertArrayEquals(new float[0], Util.Converter.toFloatArray(new byte[0], ByteOrder.LITTLE_ENDIAN), 0.01f);
176+
assertArrayEquals(new float[0], Util.Converter.toFloatArray(new byte[0], ByteOrder.BIG_ENDIAN), 0.01f);
177+
}
178+
179+
@Test
180+
public void testToDoubleArray() {
181+
assertArrayEquals(new double[]{1.4E-45}, Util.Converter.toDoubleArray(new byte[]{0, 0, 0, 0, 0, 0, 0, 1}, ByteOrder.BIG_ENDIAN), 0.01);
182+
assertArrayEquals(new double[]{3.6E-43}, Util.Converter.toDoubleArray(new byte[]{0, 0, 0, 0, 0, 0, 1, 1}, ByteOrder.BIG_ENDIAN), 0.01);
183+
184+
assertArrayEquals(new double[]{1.4E-45}, Util.Converter.toDoubleArray(new byte[]{1, 0, 0, 0, 0, 0, 0, 0}, ByteOrder.LITTLE_ENDIAN), 0.01);
185+
assertArrayEquals(new double[]{3.6E-43}, Util.Converter.toDoubleArray(new byte[]{1, 1, 0, 0, 0, 0, 0, 0}, ByteOrder.LITTLE_ENDIAN), 0.01);
186+
187+
assertArrayEquals(new double[]{-2.385279556059394E-168}, Util.Converter.toDoubleArray(new byte[]{(byte) 157, 34, 1, 0, 76, (byte) 234, 99, (byte) 255}, ByteOrder.BIG_ENDIAN), 0.01);
188+
assertArrayEquals(new double[]{-2.385279556059394E-168}, Util.Converter.toDoubleArray(new byte[]{(byte) 255, 99, (byte) 234, 76, 0, 1, 34, (byte) 157}, ByteOrder.LITTLE_ENDIAN), 0.01);
189+
190+
assertArrayEquals(new double[]{1.27E-321, 4.9E-324}, Util.Converter.toDoubleArray(new byte[]{0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1}, ByteOrder.BIG_ENDIAN), 0.01);
191+
assertArrayEquals(new double[]{1.27E-321, 4.9E-324}, Util.Converter.toDoubleArray(new byte[]{1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0}, ByteOrder.LITTLE_ENDIAN), 0.01);
192+
193+
assertArrayEquals(new double[0], Util.Converter.toDoubleArray(new byte[0], ByteOrder.LITTLE_ENDIAN), 0.01);
194+
assertArrayEquals(new double[0], Util.Converter.toDoubleArray(new byte[0], ByteOrder.BIG_ENDIAN), 0.01);
195+
}
158196
}

0 commit comments

Comments
 (0)