public static <T extends NumericType> T decodeNumeric(String input, Class<T> type) {
        try {
            byte[] inputByteArray = Numeric.hexStringToByteArray(input);
            int typeLengthAsBytes = getTypeLengthInBytes(type);
            int valueOffset = Type.MAX_BYTE_LENGTH - typeLengthAsBytes;

            BigInteger numericValue;
            if (Uint.class.isAssignableFrom(type) || Ufixed.class.isAssignableFrom(type)) {
                numericValue = new BigInteger(1, inputByteArray, valueOffset, typeLengthAsBytes);
            } else {
                numericValue = new BigInteger(inputByteArray, valueOffset, typeLengthAsBytes);
            }
            return type.getConstructor(BigInteger.class).newInstance(numericValue);

        } catch (NoSuchMethodException
                | SecurityException
                | InstantiationException
                | IllegalAccessException
                | IllegalArgumentException
                | InvocationTargetException e) {
            throw new UnsupportedOperationException(
                    "Unable to create instance of " + type.getName(), e);
        }
    }
@Test
    public void testInt16MinMax() throws Exception {
        assertEquals(
                TypeDecoder.decodeNumeric(
                        TypeEncoder.encodeNumeric(
                                new Int16(BigInteger.valueOf((long) Math.pow(2, 15) - 1))),
                        Int16.class),
                new Int16(BigInteger.valueOf((long) Math.pow(2, 15) - 1)));

        assertEquals(
                TypeDecoder.decodeNumeric(
                        TypeEncoder.encodeNumeric(
                                new Int16(BigInteger.valueOf((long) -Math.pow(2, 15)))),
                        Int16.class),
                new Int16(BigInteger.valueOf((long) -Math.pow(2, 15))));
    }