All Downloads are FREE. Search and download functionalities are using the official Maven repository.

jsonvalues.JsDouble Maven / Gradle / Ivy

package jsonvalues;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Optional;
import java.util.OptionalInt;
import java.util.OptionalLong;
import java.util.function.DoublePredicate;
import java.util.function.DoubleUnaryOperator;

import static java.util.Objects.requireNonNull;

/**
 Represents an immutable json number of type double.
 */
public final class JsDouble extends JsNumber implements Comparable {
    public static final int ID = 5;


    /**
     prism between the sum type JsValue and JsDouble
     */
    public static Prism prism = new Prism<>(s ->
                                                             {
                                                                 if (s.isDouble())
                                                                     return Optional.of(s.toJsDouble().value);
                                                                 if (s.isDecimal()) return s.toJsBigDec()
                                                                                            .doubleValueExact();
                                                                 return Optional.empty();
                                                             },
                                                             JsDouble::of
    );
    /**
     The double value.
     */
    public final double value;

    private JsDouble(final double value) {
        this.value = value;
    }

    @Override
    public int id() {
        return ID;
    }

    @Override
    public boolean isDouble() {
        return true;
    }

    /**
     Compares two {@code JsDouble} objects numerically.

     @see Double#compareTo(Double)
     */
    @Override
    public int compareTo(final JsDouble o) {
        return Double.compare(value,
                              requireNonNull(o).value
                             );
    }

    /**
     Returns the hashcode of this json double.

     @return the hashcode of this JsDouble
     */
    @Override
    public int hashCode() {
        final JsBigDec bigDecimal = JsBigDec.of(BigDecimal.valueOf(this.value));

        final OptionalInt optInt = bigDecimal.intValueExact();
        if (optInt.isPresent()) return optInt.getAsInt();

        final OptionalLong optLong = bigDecimal.longValueExact();
        if (optLong.isPresent()) return JsLong.of(optLong.getAsLong())
                                              .hashCode();

        final Optional optBigInt = bigDecimal.bigIntegerExact();
        return optBigInt.map(BigInteger::hashCode)
                        .orElseGet(bigDecimal::hashCode);
    }

    /**
     Indicates whether some other object is "equal to" this json double. Numbers of different types
     are equals if the have the same value.

     @param that the reference object with which to compare.
     @return true if that is a JsNumber with the same value as this JsDouble
     */
    @Override
    public boolean equals(final Object that) {
        if (this == that) return true;
        if (that == null) return false;
        if (!(that instanceof JsNumber)) return false;
        final JsNumber number = (JsNumber) that;
        if (number.isDouble()) return value == number.toJsDouble().value;
        if (number.isLong()) return equals(number.toJsLong());
        if (number.isInt()) return equals(number.toJsInt());
        if (number.isBigInt()) return equals(number.toJsBigInt());
        if (number.isBigDec()) return equals(number.toJsBigDec());
        return false;
    }

    /**
     @return a string representation of this object.
     @see Double#toString() Double.toString
     */
    @Override
    public String toString() {
        return Double.toString(value);
    }

    /**
     returns true if this double and the specified long represent the same number

     @param jsLong the specified JsLong
     @return true if both JsValue are the same value
     */
    private boolean equals(JsLong jsLong) {
        return requireNonNull(jsLong).equals(this);
    }

    /**
     returns true if this double and the specified integer represent the same number

     @param jsInt the specified JsInt
     @return true if both JsValue are the same value
     */
    private boolean equals(JsInt jsInt) {
        return requireNonNull(jsInt).equals(this);
    }

    /**
     returns true if this double and the specified biginteger represent the same number

     @param jsBigInt the specified JsBigInt
     @return true if both JsValue are the same value
     */
    boolean equals(JsBigInt jsBigInt) {

        final Optional y = bigIntegerExact();
        return y.isPresent() && y.get()
                                 .equals(requireNonNull(jsBigInt).value);
    }

    /**
     returns true if this double and the specified bigdecimal represent the same number

     @param jsBigDec the specified JsBigDec
     @return true if both JsValue are the same value
     */
    private boolean equals(JsBigDec jsBigDec) {
        return requireNonNull(jsBigDec).equals(this);
    }

    /**
     Converts this {@code double} to a {@code BigInteger}, checking for lost information.  An empty
     optional is returned if this {@code double} has a nonzero fractional part.

     @return this double as an bigint wrapped in an Optional
     */
    Optional bigIntegerExact() {
        try {
            return Optional.ofNullable(BigDecimal.valueOf(value)
                                                 .toBigIntegerExact());
        } catch (ArithmeticException e) {
            return Optional.empty();
        }
    }

    /**
     Maps this json double into another one.

     @param fn the mapping function
     @return a new JsDouble
     */
    public JsDouble map(DoubleUnaryOperator fn) {
        return JsDouble.of(requireNonNull(fn).applyAsDouble(value));
    }

    /**
     Static factory method to create a JsDouble from a double primitive type.

     @param n the double primitive type
     @return a new JsDouble
     */
    public static JsDouble of(double n) {
        return new JsDouble(n);
    }

    /**
     Tests the value of this json double on a predicate.

     @param predicate the predicate
     @return true if this double satisfies the predicate
     */
    public boolean test(DoublePredicate predicate) {
        return predicate.test(value);
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy