diff --git a/README.md b/README.md
index 1037d27..96e0606 100644
--- a/README.md
+++ b/README.md
@@ -58,6 +58,11 @@ Licensed under the Apache 2.0 License
#### Encoders / decoders
+##### Base32
+
+* Binary-to-text encoding. Based on charset [variant](https://www.crockford.com/base32.html) of Douglas Crockford,
+ without check
+
##### Base58
* Binary-to-text encoding. Character set includes all uppercase and lowercase letters except for "0", "O", "I", and "l"
@@ -82,7 +87,7 @@ Just add this to your **pom.xml**
com.hijackermax
- utils
- 0.0.6
+ utils
+ 0.0.7
```
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 1fea3dd..486e352 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,7 +6,7 @@
com.hijackermax
utils
- 0.0.6
+ 0.0.7
utils
A set of utils that can help in app development
diff --git a/src/main/java/com/hijackermax/utils/encoders/Base122.java b/src/main/java/com/hijackermax/utils/encoders/Base122.java
index 969d63c..2ee6dc0 100644
--- a/src/main/java/com/hijackermax/utils/encoders/Base122.java
+++ b/src/main/java/com/hijackermax/utils/encoders/Base122.java
@@ -9,8 +9,11 @@
import java.util.Objects;
import java.util.function.Consumer;
+import static com.hijackermax.utils.lang.MathUtils.add;
+import static com.hijackermax.utils.lang.MathUtils.subtract;
+
/**
- * Binary-to-text encoding that is more space-efficient than base64
+ * Binary-to-text encoding that is more space-efficient than base64, based on idea of Kevin Albertson
*
* @since 0.0.6
*/
@@ -61,20 +64,20 @@ public static byte[] decode(String source) {
if (StringUtils.isBlank(source)) {
return new byte[0];
}
- ByteArrayOutputStream outputStream = new ByteArrayOutputStream(calculateDecodedBufferSize(source.length()));
- Tuple dataPointers = new Tuple<>((byte) 0, (byte) 0);
+ ByteArrayOutputStream result = new ByteArrayOutputStream(calculateDecodedBufferSize(source.length()));
+ Tuple dataPointers = new Tuple<>(0, 0);
for (char nextChar : source.toCharArray()) {
if (nextChar > 0x7F) {
int illegalIndex = (nextChar >>> 8) & 0x07;
if (illegalIndex != K_SHORTENED) {
- pushPartition(INVALID_CHARS[illegalIndex] << 1, dataPointers, outputStream::write);
+ pushPartition(INVALID_CHARS[illegalIndex] << 1, dataPointers, result::write);
}
- pushPartition((nextChar & 0x7F) << 1, dataPointers, outputStream::write);
+ pushPartition((nextChar & 0x7F) << 1, dataPointers, result::write);
} else {
- pushPartition(nextChar << 1, dataPointers, outputStream::write);
+ pushPartition(nextChar << 1, dataPointers, result::write);
}
}
- return outputStream.toByteArray();
+ return result.toByteArray();
}
private static byte nextPartition(byte[] data, int length, Tuple dataPointers) {
@@ -83,12 +86,12 @@ private static byte nextPartition(byte[] data, int length, Tuple>> dataPointers.getValue()) & (data[dataPointers.getKey()] & 0xFF))
<< dataPointers.getValue()) >>> 1;
- dataPointers.modifyValue(v -> v + 7);
+ dataPointers.modifyValue(add(7));
if (dataPointers.getValue() < 8) {
return (byte) firstPart;
}
- dataPointers.modifyValue(v -> v - 8);
- dataPointers.modifyKey(k -> k + 1);
+ dataPointers.modifyValue(subtract(8));
+ dataPointers.modifyKey(add(1));
if (dataPointers.getKey() >= length) {
return (byte) firstPart;
}
@@ -97,13 +100,13 @@ private static byte nextPartition(byte[] data, int length, Tuple dataPointers, Consumer valueConsumer) {
- dataPointers.modifyKey(k -> (byte) (k | (nextValue >>> dataPointers.getValue())));
- dataPointers.modifyValue(v -> (byte) (v + 7));
+ private static void pushPartition(int nextValue, Tuple dataPointers, Consumer valueConsumer) {
+ dataPointers.modifyKey(k -> k | (nextValue >>> dataPointers.getValue()));
+ dataPointers.modifyValue(add(7));
if (dataPointers.getValue() >= 8) {
- valueConsumer.accept(dataPointers.getKey());
- dataPointers.modifyValue(v -> (byte) (v - 8));
- dataPointers.setKey((byte) (nextValue << (7 - dataPointers.getValue()) & 0xFF));
+ valueConsumer.accept((byte) (dataPointers.getKey() & 0xFF));
+ dataPointers.modifyValue(subtract(8));
+ dataPointers.setKey(nextValue << (7 - dataPointers.getValue()) & 0xFF);
}
}
diff --git a/src/main/java/com/hijackermax/utils/encoders/Base32.java b/src/main/java/com/hijackermax/utils/encoders/Base32.java
new file mode 100644
index 0000000..958be2c
--- /dev/null
+++ b/src/main/java/com/hijackermax/utils/encoders/Base32.java
@@ -0,0 +1,114 @@
+package com.hijackermax.utils.encoders;
+
+import com.hijackermax.utils.entities.Tuple;
+import com.hijackermax.utils.lang.ObjectUtils;
+import com.hijackermax.utils.lang.StringUtils;
+
+import java.io.ByteArrayOutputStream;
+import java.util.Arrays;
+import java.util.Map;
+import java.util.Objects;
+import java.util.function.Consumer;
+
+import static com.hijackermax.utils.lang.MathUtils.add;
+import static com.hijackermax.utils.lang.MathUtils.subtract;
+
+/**
+ * Binary-to-text encoding based on variant of Douglas Crockford, without check
+ *
+ * @since 0.0.7
+ */
+public final class Base32 {
+ private static final char[] CHARSET = "0123456789ABCDEFGHJKMNPQRSTVWXYZ".toCharArray();
+ private static final byte[] IGNORED_CHARS = {0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x20, 0x2D};
+ private static final Map ALIASES = Map.of('O', 0, 'I', 1, 'L', 1);
+ private static final byte STOP_BYTE = (byte) 0x5B;
+
+ private Base32() {
+ }
+
+ /**
+ * Encodes provided byte array to Base32 String {@link String}
+ *
+ * @param source byte array
+ * @return encoded {@link String}
+ * @since 0.0.7
+ */
+ public static String encode(byte[] source) {
+ int dataLength = Objects.requireNonNull(source).length;
+ StringBuilder result = new StringBuilder(calculateEncodeBufferSize(dataLength));
+ Tuple pointers = new Tuple<>(0, 0);
+ for (byte partition = nextPartition(source, pointers); STOP_BYTE != partition; partition = nextPartition(source, pointers)) {
+ result.append(CHARSET[partition]);
+ }
+ return result.toString();
+ }
+
+
+ /**
+ * Decodes provided {@link String} to byte array
+ *
+ * @param source {@link String}
+ * @return decoded byte array
+ * @throws IllegalArgumentException if provided string is not base32 encoded
+ * @since 0.0.7
+ */
+ public static byte[] decode(String source) {
+ if (StringUtils.isBlank(source)) {
+ return new byte[0];
+ }
+ ByteArrayOutputStream result = new ByteArrayOutputStream(calculateDecodedBufferSize(source.length()));
+ Tuple dataHolder = new Tuple<>(0, 0);
+ for (char nextChar : source.toCharArray()) {
+ if (0 <= Arrays.binarySearch(IGNORED_CHARS, (byte) nextChar)) {
+ continue;
+ }
+ char upperCaseChar = Character.toUpperCase(nextChar);
+ int idx = Arrays.binarySearch(CHARSET, upperCaseChar);
+ int partition = idx >= 0 ? idx : ObjectUtils.valueOrDefault(ALIASES.get(upperCaseChar), -1);
+ if (0 > partition) {
+ throw new IllegalArgumentException("Provided source string is not Base32 encoded");
+ }
+ pushPartition(partition << 3, dataHolder, result::write);
+ }
+ return result.toByteArray();
+ }
+
+ private static byte nextPartition(byte[] data, Tuple pointers) {
+ if (pointers.getKey() >= data.length) {
+ return STOP_BYTE;
+ }
+ int firstPart = (((0xFE >>> pointers.getValue()) & (data[pointers.getKey()] & 0xFF))
+ << pointers.getValue()) >>> 3;
+ pointers.modifyValue(add(5));
+ if (pointers.getValue() < 8) {
+ return (byte) firstPart;
+ }
+ pointers.modifyValue(subtract(8));
+ pointers.modifyKey(add(1));
+ if (pointers.getKey() >= data.length) {
+ return (byte) firstPart;
+ }
+ int secondPart = (((0xFF00 >>> pointers.getValue()) & (data[pointers.getKey()] & 0xFF)) & 0xFF)
+ >>> 8 - pointers.getValue();
+ return (byte) (firstPart | secondPart);
+ }
+
+ private static void pushPartition(int nextValue, Tuple dataHolder, Consumer valueConsumer) {
+ dataHolder.modifyValue(k -> k | (nextValue >> dataHolder.getKey()));
+ dataHolder.modifyKey(add(5));
+ if (dataHolder.getKey() >= 8) {
+ valueConsumer.accept((byte) (dataHolder.getValue() & 0xFF));
+ dataHolder.modifyKey(subtract(8));
+ dataHolder.setValue(nextValue << (5 - dataHolder.getKey()) & 0xFF);
+ }
+ }
+
+ private static int calculateEncodeBufferSize(int byteArrayLength) {
+ return ((byteArrayLength * 8) / 5) + 7;
+ }
+
+ private static int calculateDecodedBufferSize(int stringLength) {
+ return (stringLength * 5) / 8;
+ }
+}
diff --git a/src/main/java/com/hijackermax/utils/encoders/Base58.java b/src/main/java/com/hijackermax/utils/encoders/Base58.java
index 1345c65..3c92396 100644
--- a/src/main/java/com/hijackermax/utils/encoders/Base58.java
+++ b/src/main/java/com/hijackermax/utils/encoders/Base58.java
@@ -46,7 +46,7 @@ public static String encode(byte[] source) {
if (isLeadingZero) {
boolean isByteZero = 0 == nextByte;
if (isByteZero) {
- result.insert(0, (char) 0x49);
+ result.insert(0, (char) 0x31);
}
isLeadingZero = isByteZero;
}
@@ -77,7 +77,7 @@ public static byte[] decode(String source) {
throw new IllegalArgumentException("Provided source string is not Base58 encoded");
}
if (isLeadingOne) {
- boolean isCharOne = 0x49 == nextChar;
+ boolean isCharOne = 0x31 == nextChar;
if (isCharOne) {
result.write(0x00);
}
@@ -92,10 +92,10 @@ public static byte[] decode(String source) {
}
private static int calculateEncodeBufferSize(int byteArrayLength) {
- return byteArrayLength * 7 / 5;
+ return byteArrayLength * 8 / 6;
}
private static int calculateDecodedBufferSize(int stringLength) {
- return stringLength * 5 / 7;
+ return stringLength * 6 / 8;
}
}
diff --git a/src/main/java/com/hijackermax/utils/encoders/Base85.java b/src/main/java/com/hijackermax/utils/encoders/Base85.java
index 46b7efa..78423c6 100644
--- a/src/main/java/com/hijackermax/utils/encoders/Base85.java
+++ b/src/main/java/com/hijackermax/utils/encoders/Base85.java
@@ -13,9 +13,9 @@
* @since 0.0.6
*/
public final class Base85 {
- private static final int ASCII_START_IDX = 0x21;
+ private static final int CHAR_START_IDX = 0x21;
private static final int[] POWERS_85 = {52200625, 614125, 7225, 85, 1};
- private static final byte[] IGNORED_ASCII = {0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x20};
+ private static final byte[] IGNORED_CHARS = {0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x20};
private Base85() {
}
@@ -58,7 +58,7 @@ public static byte[] decode(String source) {
int paginationIdx = 0;
for (int idx = 0; idx < sourceBytes.length; idx++) {
byte nextByte = sourceBytes[idx];
- if (0 <= Arrays.binarySearch(IGNORED_ASCII, nextByte)) {
+ if (0 <= Arrays.binarySearch(IGNORED_CHARS, nextByte)) {
continue;
}
boolean isZeroPlaceholder = 0x7A == nextByte;
@@ -69,7 +69,7 @@ public static byte[] decode(String source) {
}
if (isZeroPlaceholder) {
while (paginationIdx < 5) {
- pagination[paginationIdx++] = ASCII_START_IDX;
+ pagination[paginationIdx++] = CHAR_START_IDX;
}
} else {
pagination[paginationIdx++] = nextByte;
@@ -102,7 +102,7 @@ private static byte[] encodePartition(byte[] pagination, int actualBytes) {
int encodedSize = actualBytes + 1;
byte[] encodedPartition = new byte[encodedSize];
for (int idx = 0; idx < encodedSize; idx++) {
- encodedPartition[idx] = (byte) ((unsignedInt / POWERS_85[idx]) + ASCII_START_IDX);
+ encodedPartition[idx] = (byte) ((unsignedInt / POWERS_85[idx]) + CHAR_START_IDX);
unsignedInt %= POWERS_85[idx];
}
return encodedPartition;
@@ -111,7 +111,7 @@ private static byte[] encodePartition(byte[] pagination, int actualBytes) {
private static byte[] decodePartition(byte[] partition) {
int value = 0;
for (int idx = 0; idx < 5; idx++) {
- value += (partition[idx] - ASCII_START_IDX) * POWERS_85[idx];
+ value += (partition[idx] - CHAR_START_IDX) * POWERS_85[idx];
}
return new byte[]{(byte) (value >>> 24), (byte) (value >>> 16), (byte) (value >>> 8), (byte) value};
}
diff --git a/src/main/java/com/hijackermax/utils/lang/MathUtils.java b/src/main/java/com/hijackermax/utils/lang/MathUtils.java
index 2a08bca..c3d1c7d 100644
--- a/src/main/java/com/hijackermax/utils/lang/MathUtils.java
+++ b/src/main/java/com/hijackermax/utils/lang/MathUtils.java
@@ -1,5 +1,8 @@
package com.hijackermax.utils.lang;
+import java.util.function.Function;
+import java.util.function.UnaryOperator;
+
/**
* Set of utility methods that can help with math operations
*/
@@ -233,4 +236,92 @@ public static double absMultiply(double a, double b) {
public static float absMultiply(float a, float b) {
return Math.abs(a * b);
}
+
+ /**
+ * Provides {@link UnaryOperator} which subtracts provided value from {@link Function} argument
+ *
+ * @param b subtrahend operand
+ * @return {@link UnaryOperator} which subtracts provided value from {@link Function} argument
+ * @since 0.0.7
+ */
+ public static UnaryOperator subtract(int b) {
+ return a -> subtract(a, b);
+ }
+
+ /**
+ * Provides {@link UnaryOperator} which subtracts provided value from {@link Function} argument
+ *
+ * @param b subtrahend operand
+ * @return {@link UnaryOperator} which subtracts provided value from {@link Function} argument
+ * @since 0.0.7
+ */
+ public static UnaryOperator subtract(long b) {
+ return a -> subtract(a, b);
+ }
+
+ /**
+ * Provides {@link UnaryOperator} which subtracts provided value from {@link Function} argument
+ *
+ * @param b subtrahend operand
+ * @return {@link UnaryOperator} which subtracts provided value from {@link Function} argument
+ * @since 0.0.7
+ */
+ public static UnaryOperator subtract(float b) {
+ return a -> subtract(a, b);
+ }
+
+ /**
+ * Provides {@link UnaryOperator} which subtracts provided value from {@link Function} argument
+ *
+ * @param b subtrahend operand
+ * @return {@link UnaryOperator} which subtracts provided value from {@link Function} argument
+ * @since 0.0.7
+ */
+ public static UnaryOperator subtract(double b) {
+ return a -> subtract(a, b);
+ }
+
+ /**
+ * Provides {@link UnaryOperator} which adds provided value to {@link Function} argument
+ *
+ * @param b addend
+ * @return {@link UnaryOperator} which adds provided value to {@link Function} argument
+ * @since 0.0.7
+ */
+ public static UnaryOperator add(int b) {
+ return a -> Integer.sum(a, b);
+ }
+
+ /**
+ * Provides {@link UnaryOperator} which adds provided value to {@link Function} argument
+ *
+ * @param b addend
+ * @return {@link UnaryOperator} which adds provided value to {@link Function} argument
+ * @since 0.0.7
+ */
+ public static UnaryOperator add(long b) {
+ return a -> Long.sum(a, b);
+ }
+
+ /**
+ * Provides {@link UnaryOperator} which adds provided value to {@link Function} argument
+ *
+ * @param b addend
+ * @return {@link UnaryOperator} which adds provided value to {@link Function} argument
+ * @since 0.0.7
+ */
+ public static UnaryOperator add(float b) {
+ return a -> Float.sum(a, b);
+ }
+
+ /**
+ * Provides {@link UnaryOperator} which adds provided value to {@link Function} argument
+ *
+ * @param b addend
+ * @return {@link UnaryOperator} which adds provided value to {@link Function} argument
+ * @since 0.0.7
+ */
+ public static UnaryOperator add(double b) {
+ return a -> Double.sum(a, b);
+ }
}
diff --git a/src/main/java/com/hijackermax/utils/lang/StringUtils.java b/src/main/java/com/hijackermax/utils/lang/StringUtils.java
index fe49e8b..87f1a1d 100644
--- a/src/main/java/com/hijackermax/utils/lang/StringUtils.java
+++ b/src/main/java/com/hijackermax/utils/lang/StringUtils.java
@@ -45,6 +45,17 @@ public final class StringUtils {
* Underscore {@link String} constant
*/
public static final String UNDERSCORE = "_";
+
+ /**
+ * Zero {@link String} constant
+ */
+ public static final String ZERO = "0";
+
+ /**
+ * One {@link String} constant
+ */
+ public static final String ONE = "1";
+
private static final Pattern WHITESPACES_PATTERN = Pattern.compile("\\s+");
private static final Pattern NON_DIGITS_PATTERN = Pattern.compile("[^\\d.]");
diff --git a/src/test/java/com/hijackermax/encoders/AbstractEncoderTest.java b/src/test/java/com/hijackermax/encoders/AbstractEncoderTest.java
index 026ba6c..0f3e2e8 100644
--- a/src/test/java/com/hijackermax/encoders/AbstractEncoderTest.java
+++ b/src/test/java/com/hijackermax/encoders/AbstractEncoderTest.java
@@ -43,8 +43,21 @@ private void runVariableLengthEncodeDecode(int length) {
assertEquals(source, decoded, String.format("Source and decode don't match, source length %d", length));
}
+ @Test
+ void testEncodeDecodeStatic() {
+ byte[] sourceBytes = getSourceForEncode();
+ String encoded = getEncoder().apply(sourceBytes);
+ assertFalse(encoded.isEmpty());
+ assertEquals(getEncodedSource(), encoded);
+ byte[] decodedBytes = getDecoder().apply(encoded);
+ assertArrayEquals(sourceBytes, decodedBytes);
+ }
abstract Function getEncoder();
abstract Function getDecoder();
+
+ abstract byte[] getSourceForEncode();
+
+ abstract String getEncodedSource();
}
diff --git a/src/test/java/com/hijackermax/encoders/Base122Test.java b/src/test/java/com/hijackermax/encoders/Base122Test.java
index f449529..432407d 100644
--- a/src/test/java/com/hijackermax/encoders/Base122Test.java
+++ b/src/test/java/com/hijackermax/encoders/Base122Test.java
@@ -2,6 +2,7 @@
import com.hijackermax.utils.encoders.Base122;
+import java.nio.charset.StandardCharsets;
import java.util.function.Function;
class Base122Test extends AbstractEncoderTest {
@@ -14,4 +15,14 @@ Function getEncoder() {
Function getDecoder() {
return Base122::decode;
}
+
+ @Override
+ byte[] getSourceForEncode() {
+ return "TestString124567890FooBar!@#$%^&*()[]".getBytes(StandardCharsets.UTF_8);
+ }
+
+ @Override
+ String getEncodedSource() {
+ return "*\u0019.7ύhr4[Ls\tHh5\u001B˧\u0003IA\fo7PL\u0017\u0011\u0005£\u0012\t+b1(P)-W ";
+ }
}
diff --git a/src/test/java/com/hijackermax/encoders/Base32Test.java b/src/test/java/com/hijackermax/encoders/Base32Test.java
new file mode 100644
index 0000000..5ee6e1f
--- /dev/null
+++ b/src/test/java/com/hijackermax/encoders/Base32Test.java
@@ -0,0 +1,29 @@
+package com.hijackermax.encoders;
+
+import com.hijackermax.utils.encoders.Base32;
+
+import java.nio.charset.StandardCharsets;
+import java.util.function.Function;
+
+class Base32Test extends AbstractEncoderTest {
+
+ @Override
+ Function getEncoder() {
+ return Base32::encode;
+ }
+
+ @Override
+ Function getDecoder() {
+ return Base32::decode;
+ }
+
+ @Override
+ byte[] getSourceForEncode() {
+ return "TestString124567890FooBar!@#$%^&*()[]".getBytes(StandardCharsets.UTF_8);
+ }
+
+ @Override
+ String getEncodedSource() {
+ return "AHJQ6X2KEHS6JVK764S38D9P6WW3JC26DXQM4RBJ45026915BRK2MA19BDEG";
+ }
+}
diff --git a/src/test/java/com/hijackermax/encoders/Base58Test.java b/src/test/java/com/hijackermax/encoders/Base58Test.java
index 4b45407..2a6c5fd 100644
--- a/src/test/java/com/hijackermax/encoders/Base58Test.java
+++ b/src/test/java/com/hijackermax/encoders/Base58Test.java
@@ -2,6 +2,7 @@
import com.hijackermax.utils.encoders.Base58;
+import java.nio.charset.StandardCharsets;
import java.util.function.Function;
class Base58Test extends AbstractEncoderTest {
@@ -15,4 +16,14 @@ Function getEncoder() {
Function getDecoder() {
return Base58::decode;
}
+
+ @Override
+ byte[] getSourceForEncode() {
+ return "TestString124567890FooBar!@#$%^&*()[]".getBytes(StandardCharsets.UTF_8);
+ }
+
+ @Override
+ String getEncodedSource() {
+ return "3q4DFPT8Jw8FG6jg9qdEpSaCvNBpejFY68kA6y6aacU2j8z18ig";
+ }
}
diff --git a/src/test/java/com/hijackermax/encoders/Base85Test.java b/src/test/java/com/hijackermax/encoders/Base85Test.java
index 1aee893..483c407 100644
--- a/src/test/java/com/hijackermax/encoders/Base85Test.java
+++ b/src/test/java/com/hijackermax/encoders/Base85Test.java
@@ -2,6 +2,7 @@
import com.hijackermax.utils.encoders.Base85;
+import java.nio.charset.StandardCharsets;
import java.util.function.Function;
class Base85Test extends AbstractEncoderTest {
@@ -14,4 +15,14 @@ Function getEncoder() {
Function getDecoder() {
return Base85::decode;
}
+
+ @Override
+ byte[] getSourceForEncode() {
+ return "TestString124567890FooBar!@#$%^&*()[]".getBytes(StandardCharsets.UTF_8);
+ }
+
+ @Override
+ String getEncodedSource() {
+ return "<+U,m;fm%oDJ([Z1c70M3&rZ^Df7sNEZm[m,UHbD.OZ`M>l";
+ }
}
diff --git a/src/test/java/com/hijackermax/utils/MathUtilsTest.java b/src/test/java/com/hijackermax/utils/MathUtilsTest.java
index de0c307..8798447 100644
--- a/src/test/java/com/hijackermax/utils/MathUtilsTest.java
+++ b/src/test/java/com/hijackermax/utils/MathUtilsTest.java
@@ -135,4 +135,61 @@ void testAbsMultiplyDouble() {
assertEquals(0D, MathUtils.absMultiply(20D, -0D));
assertEquals(100D, MathUtils.absMultiply(10D, -10D));
}
+
+ @Test
+ void testSubtractLongUnaryOperator() {
+ assertEquals(-10L, MathUtils.subtract(20L).apply(10L));
+ assertEquals(0L, MathUtils.subtract(0L).apply(0L));
+ assertEquals(20L, MathUtils.subtract(-10L).apply(10L));
+ }
+
+ @Test
+ void testSubtractIntUnaryOperator() {
+ assertEquals(-10, MathUtils.subtract(20).apply(10));
+ assertEquals(0, MathUtils.subtract(0).apply(0));
+ assertEquals(20, MathUtils.subtract(-10).apply(10));
+ }
+
+ @Test
+ void testSubtractFloatUnaryOperator() {
+ assertEquals(-10F, MathUtils.subtract(20F).apply(10F));
+ assertEquals(0F, MathUtils.subtract(0F).apply(0F));
+ assertEquals(20F, MathUtils.subtract(-10F).apply(10F));
+ }
+
+ @Test
+ void testSubtractDoubleUnaryOperator() {
+ assertEquals(-10D, MathUtils.subtract(20D).apply(10D));
+ assertEquals(0D, MathUtils.subtract(0D).apply(0D));
+ assertEquals(20D, MathUtils.subtract(-10D).apply(10D));
+ }
+
+
+ @Test
+ void testAddLongUnaryOperator() {
+ assertEquals(30L, MathUtils.add(20L).apply(10L));
+ assertEquals(0L, MathUtils.add(0L).apply(0L));
+ assertEquals(0L, MathUtils.add(-10L).apply(10L));
+ }
+
+ @Test
+ void testAddIntUnaryOperator() {
+ assertEquals(30, MathUtils.add(20).apply(10));
+ assertEquals(0, MathUtils.add(0).apply(0));
+ assertEquals(0, MathUtils.add(-10).apply(10));
+ }
+
+ @Test
+ void testAddFloatUnaryOperator() {
+ assertEquals(30F, MathUtils.add(20F).apply(10F));
+ assertEquals(0F, MathUtils.add(0F).apply(0F));
+ assertEquals(0F, MathUtils.add(-10F).apply(10F));
+ }
+
+ @Test
+ void testAddDoubleUnaryOperator() {
+ assertEquals(30D, MathUtils.add(20D).apply(10D));
+ assertEquals(0D, MathUtils.add(0D).apply(0D));
+ assertEquals(0D, MathUtils.add(-10D).apply(10D));
+ }
}