Java Double to Long doubleToS390LongBits(double ieeeDouble)

Here you can find the source of doubleToS390LongBits(double ieeeDouble)

Description

Converts an IEEE double to an S390 double (as a long).

License

Open Source License

Parameter

Parameter Description
ieeeDouble the IEEE double.

Return

the number as an S390 double.

Declaration

public static long doubleToS390LongBits(double ieeeDouble) 

Method Source Code

//package com.java2s;
/*******************************************************************************
 * Copyright ? 2006, 2013 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors://from   w  w w.ja  v a2 s.co  m
 * IBM Corporation - initial API and implementation
 *
 *******************************************************************************/

public class Main {
    private final static long DOUBLE_SIGN_MASK = 0x8000000000000000L;
    private final static long DOUBLE_EXPONENT_MASK = 0x7ff0000000000000L;
    private final static long DOUBLE_MANTISSA_MASK = 0x000fffffffffffffL;
    private final static long DOUBLE_MANTISSA_MSB_MASK = 0x0010000000000000L;
    private final static long DOUBLE_BIAS = 1022;
    private final static int S390_DOUBLE_BIAS = 64;

    /**
     * Converts an IEEE double to an S390 double (as a long). 
     * 
     * @param ieeeDouble  the IEEE double.
     * @return the number as an S390 double.
     */
    public static long doubleToS390LongBits(double ieeeDouble) {
        // To convert from IEEE to S390 we use the following formula:
        // let r = exponent % 4; q = exponent / 4;
        // if q == 0 then m.2^x = m.16^q
        // if q != 0 then m.2^x = (m.2^(r-4)).16^(q+1) for positive q,
        // = (m.2^-r).16^q) for negative q

        // Get the bit pattern
        long ieeeLongBits = Double.doubleToLongBits(ieeeDouble);

        // Test the sign bit (0 = positive, 1 = negative)
        boolean positive = ((ieeeLongBits & DOUBLE_SIGN_MASK) == 0);

        // Deal with zero straight away...
        if ((ieeeLongBits & 0x7fffffffffffffffL) == 0) {
            // + or - 0.0
            return ieeeLongBits;
        }

        // Extract the exponent
        long exponent = ieeeLongBits & DOUBLE_EXPONENT_MASK;
        // shift right 52 bits to get exponent in least significant byte
        exponent = exponent >>> 52;
        // subtract the bias to get the true value
        exponent = exponent - DOUBLE_BIAS;

        // Extract the mantissa
        long mantissa = ieeeLongBits & DOUBLE_MANTISSA_MASK;

        // Now begin the conversion to S390
        long remainder = Math.abs(exponent) % 4;
        long quotient = Math.abs(exponent) / 4;
        long s390Exponent = quotient;
        if ((exponent > 0) && (remainder != 0)) {
            s390Exponent = s390Exponent + 1;
        }

        // put the sign back in
        if (exponent < 0) {
            s390Exponent = -s390Exponent;
        }

        // Add the bias
        s390Exponent += S390_DOUBLE_BIAS;

        // Now adjust the mantissa part
        long s390Mantissa = mantissa;
        // for an exponent greater than -DOUBLE_BIAS, add in the implicit bit
        if (exponent > (-DOUBLE_BIAS)) {
            s390Mantissa = s390Mantissa | DOUBLE_MANTISSA_MSB_MASK;
        } else {
            // there is no implicit bit, so the mantissa is one bit to the right
            // of what
            // we would normally expect. We need to fix this for S390
            s390Mantissa = s390Mantissa << 1;
        }

        // S390 Mantissa starts 4 bits left of ieee one. The first of these is
        // implied in
        // IEEE so only shift 3 places
        s390Mantissa = s390Mantissa << 3;
        if (remainder > 0) {
            if (exponent > 0) {
                // the next two lines perform the (m.2^(r-4)) part of the
                // conversion
                int shift_places = (int) (4 - remainder);
                s390Mantissa = s390Mantissa >>> shift_places;
            } else {
                // to avoid loss of precision when the exponent is at a minimum,
                // we may need to shift the mantissa four places left and
                // decrease the
                // s390 exponent by one before shifting right
                if ((exponent == -(DOUBLE_BIAS)) && ((s390Mantissa & 0x00f0000000000000L) == 0)) {
                    s390Mantissa = s390Mantissa << 4;
                    s390Exponent = s390Exponent - 1;
                }
                // the next two lines perform the m.2-r part of the conversion
                s390Mantissa = s390Mantissa >>> remainder;
            }
        }

        // An exponent of -DOUBLE_BIAS is the smallest that IEEE can do. S390
        // has
        // a wider range, and hence may be able to normalise the mantissa more
        // than
        // is possible for IEEE
        // Each shift left of four bits is equivalent to multiplying by 16,
        // so the exponent must be reduced by 1
        if (exponent == -(DOUBLE_BIAS)) {
            while ((s390Mantissa != 0) && ((s390Mantissa & 0x00f0000000000000L) == 0)) {
                s390Mantissa = s390Mantissa << 4;
                s390Exponent = s390Exponent - 1;
            }
        }

        // if the exponent is now > 127, we have an overflow since IEEE can
        // handle larger numbers
        // than S390 can.
        if (s390Exponent > 127) {
            throw new RuntimeException( //TODO need to make a proper AnyException for this
                    "Number outside of range for double precision OS390 Float");
        } else if (s390Exponent < 0) {
            // the number is too small to represent, set it to zero
            return 0L;
        }

        // Assemble the s390BitPattern
        long s390Double = 0L;
        long s390ExponentBits = s390Exponent & 0x000000000000007FL;
        // make sure we only deal with 7 bits
        // add the exponent
        s390Double = s390ExponentBits << 56; // shift to MSB
        // add the sign
        if (!positive) {
            s390Double = s390Double | DOUBLE_SIGN_MASK;
        }
        // add the mantissa
        s390Double = s390Double | s390Mantissa;

        return s390Double;
    }
}

Related

  1. doubleToLongBits(double value)
  2. doubleToLongBits(final double d)
  3. doubleToLongBits(final double v)
  4. doubleToRawLongBits(double d)
  5. doubleToRawLongBits(double value)
  6. doubleToSortableLong(double val)
  7. doubleToSortableLong(double value)