/** * Declares this converter as a injective or surjective function, * depending on whether conversions loose information or not. */ @Override public Set<FunctionProperty> properties() { return EnumSet.of(Numbers.widestClass(sourceClass, targetClass) == targetClass ? FunctionProperty.INJECTIVE : FunctionProperty.SURJECTIVE, FunctionProperty.ORDER_PRESERVING, FunctionProperty.INVERTIBLE); }
/** * Declares this converter as a injective or surjective function, * depending on whether conversions loose information or not. */ @Override public Set<FunctionProperty> properties() { return EnumSet.of(Numbers.widestClass(sourceClass, targetClass) == targetClass ? FunctionProperty.INJECTIVE : FunctionProperty.SURJECTIVE, FunctionProperty.ORDER_PRESERVING, FunctionProperty.INVERTIBLE); }
/** * Returns the widest type of two numbers. Numbers {@code n1} and {@code n2} can be instance of * {@link Byte}, {@link Short}, {@link Integer}, {@link Long}, {@link Float}, {@link Double}, * {@link BigInteger} or {@link BigDecimal} types. * * <p>If one of the given argument is null, then this method returns the class of the non-null argument. * If both arguments are null, then this method returns {@code null}.</p> * * @param n1 the first number, or {@code null}. * @param n2 the second number, or {@code null}. * @return the widest type of the given numbers, or {@code null} if not {@code n1} and {@code n2} are null. * @throws IllegalArgumentException if a number is not of a known type. * * @see #widestClass(Number, Number) * @see #narrowestClass(Number, Number) */ public static Class<? extends Number> widestClass(final Number n1, final Number n2) throws IllegalArgumentException { return widestClass((n1 != null) ? n1.getClass() : null, (n2 != null) ? n2.getClass() : null); }
/** * Returns the widest type of two numbers. Numbers {@code n1} and {@code n2} can be instance of * {@link Byte}, {@link Short}, {@link Integer}, {@link Long}, {@link Float}, {@link Double}, * {@link BigInteger} or {@link BigDecimal} types. * * <p>If one of the given argument is null, then this method returns the class of the non-null argument. * If both arguments are null, then this method returns {@code null}.</p> * * @param n1 the first number, or {@code null}. * @param n2 the second number, or {@code null}. * @return the widest type of the given numbers, or {@code null} if not {@code n1} and {@code n2} are null. * @throws IllegalArgumentException if a number is not of a known type. * * @see #widestClass(Number, Number) * @see #narrowestClass(Number, Number) */ public static Class<? extends Number> widestClass(final Number n1, final Number n2) throws IllegalArgumentException { return widestClass((n1 != null) ? n1.getClass() : null, (n2 != null) ? n2.getClass() : null); }
/** * Creates a sequence of numbers in a given range of values using the given increment. * The range of values will be {@code first} inclusive to {@code (first + increment*length)} exclusive. * Note that the value given by the {@code first} argument is equivalent to a "lowest" or "minimum" value * only if the given increment is positive. * * <p>The {@linkplain #getElementType() element type} will be inferred from the type of the given * {@code Number} instances. If will typically be {@code Integer.class} for the [100:1:120] range * and {@code Double.class} for the [0:0.1:1] range.</p> * * @param first the first value, inclusive. * @param increment the difference between the values at two adjacent indexes. * @param length the length of the desired vector. * @return the given sequence as a vector. */ public static Vector createSequence(final Number first, final Number increment, final int length) { Class<? extends Number> type; type = Numbers.widestClass(first, increment); type = Numbers.widestClass(type, Numbers.narrowestClass(first.doubleValue() + increment.doubleValue() * (length-1))); return createSequence(type, first, increment, length); }
/** * Creates a sequence of numbers in a given range of values using the given increment. * The range of values will be {@code first} inclusive to {@code (first + increment*length)} exclusive. * Note that the value given by the {@code first} argument is equivalent to a "lowest" or "minimum" value * only if the given increment is positive. * * <p>The {@linkplain #getElementType() element type} will be inferred from the type of the given * {@code Number} instances. If will typically be {@code Integer.class} for the [100:1:120] range * and {@code Double.class} for the [0:0.1:1] range.</p> * * @param first the first value, inclusive. * @param increment the difference between the values at two adjacent indexes. * @param length the length of the desired vector. * @return the given sequence as a vector. */ public static Vector createSequence(final Number first, final Number increment, final int length) { Class<? extends Number> type; type = Numbers.widestClass(first, increment); type = Numbers.widestClass(type, Numbers.narrowestClass(first.doubleValue() + increment.doubleValue() * (length-1))); return createSequence(type, first, increment, length); }
/** * Adds a qualitative category for samples in the given range of values. * * <div class="note"><b>Implementation note:</b> * this convenience method delegates to {@link #addQualitative(CharSequence, NumberRange)}.</div> * * @param name the category name as a {@link String} or {@link InternationalString} object, * or {@code null} for a default "no data" name. * @param minimum the minimum sample value, inclusive. * @param maximum the maximum sample value, inclusive. * @return {@code this}, for method call chaining. * @throws IllegalArgumentException if the range is empty. */ public Builder addQualitative(final CharSequence name, final Number minimum, final Number maximum) { return addQualitative(name, range(Numbers.widestClass(minimum, maximum), minimum, maximum)); }
/** * Returns the increment between all consecutive values if this increment is constant, or {@code null} otherwise. */ @Override public Number increment(final double tolerance) { Number inc = first.increment(tolerance); if (inc != null) { Number check = second.increment(tolerance); if (check != null) { final Class<? extends Number> type = Numbers.widestClass(inc.getClass(), check.getClass()); inc = Numbers.cast(inc, type); check = Numbers.cast(check, type); if (inc.equals(check)) { return inc; } } } return null; }
/** * Returns the increment between all consecutive values if this increment is constant, or {@code null} otherwise. */ @Override public Number increment(final double tolerance) { Number inc = first.increment(tolerance); if (inc != null) { Number check = second.increment(tolerance); if (check != null) { final Class<? extends Number> type = Numbers.widestClass(inc.getClass(), check.getClass()); inc = Numbers.cast(inc, type); check = Numbers.cast(check, type); if (inc.equals(check)) { return inc; } } } return null; }
/** * Returns {@code true} if the supplied range is fully contained within this range. * This method converts {@code this} or the given argument to the widest numeric type, * then delegates to {@link #intersects(Range)}. * * @param range the range to check for inclusion in this range. * @return {@code true} if the given range is included in this range. * @throws IllegalArgumentException if the given range can not be converted to a valid type * through widening conversion, or if the units of measurement are not convertible. */ @SuppressWarnings({"unchecked","rawtypes"}) public boolean intersectsAny(final NumberRange<?> range) throws IllegalArgumentException { final Class type = Numbers.widestClass(elementType, range.elementType); return castTo(type).intersects(convertAndCast(range, type)); }
/** * Returns {@code true} if the supplied range is fully contained within this range. * This method converts {@code this} or the given argument to the widest numeric type, * then delegates to {@link #intersects(Range)}. * * @param range the range to check for inclusion in this range. * @return {@code true} if the given range is included in this range. * @throws IllegalArgumentException if the given range can not be converted to a valid type * through widening conversion, or if the units of measurement are not convertible. */ @SuppressWarnings({"unchecked","rawtypes"}) public boolean intersectsAny(final NumberRange<?> range) throws IllegalArgumentException { final Class type = Numbers.widestClass(elementType, range.elementType); return castTo(type).intersects(convertAndCast(range, type)); }
/** * Tests {@link Numbers#widestClass(Class, Class)}. */ @Test public void testWidestClass() { assertEquals(Byte .class, widestClass(Byte.class, Byte.class)); assertEquals(Integer.class, widestClass(Byte.class, Integer.class)); assertEquals(Integer.class, widestClass(Integer.class, Byte.class)); assertEquals(Float .class, widestClass(Integer.class, Float.class)); }
/** * Returns the range of values that are in this range but not in the given range. * This method converts {@code this} or the given argument to the widest numeric type, * then delegates to {@link #subtract(Range)}. * * @param range the range to subtract. * @return this range without the given range, as an array of length 0, 1 or 2. * @throws IllegalArgumentException if the given range can not be converted to a valid type * through widening conversion, or if the units of measurement are not convertible. */ @SuppressWarnings({"unchecked","rawtypes"}) public NumberRange<?>[] subtractAny(final NumberRange<?> range) throws IllegalArgumentException { final Class type = Numbers.widestClass(elementType, range.elementType); return (NumberRange[]) castTo(type).subtract(convertAndCast(range, type)); } }
/** * Returns the range of values that are in this range but not in the given range. * This method converts {@code this} or the given argument to the widest numeric type, * then delegates to {@link #subtract(Range)}. * * @param range the range to subtract. * @return this range without the given range, as an array of length 0, 1 or 2. * @throws IllegalArgumentException if the given range can not be converted to a valid type * through widening conversion, or if the units of measurement are not convertible. */ @SuppressWarnings({"unchecked","rawtypes"}) public NumberRange<?>[] subtractAny(final NumberRange<?> range) throws IllegalArgumentException { final Class type = Numbers.widestClass(elementType, range.elementType); return (NumberRange[]) castTo(type).subtract(convertAndCast(range, type)); } }
/** * Returns the union of this range with the given range. * This method converts {@code this} or the given argument to the widest numeric type, * then delegates to {@link #intersect(Range)}. * * @param range the range to add to this range. * @return the union of this range with the given range. * @throws IllegalArgumentException if the given range can not be converted to a valid type * through widening conversion, or if the units of measurement are not convertible. */ @SuppressWarnings({"unchecked","rawtypes"}) public NumberRange<?> intersectAny(final NumberRange<?> range) throws IllegalArgumentException { Class type = Numbers.widestClass(elementType, range.elementType); final NumberRange<?> intersect = castOrCopy(castTo(type).intersect(convertAndCast(range, type))); /* * Use a finer type capable to holds the result (since the intersection * may have reduced the range), but not finer than the finest type of * the ranges used in the intersection calculation. */ type = Numbers.narrowestClass(elementType, range.elementType); type = Numbers.widestClass(type, Numbers.narrowestClass((Number) intersect.minValue)); type = Numbers.widestClass(type, Numbers.narrowestClass((Number) intersect.maxValue)); return intersect.castTo(type); }
/** * Returns the union of this range with the given range. * This method converts {@code this} or the given argument to the widest numeric type, * then delegates to {@link #intersect(Range)}. * * @param range the range to add to this range. * @return the union of this range with the given range. * @throws IllegalArgumentException if the given range can not be converted to a valid type * through widening conversion, or if the units of measurement are not convertible. */ @SuppressWarnings({"unchecked","rawtypes"}) public NumberRange<?> intersectAny(final NumberRange<?> range) throws IllegalArgumentException { Class type = Numbers.widestClass(elementType, range.elementType); final NumberRange<?> intersect = castOrCopy(castTo(type).intersect(convertAndCast(range, type))); /* * Use a finer type capable to holds the result (since the intersection * may have reduced the range), but not finer than the finest type of * the ranges used in the intersection calculation. */ type = Numbers.narrowestClass(elementType, range.elementType); type = Numbers.widestClass(type, Numbers.narrowestClass((Number) intersect.minValue)); type = Numbers.widestClass(type, Numbers.narrowestClass((Number) intersect.maxValue)); return intersect.castTo(type); }
/** * Returns {@code true} if the supplied range is fully contained within this range. * This method converts {@code this} or the given argument to the widest numeric type, * then delegates to {@link #contains(Range)}. * * @param range the range to check for inclusion in this range. * @return {@code true} if the given range is included in this range. * @throws IllegalArgumentException if the given range can not be converted to a valid type * through widening conversion, or if the units of measurement are not convertible. */ @SuppressWarnings({"unchecked","rawtypes"}) public boolean containsAny(final NumberRange<?> range) throws IllegalArgumentException { /* * The type bounds is actually <? extends Number & Comparable> but I'm unable to express * it as local variable as of Java 7. So we have to bypass the compiler check, but those * casts are actually safes. */ final Class type = Numbers.widestClass(elementType, range.elementType); return castTo(type).contains(convertAndCast(range, type)); }
/** * Returns {@code true} if the supplied range is fully contained within this range. * This method converts {@code this} or the given argument to the widest numeric type, * then delegates to {@link #contains(Range)}. * * @param range the range to check for inclusion in this range. * @return {@code true} if the given range is included in this range. * @throws IllegalArgumentException if the given range can not be converted to a valid type * through widening conversion, or if the units of measurement are not convertible. */ @SuppressWarnings({"unchecked","rawtypes"}) public boolean containsAny(final NumberRange<?> range) throws IllegalArgumentException { /* * The type bounds is actually <? extends Number & Comparable> but I'm unable to express * it as local variable as of Java 7. So we have to bypass the compiler check, but those * casts are actually safes. */ final Class type = Numbers.widestClass(elementType, range.elementType); return castTo(type).contains(convertAndCast(range, type)); }
/** * Returns the union of this range with the given range. * This method converts {@code this} or the given argument to the widest numeric type, * then delegates to {@link #union(Range)}. * * @param range the range to add to this range. * @return the union of this range with the given range. * @throws IllegalArgumentException if the given range can not be converted to a valid type * through widening conversion, or if the units of measurement are not convertible. */ @SuppressWarnings({"unchecked","rawtypes"}) public NumberRange<?> unionAny(final NumberRange<?> range) throws IllegalArgumentException { final Class type = Numbers.widestClass(elementType, range.elementType); return castOrCopy(castTo(type).union(convertAndCast(range, type))); }
/** * Returns the union of this range with the given range. * This method converts {@code this} or the given argument to the widest numeric type, * then delegates to {@link #union(Range)}. * * @param range the range to add to this range. * @return the union of this range with the given range. * @throws IllegalArgumentException if the given range can not be converted to a valid type * through widening conversion, or if the units of measurement are not convertible. */ @SuppressWarnings({"unchecked","rawtypes"}) public NumberRange<?> unionAny(final NumberRange<?> range) throws IllegalArgumentException { final Class type = Numbers.widestClass(elementType, range.elementType); return castOrCopy(castTo(type).union(convertAndCast(range, type))); }