SquirrelJME/SquirrelJME

View on GitHub
modules/cldc-compact/src/main/java/cc/squirreljme/jvm/SoftFloat.java

Summary

Maintainability
A
0 mins
Test Coverage
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the Mozilla Public License Version 2.0.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.jvm;

import cc.squirreljme.jvm.mle.MathShelf;
import cc.squirreljme.runtime.cldc.annotation.SquirrelJMEVendorApi;
import cc.squirreljme.runtime.cldc.debug.Debugging;
import cc.squirreljme.runtime.cldc.util.UnsignedInteger;

/**
 * Software math operations on 32-bit floats.
 * 
 * This source file uses parts of the Berkeley SoftFloat Release 3e library,
 * converted into Java. See the 3rd party licenses documentation.
 *
 * @since 2019/05/24
 */
@SquirrelJMEVendorApi
@SuppressWarnings({"CommentedOutCode", "MagicNumber", "OverlyComplexClass",
    "SpellCheckingInspection"})
public final class SoftFloat
{
    /** The sign mask. */
    @SquirrelJMEVendorApi
    public static final int SIGN_MASK =
        0b1000_0000_0000_0000__0000_0000_0000_0000;
    
    /** The zero check mask. */
    @SquirrelJMEVendorApi
    public static final int ZERO_CHECK_MASK =
        0x7FFFFFFF;
    
    /** Exponent Mask. */
    @SquirrelJMEVendorApi
    public static final int EXPONENT_MASK =
        0b0111_1111_1000_0000__0000_0000_0000_0000;
    
    /** Fraction Mask. */
    @SquirrelJMEVendorApi
    public static final int FRACTION_MASK =
        0b0000_0000_0111_1111__1111_1111_1111_1111;
    
    /** The mask for NaN values. */
    @SquirrelJMEVendorApi
    public static final int NAN_MASK =
        0b0111_1111_1000_0000__0000_0000_0000_0000;
    
    /** Exponent shift. */
    private static final byte _EXP_SHIFT = 
        23;
    
    /** Default NaN value. */
    public static final float FLOAT_DEFAULT_NAN =
        Float.intBitsToFloat(0xFFC0_0000);
    
    /** Integer from negative overflow. */
    private static final int _INT_FROM_NEGOVER =
        -0x7FFFFFFF - 1;
    
    /** Integer from positive overflow. */
    private static final int _INT_FROM_POSOVER =
        -0x7FFFFFFF - 1;
    
    /** Round near even mode. */
    private static final int _ROUND_NEAR_EVEN = 
        0;
    
    /**
     * Not used.
     *
     * @since 2019/05/24
     */
    private SoftFloat()
    {
    }
    
    /**
     * Adds two values.
     *
     * @param __a A.
     * @param __b B.
     * @return The result.
     * @since 2019/05/24
     */
    @SquirrelJMEVendorApi
    public static float add(int __a, int __b)
    {
        throw Debugging.todo();
    }
    
    /**
     * Adds two values.
     *
     * @param __a A.
     * @param __b B.
     * @return The result.
     * @since 2023/08/02
     */
    @SquirrelJMEVendorApi
    public static float add(float __a, float __b)
    {
        return SoftFloat.add(MathShelf.rawFloatToInt(__a),
            MathShelf.rawFloatToInt(__b));
    }
    
    /**
     * Compares two values, NaN returns {@code -1}.
     *
     * @param __a A.
     * @param __b B.
     * @return The result.
     * @since 2019/05/24
     */
    @SquirrelJMEVendorApi
    @SuppressWarnings("SpellCheckingInspection")
    public static int cmpl(int __a, int __b)
    {
        if (SoftFloat.isNaN(__a) || SoftFloat.isNaN(__b))
            return -1;
        
        return SoftFloat.__cmp(__a, __b);
    }
    
    /**
     * Compares two values, NaN returns {@code -1}.
     *
     * @param __a A.
     * @param __b B.
     * @return The result.
     * @since 2023/08/02
     */
    @SquirrelJMEVendorApi
    public static int cmpl(float __a, float __b)
    {
        return SoftFloat.cmpl(MathShelf.rawFloatToInt(__a),
            MathShelf.rawFloatToInt(__b));
    }
    
    /**
     * Compares two values, NaN returns {@code 1}.
     *
     * @param __a A.
     * @param __b B.
     * @return The result.
     * @since 2019/05/24
     */
    @SquirrelJMEVendorApi
    public static int cmpg(int __a, int __b)
    {
        if (SoftFloat.isNaN(__a) || SoftFloat.isNaN(__b))
            return 1;
        
        return SoftFloat.__cmp(__a, __b);
    }
    
    /**
     * Compares two values, NaN returns {@code 1}.
     *
     * @param __a A.
     * @param __b B.
     * @return The result.
     * @since 2023/08/02
     */
    @SquirrelJMEVendorApi
    public static int cmpg(float __a, float __b)
    {
        return SoftFloat.cmpg(MathShelf.rawFloatToInt(__a),
            MathShelf.rawFloatToInt(__b));
    }
    
    /**
     * Divides two values.
     *
     * @param __a A.
     * @param __b B.
     * @return The result.
     * @since 2019/05/24
     */
    @SquirrelJMEVendorApi
    public static float div(int __a, int __b)
    {
        throw Debugging.todo();
    }
    
    /**
     * Divides two values.
     *
     * @param __a A.
     * @param __b B.
     * @return The result.
     * @since 2023/08/02
     */
    @SquirrelJMEVendorApi
    public static float div(float __a, float __b)
    {
        return SoftFloat.div(MathShelf.rawFloatToInt(__a),
            MathShelf.rawFloatToInt(__b));
    }
    
    /**
     * Is this Not a Number?
     * 
     * @param __a The value to check.
     * @return If this is not a number.
     * @since 2021/04/07
     */
    @SquirrelJMEVendorApi
    public static boolean isNaN(int __a)
    {
        return SoftFloat.NAN_MASK == (__a & SoftFloat.NAN_MASK);
    }
    
    /**
     * Is this Not a Number?
     * 
     * @param __a The value to check.
     * @return If this is not a number.
     * @since 2023/08/02
     */
    @SquirrelJMEVendorApi
    public static boolean isNaN(float __a)
    {
        return SoftFloat.isNaN(MathShelf.rawFloatToInt(__a));
    }
    
    /**
     * Multiplies two values.
     *
     * @param __a A.
     * @param __b B.
     * @return The result.
     * @since 2019/05/24
     */
    @SquirrelJMEVendorApi
    public static float mul(int __a, int __b)
    {
        // First value
        boolean signA = SoftFloat.__signF32UI(__a);
        int expA = SoftFloat.__expF32UI(__a);
        int sigA = SoftFloat.__fracF32UI(__a);
        
        // Second value
        boolean signB = SoftFloat.__signF32UI(__b);
        int expB = SoftFloat.__expF32UI(__b);
        int sigB = SoftFloat.__fracF32UI(__b);
        
        // Will this result in a negative value?
        boolean signZ = signA ^ signB;
        
        boolean returnInfinite = false;
        int magBits = 0;
        if (expA == 0xFF)
        {
            // if ( sigA || ((expB == 0xFF) && sigB) )
            if (sigA != 0 || ((expB == 0xFF) && (sigB != 0)))
                return Float.intBitsToFloat(
                    SoftFloat.__propagateNaNF32UI(__a, __b));
            
            magBits = expB | sigB;
            returnInfinite = true;
        }
        
        if (!returnInfinite && expB == 0xFF)
        {
            // if ( sigB )
            if (sigB != 0)
                return Float.intBitsToFloat(
                    SoftFloat.__propagateNaNF32UI(__a, __b));
            
            magBits = expA | sigA;
            returnInfinite = true;
        }
        
        // Returning infinite value?
        if (returnInfinite)
        {
            // if ( ! magBits )
            if (magBits == 0)
                return SoftFloat.FLOAT_DEFAULT_NAN;
            return Float.intBitsToFloat(
                SoftFloat.__packToF32UI(signZ, 0xFF, 0));
        }
        
        // if ( ! expA )
        if (expA == 0)
        {
            // if ( ! sigA )
            if (sigA == 0)
                return Float.intBitsToFloat(
                    SoftFloat.__packToF32UI(signZ, 0, 0));
                
            long normExpSig = SoftFloat.__normSubnormalF32Sig(sigA);
            expA = (short)MathShelf.longUnpackHigh(normExpSig);
            sigA = MathShelf.longUnpackLow(normExpSig);
        }
        
        // if ( ! expB )
        if (expB == 0)
        {
            // if ( ! sigB )
            if (sigB == 0)
                return Float.intBitsToFloat(
                    SoftFloat.__packToF32UI(signZ, 0, 0));
                
            long normExpSig = SoftFloat.__normSubnormalF32Sig(sigB);
            expB = (short)MathShelf.longUnpackHigh(normExpSig);
            sigB = MathShelf.longUnpackLow(normExpSig);
        }
        
        int expZ = (short)(expA + expB - 0x7F);
        sigA = (sigA | 0x0080_0000) << 7;
        sigB = (sigB | 0x0080_0000) << 8;
        
        // sigZ = softfloat_shortShiftRightJam64(
        //     (uint_fast64_t)sigA * sigB, 32); <-- unsigned multiply
        int sigZ = (int)SoftFloat.__shortShiftRightJam64(
            (sigA & 0xFFFF_FFFFL) * (sigB & 0xFFFF_FFFFL), 32);
        
        // if ( sigZ < 0x40000000 )
        if (UnsignedInteger.compareUnsigned(sigZ, 0x4000_0000) < 0)
        {
            expZ = (short)(expZ - 1);
            sigZ <<= 1;
        }
        
        return Float.intBitsToFloat(
            SoftFloat.__roundPackToF32(signZ, expZ, sigZ));
    }
    
    /**
     * Multiplies two values.
     *
     * @param __a A.
     * @param __b B.
     * @return The result.
     * @since 2023/08/02
     */
    @SquirrelJMEVendorApi
    public static float mul(float __a, float __b)
    {
        return SoftFloat.mul(MathShelf.rawFloatToInt(__a),
            MathShelf.rawFloatToInt(__b));
    }
    
    /**
     * Negates a value.
     *
     * @param __a A.
     * @return The result.
     * @since 2019/05/24
     */
    @SquirrelJMEVendorApi
    public static float neg(int __a)
    {
        throw Debugging.todo();
    }
    
    /**
     * Negates a value.
     *
     * @param __a A.
     * @return The result.
     * @since 2023/08/02
     */
    @SquirrelJMEVendorApi
    public static float neg(float __a)
    {
        return SoftFloat.neg(MathShelf.rawFloatToInt(__a));
    }
    
    /**
     * Ors a value, used for constant loading.
     *
     * @param __a A.
     * @param __b B.
     * @return The result.
     * @since 2019/05/24
     */
    @SquirrelJMEVendorApi
    public static float or(int __a, int __b)
    {
        return MathShelf.rawIntToFloat(__a | __b);
    }
    
    /**
     * Ors a value, used for constant loading.
     *
     * @param __a A.
     * @param __b B.
     * @return The result.
     * @since 2023/08/02
     */
    @SquirrelJMEVendorApi
    public static float or(float __a, float __b)
    {
        return SoftFloat.or(MathShelf.rawFloatToInt(__a),
            MathShelf.rawFloatToInt(__b));
    }
    
    /**
     * Remainders a value.
     *
     * @param __a A.
     * @param __b B.
     * @return The result.
     * @since 2019/05/24
     */
    @SquirrelJMEVendorApi
    public static float rem(int __a, int __b)
    {
        throw Debugging.todo();
    }
    
    /**
     * Remainders a value.
     *
     * @param __a A.
     * @param __b B.
     * @return The result.
     * @since 2023/08/02
     */
    @SquirrelJMEVendorApi
    public static float rem(float __a, float __b)
    {
        return SoftFloat.rem(MathShelf.rawFloatToInt(__a),
            MathShelf.rawFloatToInt(__b));
    }
    
    /**
     * Subtracts values.
     *
     * @param __a A.
     * @param __b B.
     * @return The result.
     * @since 2019/05/24
     */
    @SquirrelJMEVendorApi
    public static float sub(int __a, int __b)
    {
        throw Debugging.todo();
    }
    
    /**
     * Subtracts values.
     *
     * @param __a A.
     * @param __b B.
     * @return The result.
     * @since 2023/08/02
     */
    @SquirrelJMEVendorApi
    public static float sub(float __a, float __b)
    {
        return SoftFloat.sub(MathShelf.rawFloatToInt(__a),
            MathShelf.rawFloatToInt(__b));
    }
    
    /**
     * Converts to double.
     *
     * @param __a A.
     * @return The result.
     * @since 2019/05/24
     */
    @SquirrelJMEVendorApi
    public static double toDouble(int __a)
    {
        throw Debugging.todo();
    }
    
    /**
     * Converts to double.
     *
     * @param __a A.
     * @return The result.
     * @since 2023/08/02
     */
    @SquirrelJMEVendorApi
    public static double toDouble(float __a)
    {
        return SoftFloat.toDouble(MathShelf.rawFloatToInt(__a));
    }
    
    /**
     * Converts to integer.
     *
     * @param __a A.
     * @return The result.
     * @since 2019/05/24
     */
    @SquirrelJMEVendorApi
    public static int toInteger(int __a)
    {
        boolean sign = SoftFloat.__signF32UI(__a);
        int exp = SoftFloat.__expF32UI(__a);
        int sig = SoftFloat.__fracF32UI(__a);
        
        if (exp != 0)
            sig |= 0x0080_0000;
        
        // sig64 = (uint_fast64_t) sig<<32;
        long sig64 = MathShelf.longPack(0, sig);
        int shiftDist = 0xAA - exp;
        
        if (UnsignedInteger.compareUnsigned(0, shiftDist) < 0)
            sig64 = SoftFloat.__shiftRightJam64(sig64, shiftDist);
        
        return SoftFloat.__roundToI32(sign, sig64);
    }
    
    /**
     * Converts to integer.
     *
     * @param __a A.
     * @return The result.
     * @since 2023/08/02
     */
    @SquirrelJMEVendorApi
    public static int toInteger(float __a)
    {
        return SoftFloat.toInteger(MathShelf.rawFloatToInt(__a));
    }
    
    /**
     * Converts to long.
     *
     * @param __a A.
     * @return The result.
     * @since 2019/05/24
     */
    @SquirrelJMEVendorApi
    public static long toLong(int __a)
    {
        throw Debugging.todo();
    }
    
    /**
     * Converts to long.
     *
     * @param __a A.
     * @return The result.
     * @since 2023/08/02
     */
    @SquirrelJMEVendorApi
    public static long toLong(float __a)
    {
        return SoftFloat.toLong(MathShelf.rawFloatToInt(__a));
    }
    
    /**
     * Compares two values.
     *
     * @param __a A.
     * @param __b B.
     * @return The result.
     * @since 2021/04/07
     */
    private static int __cmp(int __a, int __b)
    {
        // Equality, note second means -0 == 0
        // return (uiA == uiB) || ! (uint32_t) ((uiA | uiB)<<1);
        if (__a == __b || ((__a | __b) << 1) == 0)
            return 0;
        
        // Less than
        // (signA != signB) ? signA && ((uint32_t) ((uiA | uiB)<<1) != 0)
        // : (uiA != uiB) && (signA ^ (uiA < uiB));
        boolean signA = (0 != (__a & SoftFloat.SIGN_MASK));
        boolean signB = (0 != (__b & SoftFloat.SIGN_MASK));
        if (signA != signB)
        {
            // signA && ((uint32_t) ((uiA | uiB)<<1) != 0)
            if (signA && ((__a | __b) << 1) != 0)
                return -1;
        }
        
        // (uiA != uiB) && (signA ^ (uiA < uiB))
        // ^^^ const ^^
        else if (signA ^ (UnsignedInteger.compareUnsigned(__a, __b) < 0))
            return -1;
        
        // Anything else assume greater than
        return 1;
    }
    
    /**
     * Returns the exponent.
     * 
     * @param __a The float to read from.
     * @return The exponent.
     * @since 2021/04/10
     */
    private static int __expF32UI(int __a)
    {
        // ((int_fast16_t) ((a)>>23) & 0xFF)
        return (((__a) >>> SoftFloat._EXP_SHIFT) & 0xFF);
    }
    
    /**
     * Returns the fraction/significand from the floating point value.
     * 
     * @param __a The float to read from.
     * @return The fraction/significand.
     * @since 2021/04/10
     */
    private static int __fracF32UI(int __a)
    {
        return (__a & SoftFloat.FRACTION_MASK);
    }
    
    /**
     * Gets if this is a NaN.
     * 
     * @param __a The value to check.
     * @return If this is a NaN.
     * @since 2021/04/10
     */
    private static boolean __isNaNF32UI(int __a)
    {
        return ((~(__a) & 0x7F800000) == 0) &&
            ((__a) & 0x007FFFFF) != 0;
    }
    
    /**
     * Gets if this is a signaling NaN.
     * 
     * @param __a The value to check.
     * @return If this is a signaling NaN.
     * @since 2021/04/10
     */
    private static boolean __isSigNaNF32UI(int __a)
    {
        return ((__a & 0x7FC00000) == 0x7F800000) &&
            (__a & 0x003FFFFF) != 0;
    }
    
    /**
     * Normalized round packed to 32-bit float.
     * 
     * @param __sign The sign.
     * @param __exp The exponent.
     * @param __sig The significand.
     * @return The resultant value.
     * @since 2021/04/08
     */
    static int __normRoundPackToF32(boolean __sign, int __exp, int __sig)
    {
        int shiftDist;
        
        // shiftDist = softfloat_countLeadingZeros32( __sig ) - 1;
        shiftDist = Integer.numberOfLeadingZeros(__sig) - 1;
        __exp -= shiftDist;
        
        // if ( (7 <= shiftDist) && ((unsigned int) exp < 0xFD) ) {
        if (7 <= shiftDist &&
            UnsignedInteger.compareUnsigned(__exp, 0xFD) < 0)
        {
            // uZ.ui = packToF32UI( sign, sig ? exp : 0, sig<<(shiftDist - 7));
            return SoftFloat.__packToF32UI(__sign,
                (__sig != 0 ? __exp : 0),
                __sig << (shiftDist - 7));
        }
        
        // return softfloat_roundPackToF32( sign, exp, sig<<shiftDist );
        return SoftFloat.__roundPackToF32(__sign, __exp,
            __sig << shiftDist);
    }
    
    /**
     * Normalizes a subnormal 32-bit float significand. 
     * 
     * @param __sig The significand.
     * @return The normalized value, the exponent is the high value and
     * the significand is the low value.
     * @since 2021/04/10
     */
    private static long __normSubnormalF32Sig(int __sig)
    {
        // softfloat_countLeadingZeros32( sig ) - 8;
        int shiftDist = Integer.numberOfLeadingZeros(__sig) - 8;
        
        // struct exp16_sig32 { int_fast16_t exp; uint_fast32_t sig; };
        // exp = 1 - shiftDist ,, sig = sig<<shiftDist
        return MathShelf.longPack(__sig << shiftDist,
            (short)(1 - shiftDist));
    }
    
    /**
     * Packs value to an unsigned integer, note that some of these values are
     * perfectly fine to overflow into each other such as the significand
     * being larger than the value.
     * 
     * @param __sign Sign bit.
     * @param __exp Exponent.
     * @param __sig Significand.
     * @return The packed value.
     * @since 2021/04/08
     */
    static int __packToF32UI(boolean __sign, int __exp, int __sig)
    {
        // (((uint32_t) (sign)<<31) + ((uint32_t) (exp)<<23) + (sig))
        return (__sign ? SoftFloat.SIGN_MASK : 0) + ((__exp) << 23) + (__sig);
    }
    
    /**
     * Propagates the given NaN values.
     * 
     * @param __a The first value.
     * @param __b The second value.
     * @return The propagated NaN.
     * @since 2021/04/10
     */
    private static int __propagateNaNF32UI(int __a, int __b)
    {
        boolean isSigNaNA = SoftFloat.__isSigNaNF32UI(__a);
        boolean isSigNaNB = SoftFloat.__isSigNaNF32UI(__b);
        
        // Make NaNs non-signaling.
        int uiNonSigA = __a | 0x00400000;
        int uiNonSigB = __b | 0x00400000;
        
        // Are either of these signaling?
        if (isSigNaNA | isSigNaNB)
        {
            if (isSigNaNA)
            {
                if (!isSigNaNB)
                    return SoftFloat.__isNaNF32UI(__b) ? uiNonSigB : uiNonSigA;
            }
            else
                return SoftFloat.__isNaNF32UI(__a) ? uiNonSigA : uiNonSigB;
        }
        
        int uiMagA = __a & 0x7FFFFFFF;
        int uiMagB = __b & 0x7FFFFFFF;
        
        if (UnsignedInteger.compareUnsigned(uiMagA, uiMagB) < 0)
            return uiNonSigB;
        
        if (UnsignedInteger.compareUnsigned(uiMagB, uiMagA) < 0)
            return uiNonSigA;
        
        // return (uiNonSigA < uiNonSigB) ? uiNonSigA : uiNonSigB;
        if (UnsignedInteger.compareUnsigned(uiNonSigA, uiNonSigB) < 0)
            return uiNonSigA;
        return uiNonSigB;
    }
    
    /**
     * Round and pack to float.
     * 
     * @param __sign The sign.
     * @param __exp The exponent.
     * @param __sig The significand.
     * @return The resultant value.
     * @since 2021/04/08
     */
    private static int __roundPackToF32(boolean __sign, int __exp, int __sig)
    {
        int roundIncrement = 0x40;
        int roundBits = __sig & 0x7F;
        
        // if ( 0xFD <= (unsigned int) exp )
        if (UnsignedInteger.compareUnsigned(0xFD, __exp) <= 0)
        {
            // Negative exponent?
            if (__exp < 0)
            {
                __sig = SoftFloat.__shiftRightJam32(__sig, -__exp);
                __exp = 0;
                roundBits = __sig & 0x7F;
            }
            
            // else if ((0xFD < exp) || (0x80000000 <= sig + roundIncrement))
            else if (0xFD < __exp ||
                UnsignedInteger.compareUnsigned(0x8000_0000,
                    __sig + roundIncrement) <= 0)
            {
                // uiZ = packToF32UI(__sign, 0xFF, 0) - !roundIncrement;
                return SoftFloat.__packToF32UI(__sign, 0xFF, 0);
            }
        }
        
        // sig = (sig + roundIncrement)>>7;
        __sig = (__sig + roundIncrement) >>> 7;
        
        // sig &= ~(uint_fast32_t) (! (roundBits ^ 0x40) & roundNearEven);
        __sig &= ~(((roundBits ^ 0x40) == 0 ? 1 : 0) & 1);
        
        // if ( ! sig ) exp = 0;
        if (__sig == 0)
            __exp = 0;
        
        // uiZ = packToF32UI( sign, exp, sig );
        return SoftFloat.__packToF32UI(__sign, __exp, __sig);
    }
    
    /**
     * Rounds to 32-bit integer.
     * 
     * @param __sign The sign.
     * @param __sig The significand.
     * @return The resultant integer.
     * @since 2021/04/10
     */
    private static int __roundToI32(boolean __sign, long __sig)
    {
        int roundBits = ((int)__sig) & 0xFFF;
        int roundIncrement = 0x800;
        __sig += roundIncrement;
        
        // if ( sig & UINT64_C( 0xFFFFF00000000000 ) ) goto invalid;
        if ((__sig & 0xFFFF_F000_0000_0000L) != 0)
            return __sign ? SoftFloat._INT_FROM_NEGOVER :
                SoftFloat._INT_FROM_POSOVER;
        
        // sig32 = sig>>12;
        int sig32 = (int)(__sig >>> 12);
        
        // if (roundBits == 0x800) && (roundMode == softfloat_round_near_even)
        if (roundBits == 0x800)
            sig32 &= ~1;
        
        int z = __sign ? -sig32 : sig32;
        
        // if ( z && ((z < 0) ^ sign) ) goto invalid;
        if (z != 0 && ((z < 0) ^ __sign))
            return __sign ? SoftFloat._INT_FROM_NEGOVER :
                SoftFloat._INT_FROM_POSOVER;
        
        return z;
    }
    
    /**
     * Shift right and jam float.
     * 
     * @param __v The value.
     * @param __uDist The distance.
     * @return The jammed value.
     * @since 2021/04/08
     */
    private static int __shiftRightJam32(int __v, int __uDist)
    {
        // uint_fast16_t dist
        // (dist < 31) ? a>>dist | ((uint32_t) (a<<(-dist & 31)) != 0)
        if (UnsignedInteger.compareUnsigned(__uDist, 31) < 0)
            return __v >> __uDist | (((__v << (-__uDist & 31)) != 0) ? 1 : 0);
        
        // (a != 0)
        return (__v != 0 ? 1 : 0);
    }
    
    /**
     * Shift right and jam 64-bit.
     * 
     * @param __a The value.
     * @param __dist The distance.
     * @return The result.
     * @since 2021/04/10
     */
    private static long __shiftRightJam64(long __a, int __dist)
    {
        // (__dist < 63) ? __a>>__dist |
        //     ((uint64_t) (__a<<(-__dist & 63)) != 0) : (__a != 0);
        if (UnsignedInteger.compareUnsigned(__dist, 63) < 0)
            return __a >>> __dist |
                (((__a << (-__dist & 63)) != 0) ? 1 : 0);
        return (__a != 0 ? 1 : 0);
    }
    
    /**
     * Short shift right jam at 64-bits.
     * 
     * @param __a The value to jam.
     * @param __dist The distance.
     * @return The jammed value.
     * @since 2021/04/10
     */
    private static long __shortShiftRightJam64(long __a, int __dist)
    {
        // return a>>dist | ((a & (((uint_fast64_t) 1<<dist) - 1)) != 0);
        return __a >>> __dist |
            (((__a & ((1L << __dist) - 1)) != 0) ? 1 : 0);
    }
    
    /**
     * Returns whether the sign bit is set.
     * 
     * @param __a The float to read from.
     * @return If the sign bit is set.
     * @since 2021/04/10
     */
    private static boolean __signF32UI(int __a)
    {
        return (__a & SoftFloat.SIGN_MASK) != 0;
    }
}