Java source code reading java.lang.Math class

Java source code reading java.lang.Math class

Purpose

――I got a job offer as an engineer, but I'm sick of what I should study for the year before joining the company. I used to write in Ruby, but after joining the company, I don't seem to use Ruby. .. .. → Be familiar with Java. It's a great deal to study design patterns as well.

Overview

--Version is Java 9 ――As a policy, browse where you are interested

Class declaration

public final class Math {

Cannot be inherited with final modifier

constructor

    /**
     * Don't let anyone instantiate this class.
     */
    private Math() {}

Cannot be instantiated

constant

--Natural logarithm e

    public static final double E = 2.7182818284590452354;

    public static final double PI = 3.14159265358979323846;

    private static final double DEGREES_TO_RADIANS = 0.017453292519943295;

    private static final double RADIANS_TO_DEGREES = 57.29577951308232;

Trigonometric function

As mentioned in the opening comment, the method of the same name in the StrictMath class is diverted.

    @HotSpotIntrinsicCandidate
    public static double sin(double a) {
        return StrictMath.sin(a); // default impl. delegates to StrictMath
    }

    @HotSpotIntrinsicCandidate
    public static double cos(double a) {
        return StrictMath.cos(a); // default impl. delegates to StrictMath
    }

    @HotSpotIntrinsicCandidate
    public static double tan(double a) {
        return StrictMath.tan(a); // default impl. delegates to StrictMath
    }

    public static double asin(double a) {
        return StrictMath.asin(a); // default impl. delegates to StrictMath
    }

    public static double acos(double a) {
        return StrictMath.acos(a); // default impl. delegates to StrictMath
    }

    public static double atan(double a) {
        return StrictMath.atan(a); // default impl. delegates to StrictMath
    }

And the mysterious annotation @HotSpotIntrinsicCandidate. Hotspot Intrinsic? Intrinsic? Candidate? I don't know what it means.

@Target({ElementType.METHOD, ElementType.CONSTRUCTOR})
@Retention(RetentionPolicy.RUNTIME)
public @interface HotSpotIntrinsicCandidate {
}

???

What does this annotation do?

--atan2 function: It seems that when you enter the coordinates, it will tell you the tan of the right triangle that makes it.

    @HotSpotIntrinsicCandidate
    public static double atan2(double y, double x) {
        return StrictMath.atan2(y, x); // default impl. delegates to StrictMath
    }

Differences between the meanings of the atan function and the atan2 function -Mathematics learned with concrete examples

--Radian ⇄ Π conversion

Just multiply by a constant

    public static double toRadians(double angdeg) {
        return angdeg * DEGREES_TO_RADIANS;
    }

    public static double toDegrees(double angrad) {
        return angrad * RADIANS_TO_DEGREES;
    }

Column: double type

--Double type is a 64-bit floating point number with sign 1, exponent part 11, mantissa part 52 --Value represented by double = (-1) code part x 2 exponent part-1023 x 1. mantissa part --2.225074 10-308 <absolute value of double <1.7797693 10 + 308

Reference: Floating point type and error

Exponential

    @HotSpotIntrinsicCandidate
    public static double exp(double a) {
        return StrictMath.exp(a); // default impl. delegates to StrictMath
    }

    @HotSpotIntrinsicCandidate
    public static double log(double a) {
        return StrictMath.log(a); // default impl. delegates to StrictMath
    }

    @HotSpotIntrinsicCandidate
    public static double log10(double a) {
        return StrictMath.log10(a); // default impl. delegates to StrictMath
    }

After all Strict Math class

root

--Square root --Cube root

    @HotSpotIntrinsicCandidate
    public static double sqrt(double a) {
        return StrictMath.sqrt(a); // default impl. delegates to StrictMath
                                   // Note that hardware sqrt instructions
                                   // frequently can be directly used by JITs
                                   // and should be much faster than doing
                                   // Math.sqrt in software.
    }

    public static double cbrt(double a) {
        return StrictMath.cbrt(a);
    }
    public static double IEEEremainder(double f1, double f2) {
        return StrictMath.IEEEremainder(f1, f2); // delegate to StrictMath
    }

I wondered what the name IEEE (Institute of Electrical and Electronics Engineers) came up with, but it seems to be division.

Defined by ** IEEE 754 ** (Aitori Purui 754, IEEE Standard for Floating-Point Arithmetic: literally translated as "floating point arithmetic standard") It seems that it is.

--Basic format: Set of floating point data in binary and decimal .. A finite number (signed zero and a denormalized number Including E9% 9D% 9E% E6% AD% A3% E8% A6% 8F% E5% 8C% 96% E6% 95% B0)), [Infinite](https://ja.wikipedia.org/wiki/ % E7% 84% A1% E9% 99% 90), consisting of a special "non-number" value (NaN). There are 5 types of basic formats, 3 types in binary format and 2 types in decimal format. --Exchange format: The encoding format (bit string) used to exchange floating point numbers in an efficient and compact manner. --Rounding rule: Rounding method for arithmetic and conversion (Rounding % E7% 90% 86))) —— Arithmetic: Arithmetic and other operations on basic formats --Exception handling: Exceptional state notification ([Division by Zero](https://ja.wikipedia.org/wiki/%E3%82%BC%E3%83%AD%E9%99%A4%E7%AE% 97), overflow, etc.)

Quote: IEEE 754 -Wikipedia

Round

--ceil: Round up the decimal point --floor: Decimal point devaluation --rint: Round to the nearest integer value ←? How is it different from rounding?

  	public static double ceil(double a) {
        return StrictMath.ceil(a); // default impl. delegates to StrictMath
    }
		public static double floor(double a) {
        return StrictMath.floor(a); // default impl. delegates to StrictMath
    }

		public static double rint(double a) {
        return StrictMath.rint(a); // default impl. delegates to StrictMath
    }

--round: Rounding

Finally, a decent and readable code has arrived ...!

   public static int round(float a) {
        int intBits = Float.floatToRawIntBits(a); //1 
        int biasedExp = (intBits & FloatConsts.EXP_BIT_MASK)
                >> (FloatConsts.SIGNIFICAND_WIDTH - 1);// 2
        int shift = (FloatConsts.SIGNIFICAND_WIDTH - 2
                + FloatConsts.EXP_BIAS) - biasedExp; //3
        if ((shift & -32) == 0) { // shift >= 0 && shift < 32
            // a is a finite number such that pow(2,-32) <= ulp(a) < 1
            int r = ((intBits & FloatConsts.SIGNIF_BIT_MASK)
                    | (FloatConsts.SIGNIF_BIT_MASK + 1));
            if (intBits < 0) {
                r = -r;
            }
            // In the comments below each Java expression evaluates to the value
            // the corresponding mathematical expression:
            // (r) evaluates to a / ulp(a)
            // (r >> shift) evaluates to floor(a * 2)
            // ((r >> shift) + 1) evaluates to floor((a + 1/2) * 2)
            // (((r >> shift) + 1) >> 1) evaluates to floor(a + 1/2)
            return ((r >> shift) + 1) >> 1;
        } else {
            // a is either
            // - a finite number with abs(a) < exp(2,FloatConsts.SIGNIFICAND_WIDTH-32) < 1/2
            // - a finite number with ulp(a) >= 1 and hence a is a mathematical integer
            // - an infinity or NaN
            return (int) a;
        }
    }

    public static long round(double a) {
        long longBits = Double.doubleToRawLongBits(a);
        long biasedExp = (longBits & DoubleConsts.EXP_BIT_MASK)
                >> (DoubleConsts.SIGNIFICAND_WIDTH - 1);
        long shift = (DoubleConsts.SIGNIFICAND_WIDTH - 2
                + DoubleConsts.EXP_BIAS) - biasedExp;
        if ((shift & -64) == 0) { // shift >= 0 && shift < 64
            // a is a finite number such that pow(2,-64) <= ulp(a) < 1
            long r = ((longBits & DoubleConsts.SIGNIF_BIT_MASK)
                    | (DoubleConsts.SIGNIF_BIT_MASK + 1));
            if (longBits < 0) {
                r = -r;
            }
            // In the comments below each Java expression evaluates to the value
            // the corresponding mathematical expression:
            // (r) evaluates to a / ulp(a)
            // (r >> shift) evaluates to floor(a * 2)
            // ((r >> shift) + 1) evaluates to floor((a + 1/2) * 2)
            // (((r >> shift) + 1) >> 1) evaluates to floor(a + 1/2)
            return ((r >> shift) + 1) >> 1;
        } else {
            // a is either
            // - a finite number with abs(a) < exp(2,DoubleConsts.SIGNIFICAND_WIDTH-64) < 1/2
            // - a finite number with ulp(a) >= 1 and hence a is a mathematical integer
            // - an infinity or NaN
            return (long) a;
        }
    }


-&: Bit AND operation -">>": Shift operator. Shift right. If ʻa >> 3`, shift a to the right by 3 digits. Since it is a binary number, it is divided by 8.

  1. Integer conversion: Convert argument float to int / convert double to long --It is said that it is acquiring the internal bit representation, not the conversion (cast).
  2. AND the argument int with positive infinity, and shift it to the right by 23.
  3. 22 + 127 = 149- (value after shift obtained in 2.)

??? Give up ... Study shift arithmetic and IEEE754 and then start again ...

Exponentiation

--pow: Exponentiation

/     
		 * @param   a   the base.
     * @param   b   the exponent.
     * @return  the value {@code a}<sup>{@code b}</sup>.
     */
@HotSpotIntrinsicCandidate
    public static double pow(double a, double b) {
        return StrictMath.pow(a, b); // default impl. delegates to StrictMath
    }

random number

    private static final class RandomNumberGeneratorHolder {
        static final Random randomNumberGenerator = new Random();
    }

    public static double random() {
        return RandomNumberGeneratorHolder.randomNumberGenerator.nextDouble();
    }

The Random class is instantiated as an inner class.

Random.class

    private static final double DOUBLE_UNIT = 0x1.0p-53; // 1.0 / (1L << 53)

		public double nextDouble() {
        return (((long)(next(26)) << 27) + next(27)) * DOUBLE_UNIT;
    }

next method

    protected int next(int bits) {
        long oldseed, nextseed;
        AtomicLong seed = this.seed;
        do {
            oldseed = seed.get();
            nextseed = (oldseed * multiplier + addend) & mask;
        } while (!seed.compareAndSet(oldseed, nextseed));
        return (int)(nextseed >>> (48 - bits));
    }

Exact system

It seems to throw an ArithmeticException when it overflows

Supports int and long respectively

    @HotSpotIntrinsicCandidate
    public static int addExact(int x, int y) {
        int r = x + y;
        // HD 2-12 Overflow iff both arguments have the opposite sign of the result
        if (((x ^ r) & (y ^ r)) < 0) {
            throw new ArithmeticException("integer overflow");
        }
        return r;
    }

    @HotSpotIntrinsicCandidate
    public static long addExact(long x, long y) {
        long r = x + y;
        // HD 2-12 Overflow iff both arguments have the opposite sign of the result
        if (((x ^ r) & (y ^ r)) < 0) {
            throw new ArithmeticException("long overflow");
        }
        return r;
    }

    @HotSpotIntrinsicCandidate
    public static int subtractExact(int x, int y) {
        int r = x - y;
        // HD 2-12 Overflow iff the arguments have different signs and
        // the sign of the result is different from the sign of x
        if (((x ^ y) & (x ^ r)) < 0) {
            throw new ArithmeticException("integer overflow");
        }
        return r;
    }

    @HotSpotIntrinsicCandidate
    public static long subtractExact(long x, long y) {
        long r = x - y;
        // HD 2-12 Overflow iff the arguments have different signs and
        // the sign of the result is different from the sign of x
        if (((x ^ y) & (x ^ r)) < 0) {
            throw new ArithmeticException("long overflow");
        }
        return r;
    }

    @HotSpotIntrinsicCandidate
    public static int multiplyExact(int x, int y) {
        long r = (long)x * (long)y;
        if ((int)r != r) {
            throw new ArithmeticException("integer overflow");
        }
        return (int)r;
    }

    public static long multiplyExact(long x, int y) {
        return multiplyExact(x, (long)y);
    }

    @HotSpotIntrinsicCandidate
    public static long multiplyExact(long x, long y) {
        long r = x * y;
        long ax = Math.abs(x);
        long ay = Math.abs(y);
        if (((ax | ay) >>> 31 != 0)) {
            // Some bits greater than 2^31 that might cause overflow
            // Check the result using the divide operator
            // and check for the special case of Long.MIN_VALUE * -1
           if (((y != 0) && (r / y != x)) ||
               (x == Long.MIN_VALUE && y == -1)) {
                throw new ArithmeticException("long overflow");
            }
        }
        return r;
    }

    @HotSpotIntrinsicCandidate
    public static int incrementExact(int a) {
        if (a == Integer.MAX_VALUE) {
            throw new ArithmeticException("integer overflow");
        }

        return a + 1;
    }
    @HotSpotIntrinsicCandidate
    public static long incrementExact(long a) {
        if (a == Long.MAX_VALUE) {
            throw new ArithmeticException("long overflow");
        }

        return a + 1L;
    }

    @HotSpotIntrinsicCandidate
    public static int decrementExact(int a) {
        if (a == Integer.MIN_VALUE) {
            throw new ArithmeticException("integer overflow");
        }

        return a - 1;
    }

    @HotSpotIntrinsicCandidate
    public static long decrementExact(long a) {
        if (a == Long.MIN_VALUE) {
            throw new ArithmeticException("long overflow");
          //    @Native public static final long MIN_VALUE = 0x8000000000000000L;
        }

        return a - 1L;
    }
    @HotSpotIntrinsicCandidate
    public static int negateExact(int a) {
        if (a == Integer.MIN_VALUE) {
            throw new ArithmeticException("integer overflow");
        }

        return -a;
    }
    @HotSpotIntrinsicCandidate
    public static long negateExact(long a) {
        if (a == Long.MIN_VALUE) {
            throw new ArithmeticException("long overflow");
        }

        return -a;
    }
    public static int toIntExact(long value) {
        if ((int)value != value) {
            throw new ArithmeticException("integer overflow");
        }
        return (int)value;
    }

--long MIN_VALUE = 0x8000000000000000L; It seems to be the minimum value. Is it the sign inversion of the minimum value, that is, the maximum value, that is, the overflow? --From the comment, it corresponds to 2's complement and is equivalent when the sign is inverted. --In toIntExact, if it overflows when casting to int, error

    /**
     * Returns as a {@code long} the most significant 64 bits of the 128-bit
     * product of two 64-bit factors.
     *
     * @param x the first value
     * @param y the second value
     * @return the result
     * @since 9
     */
public static long multiplyHigh(long x, long y) {
        if (x < 0 || y < 0) {
            // Use technique from section 8-2 of Henry S. Warren, Jr.,
            // Hacker's Delight (2nd ed.) (Addison Wesley, 2013), 173-174.
            long x1 = x >> 32;
            long x2 = x & 0xFFFFFFFFL;
            long y1 = y >> 32;
            long y2 = y & 0xFFFFFFFFL;
            long z2 = x2 * y2;
            long t = x1 * y2 + (z2 >>> 32);
            long z1 = t & 0xFFFFFFFFL;
            long z0 = t >> 32;
            z1 += x2 * y1;
            return x1 * y1 + z0 + (z1 >> 32);
        } else {
            // Use Karatsuba technique with two base 2^32 digits.
            long x1 = x >>> 32;
            long y1 = y >>> 32;
            long x2 = x & 0xFFFFFFFFL;
            long y2 = y & 0xFFFFFFFFL;
            long A = x1 * y1;
            long B = x2 * y2;
            long C = (x1 + x2) * (y1 + y2);
            long K = C - A - B;
            return (((B >>> 32) + K) >>> 32) + A;
        }
    }

--long type is a 64-bit integer

I'm not sure ... It says that I'm doing something techy quoted from a book

Maximum below the quotient algebra (the largest integer in the quotient is rounded down to the nearest whole number)

    public static int floorDiv(int x, int y) {
        int r = x / y;
        // if the signs are different and modulo not zero, round down
        if ((x ^ y) < 0 && (r * y != x)) {
            r--;
        }
        return r;
    }

    public static long floorDiv(long x, int y) {
        return floorDiv(x, (long)y);
    }

    public static long floorDiv(long x, long y) {
        long r = x / y;
        // if the signs are different and modulo not zero, round down
        if ((x ^ y) < 0 && (r * y != x)) {
            r--;
        }
        return r;
    }

-^: Bitwise operator NOR

Mod

   public static int floorMod(int x, int y) {
        return x - floorDiv(x, y) * y;
    }

    public static int floorMod(long x, int y) {
        // Result cannot overflow the range of int.
        return (int)(x - floorDiv(x, y) * y);
    }

    public static long floorMod(long x, long y) {
        return x - floorDiv(x, y) * y;
    }

Do you ask for mod like that ...!

Let's think concretely.

  1. Let (x, y) = (11, 5). Naturally 11% 5 is 1
  2. floorDiv (11,5) → Commerce 2
  3. 2 * 5 = 10
  4. 11 - 10 = 1

Oh.

Absolute value

   public static int abs(int a) {
        return (a < 0) ? -a : a;
    }

    public static long abs(long a) {
        return (a < 0) ? -a : a;
    }

    public static float abs(float a) {
        return (a <= 0.0F) ? 0.0F - a : a;
    }

    @HotSpotIntrinsicCandidate
    public static double abs(double a) {
        return (a <= 0.0D) ? 0.0D - a : a;
    }

    @HotSpotIntrinsicCandidate
    public static int max(int a, int b) {
        return (a >= b) ? a : b;
    }

Maximum value Minimum value

   public static long max(long a, long b) {
        return (a >= b) ? a : b;
    }

Member variables that suddenly appeared

    // Use raw bit-wise conversions on guaranteed non-NaN arguments.
    private static long negativeZeroFloatBits  = Float.floatToRawIntBits(-0.0f);
    private static long negativeZeroDoubleBits = Double.doubleToRawLongBits(-0.0d);

--It seems that it was guaranteed that it was not NaN

I'm grateful that it's easy to read that the member variables appear just before use, rather than being above everything.

    public static float max(float a, float b) {
        if (a != a)
            return a;   // a is NaN
        if ((a == 0.0f) &&
            (b == 0.0f) &&
            (Float.floatToRawIntBits(a) == negativeZeroFloatBits)) {
            // Raw conversion ok since NaN can't map to -0.0.
            return b;
        }
        return (a >= b) ? a : b;
    }

  public static double max(double a, double b) {
        if (a != a)
            return a;   // a is NaN
        if ((a == 0.0d) &&
            (b == 0.0d) &&
            (Double.doubleToRawLongBits(a) == negativeZeroDoubleBits)) {
            // Raw conversion ok since NaN can't map to -0.0.
            return b;
        }
        return (a >= b) ? a : b;  
  }

    @HotSpotIntrinsicCandidate
    public static int min(int a, int b) {
        return (a <= b) ? a : b;
    }

    public static long min(long a, long b) {
        return (a <= b) ? a : b;
    }

    public static float min(float a, float b) {
        if (a != a)
            return a;   // a is NaN
        if ((a == 0.0f) &&
            (b == 0.0f) &&
            (Float.floatToRawIntBits(b) == negativeZeroFloatBits)) {
            // Raw conversion ok since NaN can't map to -0.0.
            return b;
        }
        return (a <= b) ? a : b;
    }

    public static double min(double a, double b) {
        if (a != a)
            return a;   // a is NaN
        if ((a == 0.0d) &&
            (b == 0.0d) &&
            (Double.doubleToRawLongBits(b) == negativeZeroDoubleBits)) {
            // Raw conversion ok since NaN can't map to -0.0.
            return b;
        }
        return (a <= b) ? a : b;
    }

--If a is NaN, a is the maximum, and if both are 0.0d / 0.0f and a is not NaN, b seems to be the maximum. --If a is NaN, will it be false when compared to a ... why? ――Familiar ternary operator

Fused Multiply Add

--Japanese unknown

-It seems to be an operation of ∘ (x × y + z)

--Compared to ∘ (∘ (x × y) + z), it can be rounded only once, so it seems to be advantageous in terms of accuracy. Reference: FMA \ (Fused Multiply \ -Add ) is summarized from various points of view -Koshimizu And computer mathematics

   @HotSpotIntrinsicCandidate
    public static double fma(double a, double b, double c) {
        /*
         * Infinity and NaN arithmetic is not quite the same with two
         * roundings as opposed to just one so the simple expression
         * "a * b + c" cannot always be used to compute the correct
         * result.  With two roundings, the product can overflow and
         * if the addend is infinite, a spurious NaN can be produced
         * if the infinity from the overflow and the infinite addend
         * have opposite signs.
         */

        // First, screen for and handle non-finite input values whose
        // arithmetic is not supported by BigDecimal.
        if (Double.isNaN(a) || Double.isNaN(b) || Double.isNaN(c)) {
            return Double.NaN;
        } else { // All inputs non-NaN
            boolean infiniteA = Double.isInfinite(a);
            boolean infiniteB = Double.isInfinite(b);
            boolean infiniteC = Double.isInfinite(c);
            double result;

            if (infiniteA || infiniteB || infiniteC) {
                if (infiniteA && b == 0.0 ||
                    infiniteB && a == 0.0 ) {
                    return Double.NaN;
                }
                // Store product in a double field to cause an
                // overflow even if non-strictfp evaluation is being
                // used.
                double product = a * b;
                if (Double.isInfinite(product) && !infiniteA && !infiniteB) {
                    // Intermediate overflow; might cause a
                    // spurious NaN if added to infinite c.
                    assert Double.isInfinite(c);
                    return c;
                } else {
                    result = product + c;
                    assert !Double.isFinite(result);
                    return result;
                }
            } else { // All inputs finite
                BigDecimal product = (new BigDecimal(a)).multiply(new BigDecimal(b));
                if (c == 0.0) { // Positive or negative zero
                    // If the product is an exact zero, use a
                    // floating-point expression to compute the sign
                    // of the zero final result. The product is an
                    // exact zero if and only if at least one of a and
                    // b is zero.
                    if (a == 0.0 || b == 0.0) {
                        return a * b + c;
                    } else {
                        // The sign of a zero addend doesn't matter if
                        // the product is nonzero. The sign of a zero
                        // addend is not factored in the result if the
                        // exact product is nonzero but underflows to
                        // zero; see IEEE-754 2008 section 6.3 "The
                        // sign bit".
                        return product.doubleValue();
                    }
                } else {
                    return product.add(new BigDecimal(c)).doubleValue();
                }
            }
        }
    }
  @HotSpotIntrinsicCandidate
    public static float fma(float a, float b, float c) {
        /*
         *  Since the double format has more than twice the precision
         *  of the float format, the multiply of a * b is exact in
         *  double. The add of c to the product then incurs one
         *  rounding error. Since the double format moreover has more
         *  than (2p + 2) precision bits compared to the p bits of the
         *  float format, the two roundings of (a * b + c), first to
         *  the double format and then secondarily to the float format,
         *  are equivalent to rounding the intermediate result directly
         *  to the float format.
         *
         * In terms of strictfp vs default-fp concerns related to
         * overflow and underflow, since
         *
         * (Float.MAX_VALUE * Float.MAX_VALUE) << Double.MAX_VALUE
         * (Float.MIN_VALUE * Float.MIN_VALUE) >> Double.MIN_VALUE
         *
         * neither the multiply nor add will overflow or underflow in
         * double. Therefore, it is not necessary for this method to
         * be declared strictfp to have reproducible
         * behavior. However, it is necessary to explicitly store down
         * to a float variable to avoid returning a value in the float
         * extended value set.
         */
        float result = (float)(((double) a * (double) b ) + (double) c);
        return result;
    }

Unit in the Last Place

--Unit of the last digit It seems to represent the absolute value of rounding error ULP, relative error, and machine epsilon

    public static double ulp(double d) {
        int exp = getExponent(d);

        switch(exp) {
        case Double.MAX_EXPONENT + 1:       // NaN or infinity
            return Math.abs(d);

        case Double.MIN_EXPONENT - 1:       // zero or subnormal
            return Double.MIN_VALUE;

        default:
            assert exp <= Double.MAX_EXPONENT && exp >= Double.MIN_EXPONENT;

            // ulp(x) is usually 2^(SIGNIFICAND_WIDTH-1)*(2^ilogb(x))
            exp = exp - (DoubleConsts.SIGNIFICAND_WIDTH-1);
            if (exp >= Double.MIN_EXPONENT) {
                return powerOfTwoD(exp);
            }
            else {
                // return a subnormal result; left shift integer
                // representation of Double.MIN_VALUE appropriate
                // number of positions
                return Double.longBitsToDouble(1L <<
                (exp - (Double.MIN_EXPONENT - (DoubleConsts.SIGNIFICAND_WIDTH-1)) ));
            }
        }
    }

   public static float ulp(float f) {
        int exp = getExponent(f);

        switch(exp) {
        case Float.MAX_EXPONENT+1:        // NaN or infinity
            return Math.abs(f);

        case Float.MIN_EXPONENT-1:        // zero or subnormal
            return Float.MIN_VALUE;

        default:
            assert exp <= Float.MAX_EXPONENT && exp >= Float.MIN_EXPONENT;

            // ulp(x) is usually 2^(SIGNIFICAND_WIDTH-1)*(2^ilogb(x))
            exp = exp - (FloatConsts.SIGNIFICAND_WIDTH-1);
            if (exp >= Float.MIN_EXPONENT) {
                return powerOfTwoF(exp);
            } else {
                // return a subnormal result; left shift integer
                // representation of FloatConsts.MIN_VALUE appropriate
                // number of positions
                return Float.intBitsToFloat(1 <<
                (exp - (Float.MIN_EXPONENT - (FloatConsts.SIGNIFICAND_WIDTH-1)) ));
            }
        }
    }
    public static double signum(double d) {
        return (d == 0.0 || Double.isNaN(d))?d:copySign(1.0, d);
    }

--subnormal number: [Denormal number -Wikipedia](https://ja.wikipedia.org/wiki/%E9%9D%9E%E6%AD%A3%E8%A6%8F%E5%8C%96 % E6% 95% B0) A number very close to 0

Signum

Judge the sign

    public static double signum(double d) {
        return (d == 0.0 || Double.isNaN(d))?d:copySign(1.0, d);
    }
    public static float signum(float f) {
        return (f == 0.0f || Float.isNaN(f))?f:copySign(1.0f, f);
    }

...
  
    public static double copySign(double magnitude, double sign) {
        return Double.longBitsToDouble((Double.doubleToRawLongBits(sign) &
                                        (DoubleConsts.SIGN_BIT_MASK)) |
                                       (Double.doubleToRawLongBits(magnitude) &
                                        (DoubleConsts.EXP_BIT_MASK |
                                         DoubleConsts.SIGNIF_BIT_MASK)));
    }

    public static float copySign(float magnitude, float sign) {
        return Float.intBitsToFloat((Float.floatToRawIntBits(sign) &
                                     (FloatConsts.SIGN_BIT_MASK)) |
                                    (Float.floatToRawIntBits(magnitude) &
                                     (FloatConsts.EXP_BIT_MASK |
                                      FloatConsts.SIGNIF_BIT_MASK)));
    }

--It seems to return 0.0 if d is 0.0 or non-number, 1.0 for positive numbers, and -1.0 for negative numbers otherwise.

Trigonometric function Hyperbolic function

    public static double sinh(double x) {
        return StrictMath.sinh(x);
    }
    public static double cosh(double x) {
        return StrictMath.cosh(x);
    }
    public static double tanh(double x) {
        return StrictMath.tanh(x);
    }

sum of squares

Find the diagonal side of the three-square theorem

    public static double hypot(double x, double y) {
        return StrictMath.hypot(x, y);
    }

Exponential function, logarithmic function

    public static double expm1(double x) {
        return StrictMath.expm1(x);
    }
    public static double log1p(double x) {
        return StrictMath.log1p(x);
    }
    public static int getExponent(float f) {
        /*
         * Bitwise convert f to integer, mask out exponent bits, shift
         * to the right and then subtract out float's bias adjust to
         * get true exponent value
         */
        return ((Float.floatToRawIntBits(f) & FloatConsts.EXP_BIT_MASK) >>
                (FloatConsts.SIGNIFICAND_WIDTH - 1)) - FloatConsts.EXP_BIAS;
    }

    public static int getExponent(double d) {
        /*
         * Bitwise convert d to long, mask out exponent bits, shift
         * to the right and then subtract out double's bias adjust to
         * get true exponent value.
         */
        return (int)(((Double.doubleToRawLongBits(d) & DoubleConsts.EXP_BIT_MASK) >>
                      (DoubleConsts.SIGNIFICAND_WIDTH - 1)) - DoubleConsts.EXP_BIAS);
    }


New Java Math Class: Part 2 Floating Point Numbers

nextAfter, nextUp,

    public static double nextAfter(double start, double direction) {
       

        // Branch to descending case first as it is more costly than ascending
        // case due to start != 0.0d conditional.
        if (start > direction) { // descending
            if (start != 0.0d) {
                final long transducer = Double.doubleToRawLongBits(start);
                return Double.longBitsToDouble(transducer + ((transducer > 0L) ? -1L : 1L));
            } else { // start == 0.0d && direction < 0.0d
                return -Double.MIN_VALUE;
            }
        } else if (start < direction) { // ascending
            // Add +0.0 to get rid of a -0.0 (+0.0 + -0.0 => +0.0)
            // then bitwise convert start to integer.
            final long transducer = Double.doubleToRawLongBits(start + 0.0d);
            return Double.longBitsToDouble(transducer + ((transducer >= 0L) ? 1L : -1L));
        } else if (start == direction) {
            return direction;
        } else { // isNaN(start) || isNaN(direction)
            return start + direction;
        }
    }

    public static float nextAfter(float start, double direction) {
  
        if (start > direction) { // descending
            if (start != 0.0f) {
                final int transducer = Float.floatToRawIntBits(start);
                return Float.intBitsToFloat(transducer + ((transducer > 0) ? -1 : 1));
            } else { // start == 0.0f && direction < 0.0f
                return -Float.MIN_VALUE;
            }
        } else if (start < direction) { // ascending
            // Add +0.0 to get rid of a -0.0 (+0.0 + -0.0 => +0.0)
            // then bitwise convert start to integer.
            final int transducer = Float.floatToRawIntBits(start + 0.0f);
            return Float.intBitsToFloat(transducer + ((transducer >= 0) ? 1 : -1));
        } else if (start == direction) {
            return (float)direction;
        } else { // isNaN(start) || isNaN(direction)
            return start + (float)direction;
        }
    }

    public static double nextUp(double d) {
        // Use a single conditional and handle the likely cases first.
        if (d < Double.POSITIVE_INFINITY) {
            // Add +0.0 to get rid of a -0.0 (+0.0 + -0.0 => +0.0).
            final long transducer = Double.doubleToRawLongBits(d + 0.0D);
            return Double.longBitsToDouble(transducer + ((transducer >= 0L) ? 1L : -1L));
        } else { // d is NaN or +Infinity
            return d;
        }
    }

    public static float nextUp(float f) {
        // Use a single conditional and handle the likely cases first.
        if (f < Float.POSITIVE_INFINITY) {
            // Add +0.0 to get rid of a -0.0 (+0.0 + -0.0 => +0.0).
            final int transducer = Float.floatToRawIntBits(f + 0.0F);
            return Float.intBitsToFloat(transducer + ((transducer >= 0) ? 1 : -1));
        } else { // f is NaN or +Infinity
            return f;
        }
    }

    public static double nextDown(double d) {
        if (Double.isNaN(d) || d == Double.NEGATIVE_INFINITY)
            return d;
        else {
            if (d == 0.0)
                return -Double.MIN_VALUE;
            else
                return Double.longBitsToDouble(Double.doubleToRawLongBits(d) +
                                               ((d > 0.0d)?-1L:+1L));
        }
    }

    public static float nextDown(float f) {
        if (Float.isNaN(f) || f == Float.NEGATIVE_INFINITY)
            return f;
        else {
            if (f == 0.0f)
                return -Float.MIN_VALUE;
            else
                return Float.intBitsToFloat(Float.floatToRawIntBits(f) +
                                            ((f > 0.0f)?-1:+1));
        }
    }

Both have only been found to return very close floating point numbers. What is it used for?

scalb

   public static double scalb(double d, int scaleFactor) {
   
        final int MAX_SCALE = Double.MAX_EXPONENT + -Double.MIN_EXPONENT +
                              DoubleConsts.SIGNIFICAND_WIDTH + 1;
        int exp_adjust = 0;
        int scale_increment = 0;
        double exp_delta = Double.NaN;

        // Make sure scaling factor is in a reasonable range

        if(scaleFactor < 0) {
            scaleFactor = Math.max(scaleFactor, -MAX_SCALE);
            scale_increment = -512;
            exp_delta = twoToTheDoubleScaleDown;
        }
        else {
            scaleFactor = Math.min(scaleFactor, MAX_SCALE);
            scale_increment = 512;
            exp_delta = twoToTheDoubleScaleUp;
        }

        // Calculate (scaleFactor % +/-512), 512 = 2^9, using
        // technique from "Hacker's Delight" section 10-2.
        int t = (scaleFactor >> 9-1) >>> 32 - 9;
        exp_adjust = ((scaleFactor + t) & (512 -1)) - t;

        d *= powerOfTwoD(exp_adjust);
        scaleFactor -= exp_adjust;

        while(scaleFactor != 0) {
            d *= exp_delta;
            scaleFactor -= scale_increment;
        }
        return d;
    }
    public static float scalb(float f, int scaleFactor) {
        final int MAX_SCALE = Float.MAX_EXPONENT + -Float.MIN_EXPONENT +
                              FloatConsts.SIGNIFICAND_WIDTH + 1;

        // Make sure scaling factor is in a reasonable range
        scaleFactor = Math.max(Math.min(scaleFactor, MAX_SCALE), -MAX_SCALE);
      return (float)((double)f*powerOfTwoD(scaleFactor));
    }


    // Constants used in scalb
    static double twoToTheDoubleScaleUp = powerOfTwoD(512);
    static double twoToTheDoubleScaleDown = powerOfTwoD(-512);

    static double powerOfTwoD(int n) {
        assert(n >= Double.MIN_EXPONENT && n <= Double.MAX_EXPONENT);
        return Double.longBitsToDouble((((long)n + (long)DoubleConsts.EXP_BIAS) <<
                                        (DoubleConsts.SIGNIFICAND_WIDTH-1))
                                       & DoubleConsts.EXP_BIT_MASK);
    }


  	static float powerOfTwoF(int n) {
        assert(n >= Float.MIN_EXPONENT && n <= Float.MAX_EXPONENT);
        return Float.intBitsToFloat(((n + FloatConsts.EXP_BIAS) <<
                                     (FloatConsts.SIGNIFICAND_WIDTH-1))
                                    & FloatConsts.EXP_BIT_MASK);
    }

It seems that the first argument is scaleFactor + 1.

Glossary

--trigonometric: Trigonometric

--trigonometric function: trigonometric function

--instrictic: Immanent

--Transducer: Transducer

What i found

--Almost calling the method of java.lang.StrictMath class → You should read the StrictMath class again ――Since shift operation is used a lot, knowledge of shift operation is required to understand it. --If you don't understand just by looking at the code, you should read the comments. -→ I don't want to get stuck with math knowledge, so if you know what Gugu is like, you should skip the rest and come back someday. --Knowledge of IEEE754 seems to be essential.

Question

--What is the @ target annotation doing? --Things that target annotations rather than comments. --Retention RUNTIME is the one that the information is reflected (remains) in the JVM when using the class. --If a is NaN, will it be false when compared to a ... why? ――Since NaN is a "mystery", it seems that they are not necessarily the same even if compared.

Recommended Posts

Java source code reading java.lang.Math class
Technology for reading Java source code in Eclipse
When reading the source code
Basic structure of Java source code
Technology for reading source code (cheat sheet)
[JAWS-UG CLI] CodeBuild: # 1 Creating Source Code (Java)
[Java] Flow from source code to execution
[Java] Class inheritance
Script Java code
Java code TIPS
java Scanner class
Java HashMap class
Java sample code 02
Java sample code 03
Java anonymous class
About Java class
Java sample code 01
Java character code
[java] abstract class
[Java] Object class
Java local class
About class division (Java)
About Java StringBuilder class
When entering eclipse Java source code, auto activation triggers
[Java] About Singleton Class
Comments in Java source
java (split source file)
Eval Java source from Java
Java inner class review
Java class type field
Java programming (class structure)
About java abstract class
CRuby code reading (2): rb_newobj_of
How to decompile apk file to java source code with MAC
[Java] Integer wrapper class reference
Java memo (standard class) substring
Java tips --StaticUtility class modifier
Digital signature sample code (JAVA)
Java inflexible String class substring
Java parallelization code sample collection
Java memo (standard class) length
[Implementation] Java Process class notes
About Java class loader types
CRuby code reading (1): LIKELY / UNLIKELY
How to use java class
[Java] Comparator of Collection class
Java class definition and instantiation
code smell refactoring [lazy class]
[Windows] Java code is garbled
Java learning memo (abstract class)
Java in Visual Studio Code
Write Java8-like code in Java8
Summary of Java Math class
[Java] What is class inheritance?
I tried source code analysis
About Java class variables class methods
[Java] Tips for writing source
[Java basics] What is Class?