de.caff.generics

## Class Primitives

- java.lang.Object
- - de.caff.generics.Primitives

-     public final class Primitives
      extends java.lang.Object

  Primitives helper tool.

  This tool class provides several helper methods and helpful constants for handling primitive Java values.

  One large part is fixing Java's broken handling of `double` and `float` equality and hashing. In Java the following assertion is valid and this can result in subtle errors:

           final double nz = -0.0;  // IEEE 784 negative zero
           final double pz = +0.0;  // IEEE 784 positive zero, same as 0.0

           final Double abNZ = nz; // automatically boxed negative zero (i.e. Double.valueOf())
           final Double abPZ = pz; // automatically boxed positive zero (i.e. Double.valueOf())

           assert abNZ == pz  &&  !abNZ.equals(pz);  // same, but not equal

  Thanks to automatic boxing and unboxing this problem is hidden so deep in the Java language that it is hard to overcome. This class provides some methods of checking floating point values for equality or hashing them with a more natural handling of `0.0`. There is another problem with IEEE 784 having a lot more NaN values which Java usually collapse into one value, but not for equality, hashing, and comparison. But in normal usage this should pose no real problem. See Double Comparison where I elaborate (probably too much) about this mess.
  - `areEqual(double, double)` checks two `double` values for equality with correct zero handling and collapsed NaNs.
  - `areEqual(double[], double[])` checks two `double[]` arrays for equality with correct zero handling and collapsed NaNs.
  - `areEqual(float, float)` checks two `float` values for equality with correct zero handling and collapsed NaNs.
  - `areEqual(float[], float[])` checks two `float[]` arrays for equality with correct zero handling and collapsed NaNs.
  - `areEqual(Object, Object)` deep-checks possible arrays. See the documentation for what it cannot do.
  - `hash(double)` calculates hash values from `double` values which agree with above equality.
  - `hash(double[])` calculates hash values from `double[]` arrays which agree with above equality.
  - `hash(float)` calculates hash values from `float` values which agree with above equality.
  - `hash(float[])` calculates hash values from `float[]` arrays which agree with above equality.
  - `hashAny(Object)` calculates hash values for general objects which may be boxed floating point values, or array of these or their primitive counterparts. See the documentation for what it cannot do.
  - `boxed(double)` boxes a `double` value with zero collapse.
  - `boxedN(double)` does the same with also collapsing all possible NaN values.
  - `boxed(float)` boxes a `float` value with zero collapse.
  - `boxedN(float)` does the same with also collapsing all possible NaN values.
  Author:
    Rammi

- - ### Field Summary

    Fields
    Modifier and Type | Field and Description
    --- | ---
    `static Function1<byte[],byte[]>` | `BYTE_ARRAY_CLONER` Function which clones byte arrays.
    `static Function1<char[],char[]>` | `CHAR_ARRAY_CLONER` Function which clones char arrays.
    `static Subjectivity` | `DEEP_NATURAL_FP` Subjective wrapper factory to repair floating point values in a way that they behave more natural.
    `static Function1<double[],double[]>` | `DOUBLE_ARRAY_CLONER` Function which clones double arrays.
    `static Function1<float[],float[]>` | `FLOAT_ARRAY_CLONER` Function which clones float arrays.
    `static Function1<int[],int[]>` | `INT_ARRAY_CLONER` Function which clones int arrays.
    `static Function1<long[],long[]>` | `LONG_ARRAY_CLONER` Function which clones long arrays.
    `static Function1<short[],short[]>` | `SHORT_ARRAY_CLONER` Function which clones short arrays.

  - ### Method Summary

    All Methods Static Methods Concrete Methods
    Modifier and Type | Method and Description
    --- | ---
    `static boolean` | `areEqual(double[] v1, double[] v2)` Are two primitive `double` arrays equal?
    `static boolean` | `areEqual(double v1, double v2)` Are two primitive `double` values equal?
    `static boolean` | `areEqual(double v1, double v2, double eps)` Are two primitive `double` values nearly equal?
    `static boolean` | `areEqual(float[] v1, float[] v2)` Are two primitive `float` arrays equal?
    `static boolean` | `areEqual(float v1, float v2)` Are two primitive `float` values equal?
    `static boolean` | `areEqual(float v1, float v2, float eps)` Are two primitive `float` values nearly equal?
    `static boolean` | `areEqual(java.lang.Object obj1, java.lang.Object obj2)` Are the too arbitrary objects equal?
    `static java.lang.Double` | `boxed(double value)` Get a boxed double value which takes care of handling positive and negative zero in a more natural way.
    `static java.lang.Float` | `boxed(float value)` Get a boxed float value which takes care of handling positive and negative zero in a more natural way.
    `static java.lang.Double` | `boxedN(double value)` Get a boxed double value which takes care of handling positive and negative zero in a more natural way.
    `static java.lang.Float` | `boxedN(float value)` Get a boxed float value which takes care of handling positive and negative zero in a more natural way.
    `static int` | `compare(double v1, double v2)` Compare two double values without the quirks of `Double.compare(double, double)`.
    `static int` | `compare(float v1, float v2)` Compare two float values without the quirks of `Float.compare(float, float)`.
    `static int` | `compareUnsigned(byte b1, byte b2)` Compare two bytes as if they are unsigned.
    `static int` | `compareUnsigned(short s1, short s2)` Compare two short integers as if they are unsigned.
    `static int` | `hash(double v)` Hashcode calculation for primitive double values giving more natural results.
    `static int` | `hash(double[] arr)` Hashcode calculation for a primitive double array giving more natural results.
    `static int` | `hash(float v)` Hashcode calculation for primitive float values giving more natural results.
    `static int` | `hash(float[] arr)` Hashcode calculation for a primitive float array giving more natural results.
    `static int` | `hashAny(java.lang.Object obj)` Hash any object while handling simple floating point values and arrays of primitive and boxed floating point values in a more natural way.
    `static Order` | `order(double v1, double v2)` Compare two double values without the quirks of `Double.compare(double, double)`.
    `static Order` | `order(float v1, float v2)` Compare two float values without the quirks of `Float.compare(float, float)`.
    `static int` | `positionOfHighestOneBit(int value)` Get the position of the highest one bit.
    `static int` | `positionOfHighestOneBit(long value)` Get the position of the highest one bit.
    `static int` | `positionOfLowestOneBit(int value)` Get the position of the lowest one bit.
    `static int` | `positionOfLowestOneBit(long value)` Get the position of the lowest one bit.
    `static int` | `unsigned(byte b)` Get the unsigned value of a byte.
    `static long` | `unsigned(int i)` Get the unsigned value of an integer.
    `static int` | `unsigned(short s)` Get the unsigned value of a short int.

    - ### Methods inherited from class java.lang.Object

      `clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

- - ### Field Detail

    - #### BYTE_ARRAY_CLONER

          public static final Function1<byte[],byte[]> BYTE_ARRAY_CLONER

      Function which clones byte arrays. `null` is accepted.

    - #### SHORT_ARRAY_CLONER

          public static final Function1<short[],short[]> SHORT_ARRAY_CLONER

      Function which clones short arrays. `null` is accepted.

    - #### INT_ARRAY_CLONER

          public static final Function1<int[],int[]> INT_ARRAY_CLONER

      Function which clones int arrays. `null` is accepted.

    - #### LONG_ARRAY_CLONER

          public static final Function1<long[],long[]> LONG_ARRAY_CLONER

      Function which clones long arrays. `null` is accepted.

    - #### CHAR_ARRAY_CLONER

          public static final Function1<char[],char[]> CHAR_ARRAY_CLONER

      Function which clones char arrays. `null` is accepted.

    - #### FLOAT_ARRAY_CLONER

          public static final Function1<float[],float[]> FLOAT_ARRAY_CLONER

      Function which clones float arrays. `null` is accepted.

    - #### DOUBLE_ARRAY_CLONER

          public static final Function1<double[],double[]> DOUBLE_ARRAY_CLONER

      Function which clones double arrays. `null` is accepted.

    - #### DEEP_NATURAL_FP

          public static final Subjectivity DEEP_NATURAL_FP

      Subjective wrapper factory to repair floating point values in a way that they behave more natural. More natural here means that they no longer differ between the two possible zero values, and neither between all possible NaN values.

      This will take care of standard methods `Object.equals(Object)` and `Object.hashCode()` of `Double`, `double[]`, `Float`, and `float[]` when handled directly or inside arrays. It will also do deep evaluation for both methods when called with arbitrary arrays.

  - ### Method Detail

    - #### unsigned

          public static int unsigned(byte b)

      Get the unsigned value of a byte.
      Parameters:
        `b` - byte value
      Returns:
        unsigned value between `0x00` and `0xFF`

    - #### unsigned

          public static int unsigned(short s)

      Get the unsigned value of a short int.
      Parameters:
        `s` - short value
      Returns:
        unsigned value between `0x0000` and `0xFFFF`

    - #### unsigned

          public static long unsigned(int i)

      Get the unsigned value of an integer.
      Parameters:
        `i` - int value
      Returns:
        unsigned value between `0x00000000` and `0xFFFFFFFF`

    - #### compareUnsigned

          public static int compareUnsigned(byte b1,
                                            byte b2)

      Compare two bytes as if they are unsigned.
      Parameters:
        `b1` - first byte, interpreted as unsigned 8 bit value
        `b2` - second byte interpreted as unsigned 8 bit value
      Returns:
        less than `0` if `unsigned(b1) < unsigned(b2)`, greater than `0` if `unsigned(b1) > unsigned(b2)`, or `0` if `unsigned(b1) == unsigned(b2)`

    - #### compareUnsigned

          public static int compareUnsigned(short s1,
                                            short s2)

      Compare two short integers as if they are unsigned.
      Parameters:
        `s1` - first short integer, interpreted as unsigned 16 bit value
        `s2` - second short integer interpreted as unsigned 16 bit value
      Returns:
        less than `0` if `unsigned(s1) < unsigned(s2)`, greater than `0` if `unsigned(s1) > unsigned(s2)`, or `0` if `unsigned(s1) == unsigned(s2)`

    - #### positionOfHighestOneBit

          public static int positionOfHighestOneBit(int value)

      Get the position of the highest one bit.
      Parameters:
        `value` - value to check
      Returns:
        `-1` if not bit is set, or a value between `0` (only the 1 bit is set) and `31` (the highest bit is set)

    - #### positionOfLowestOneBit

          public static int positionOfLowestOneBit(int value)

      Get the position of the lowest one bit.
      Parameters:
        `value` - value to check
      Returns:
        `-1` if not bit is set, or a value between `0` (the lowest bit is set) and `31` (only the highest bit is set)

    - #### positionOfHighestOneBit

          public static int positionOfHighestOneBit(long value)

      Get the position of the highest one bit.
      Parameters:
        `value` - value to check
      Returns:
        `-1` if not bit is set, or a value between `0` (only the lowest bit is set) and `63` (the highest bit is set)

    - #### positionOfLowestOneBit

          public static int positionOfLowestOneBit(long value)

      Get the position of the lowest one bit.
      Parameters:
        `value` - value to check
      Returns:
        `-1` if not bit is set, or a value between `0` (the lowest bit is set) and `63` (only the highest bit is set)

    - #### areEqual

          public static boolean areEqual(double v1,
                                         double v2)

      Are two primitive `double` values equal?

      Thanks to the underlying standard ANSI / IEEE Std 754-1985 defining floating point arithmetic `Double.NaN` is not equal to anything, not even to itself. This is often not what you want. `Double.compare(double, double)` falls back to the binary representation in some cases, which again is not always a good idea as it differs between `-0.0` and `+0.0` which are considered not equal, although they represent the same mathematical number.

      This method considers two values equal if the both represent the same number. So two `NaN` values are equal, and both `0.0` values are equal in any combination, too. This seems the most natural way to compare doubles.

      Parameters:
        `v1` - first value to compare
        `v2` - second value to compare
      Returns:
        `true`: if both values are considered equal according to the above definition
        `false`: otherwise
      See Also:
        `hash(double)`

    - #### areEqual

          public static boolean areEqual(float v1,
                                         float v2)

      Are two primitive `float` values equal?

      Thanks to the underlying standard ANSI / IEEE Std 754-1985 defining floating point arithmetic `Float.NaN` is not equal to anything, not even to itself. This is often not what you want. `Float.compare(float, float)` falls back to the binary representation in some cases, which again is not always a good idea as it differs between `-0.0f` and `+0.0f` which are considered not equal, although they represent the same mathematical number.

      This method considers two values equal if the both represent the same number. So two `NaN` values are equal, and both `0.0f` values are equal in any combination, too. This seems the most natural way to compare floats.

      Parameters:
        `v1` - first value to compare
        `v2` - second value to compare
      Returns:
        `true`: if both values are considered equal according to the above definition
        `false`: otherwise

    - #### areEqual

          public static boolean areEqual(double v1,
                                         double v2,
                                         double eps)

      Are two primitive `double` values nearly equal?
      Parameters:
        `v1` - first value to compare
        `v2` - second value to compare
        `eps` - allowed deviation for both values to be still considered equal, a small non-negative number
      Returns:
        `true`: if both values are considered equal within the given allowance
        `false`: if they differ too much

    - #### areEqual

          public static boolean areEqual(float v1,
                                         float v2,
                                         float eps)

      Are two primitive `float` values nearly equal?
      Parameters:
        `v1` - first value to compare
        `v2` - second value to compare
        `eps` - allowed deviation for both values to be still considered equal, a small non-negative number
      Returns:
        `true`: if both values are considered equal within the given allowance
        `false`: if they differ too much

    - #### areEqual

          public static boolean areEqual(@NotNull
                                         double[] v1,
                                         @NotNull
                                         double[] v2)

      Are two primitive `double` arrays equal?

      This method uses `areEqual(double, double)` for comparing elements.

      Parameters:
        `v1` - first array to compare
        `v2` - second array to compare
      Returns:
        `true`: if both values are considered equal according to the above definition
        `false`: otherwise
      See Also:
        `hash(double[])`

    - #### areEqual

          public static boolean areEqual(@NotNull
                                         float[] v1,
                                         @NotNull
                                         float[] v2)

      Are two primitive `float` arrays equal?

      This method uses `areEqual(float, float)` for comparing elements.

      Parameters:
        `v1` - first array to compare
        `v2` - second array to compare
      Returns:
        `true`: if both values are considered equal according to the above definition
        `false`: otherwise
      See Also:
        `hash(float[])`

    - #### hash

          public static int hash(double v)

      Hashcode calculation for primitive double values giving more natural results.

      This method agrees with the equality definition provided by areEqual(double, double). Standard Java's `Double.hashCode(double)` will return different values for +0.0 and negative -0.0, and for each NaN value.

      Parameters:
        `v` - double value to hash
      Returns:
        hash value
      See Also:
        `areEqual(double, double)`

    - #### hash

          public static int hash(float v)

      Hashcode calculation for primitive float values giving more natural results.

      This method agrees with the equality definition provided by areEqual(float, float). Standard Java's `Double.hashCode(double)` will return different values for +0.0f and negative -0.0f, and for each NaN value.

      Parameters:
        `v` - float value to hash
      Returns:
        hash value
      See Also:
        `areEqual(float, float)`

    - #### hash

          public static int hash(@Nullable
                                 double[] arr)

      Hashcode calculation for a primitive double array giving more natural results.

      See hash(double) for information.

      Parameters:
        `arr` - double array to hash
      Returns:
        hash value
      See Also:
        `areEqual(double, double)`

    - #### hash

          public static int hash(@Nullable
                                 float[] arr)

      Hashcode calculation for a primitive float array giving more natural results.

      See hash(float) for information.

      Parameters:
        `arr` - double array to hash
      Returns:
        hash value
      See Also:
        `areEqual(double, double)`

    - #### hashAny

          public static int hashAny(@Nullable
                                    java.lang.Object obj)

      Hash any object while handling simple floating point values and arrays of primitive and boxed floating point values in a more natural way.

      It will always hash arrays deeply.

      ATTENTION: this method only handles `double` and `float` values and their boxed counterparts as well as arrays of these in any depth to make them work more natural, but cannot provide this for floating point items inside arbitrary objects.

      Parameters:
        `obj` - object to be hashed
      Returns:
        hash value

    - #### areEqual

          public static boolean areEqual(@Nullable
                                         java.lang.Object obj1,
                                         @Nullable
                                         java.lang.Object obj2)

      Are the too arbitrary objects equal? This method handles primitive and boxed floating point values as well as arrays of them in a more natural way compared to standard Java.

      It will always compare arrays deeply.

      ATTENTION: this method only handles `double` and `float` values and their boxed counterparts as well as arrays of these in any depth to make them work more natural, but cannot provide this for floating point items inside arbitrary objects.

      Parameters:
        `obj1` - first object
        `obj2` - second object
      Returns:
        `true` if both objects are considered the same
        `false` if not

    - #### boxed

          @NotNull
          public static java.lang.Float boxed(float value)

      Get a boxed float value which takes care of handling positive and negative zero in a more natural way.

      This method does not collapse all possible NaN values. This should be a problem only in very rare cases where the values are read from outside Java, or are deliberately created, so the required general overhead seems too much. See boxedN(float) if you also need NaN collapse.

      Parameters:
        `value` - float value to be boxed
      Returns:
        boxed value

    - #### boxedN

          @NotNull
          public static java.lang.Float boxedN(float value)

      Get a boxed float value which takes care of handling positive and negative zero in a more natural way.

      This method also collapses all possible 16,777,214 NaN values into one.

      Parameters:
        `value` - float value to be boxed
      Returns:
        boxed value

    - #### boxed

          @NotNull
          public static java.lang.Double boxed(double value)

      Get a boxed double value which takes care of handling positive and negative zero in a more natural way.

      This method does not collapse all possible NaN values. This should be a problem only in very rare cases where the values are read from outside Java, or are deliberately created, so the required general overhead seems too much. See boxedN(double) if you also need NaN collapse.

      Parameters:
        `value` - double value to be boxed
      Returns:
        boxed value

    - #### boxedN

          @NotNull
          public static java.lang.Double boxedN(double value)

      Get a boxed double value which takes care of handling positive and negative zero in a more natural way.

      This method also collapses all possible 9,007,199,254,740,990 NaN values into one.

      Parameters:
        `value` - double value to be boxed
      Returns:
        boxed value

    - #### compare

          public static int compare(double v1,
                                    double v2)

      Compare two double values without the quirks of `Double.compare(double, double)`. This will sort all NaN values for which `Double.isNaN(double)` as if they are the same value. It will handle `-0.0` and `+0.0` as being the same value. That makes this method work the same as areEqual(double, double) and hash(double). If you use one of them it is best to combine them all.
      Parameters:
        `v1` - first value
        `v2` - second value
      Returns:
        less than zero if `v1` is less than`v2`, more than zero if `v1` is greater than `v2`, and `0` if they considered are the same

    - #### compare

          public static int compare(float v1,
                                    float v2)

      Compare two float values without the quirks of `Float.compare(float, float)`. This will sort all NaN values for which `Float.isNaN(float)` as if they are the same value. It will handle `-0.0` and `+0.0` as being the same value. That makes this method work the same as areEqual(float, float) and hash(float). If you use one of them it is best to combine them all.
      Parameters:
        `v1` - first value
        `v2` - second value
      Returns:
        less than zero if `v1` is less than`v2`, more than zero if `v1` is greater than `v2`, and `0` if they considered are the same

    - #### order

          @NotNull
          public static Order order(double v1,
                                             double v2)

      Compare two double values without the quirks of `Double.compare(double, double)`. This will sort all NaN values for which `Double.isNaN(double)` as if they are the same value. It will handle `-0.0` and `+0.0` as being the same value. That makes this method work the same as areEqual(double, double) and hash(double). If you use one of them it is best to combine them all.
      Parameters:
        `v1` - first value
        `v2` - second value
      Returns:
        the ordering of `v1` and `v2` when appearing in that order

    - #### order

          @NotNull
          public static Order order(float v1,
                                             float v2)

      Compare two float values without the quirks of `Float.compare(float, float)`. This will sort all NaN values for which `Float.isNaN(float)` as if they are the same value. It will handle `-0.0` and `+0.0` as being the same value. That makes this method work the same as areEqual(float, float) and hash(float). If you use one of them it is best to combine them all.
      Parameters:
        `v1` - first value
        `v2` - second value
      Returns:
        the ordering of `v1` and `v2` when appearing in that order