/** * Copyright (c) 2010-2016 by the respective copyright holders. * * 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 */ package org.openhab.binding.souliss.internal.network.udp; /** * Helper class to conver half precision float to int int are used on analogue * typicals (2 bytes) and should be reversed because of endianess * * @author http://stackoverflow.com/users/237321/x4u * * @since 1.7.0 */ public class HalfFloatUtils { public static boolean isNaN(float x) { return x != x; } // ignores the higher 16 bits public static float toFloat(int hbits) { int mant = hbits & 0x03ff; // 10 bits mantissa int exp = hbits & 0x7c00; // 5 bits exponent if (exp == 0x7c00) { exp = 0x3fc00; // -> NaN/Inf } else if (exp != 0) // normalized value { exp += 0x1c000; // exp - 15 + 127 if (mant == 0 && exp > 0x1c400) { return Float.intBitsToFloat((hbits & 0x8000) << 16 | exp << 13 | 0x3ff); } } else if (mant != 0) // && exp==0 -> subnormal { exp = 0x1c400; // make it normal do { mant <<= 1; // mantissa * 2 exp -= 0x400; // decrease exp by 1 } while ((mant & 0x400) == 0); // while not normal mant &= 0x3ff; // discard subnormal bit } // else +/-0 -> +/-0 return Float.intBitsToFloat( // combine all parts (hbits & 0x8000) << 16 // sign << ( 31 - 15 ) | (exp | mant) << 13); // value << ( 23 - 10 ) } // returns all higher 16 bits as 0 for all results public static int fromFloat(float fval) { int fbits = Float.floatToIntBits(fval); int sign = fbits >>> 16 & 0x8000; // sign only int val = (fbits & 0x7fffffff) + 0x1000; // rounded value if (val >= 0x47800000) // might be or become NaN/Inf { // avoid Inf due to rounding if ((fbits & 0x7fffffff) >= 0x47800000) { // is or must become // NaN/Inf if (val < 0x7f800000) { return sign | 0x7c00; // make it +/-Inf } return sign | 0x7c00 | // remains +/-Inf or NaN (fbits & 0x007fffff) >>> 13; // keep NaN (and Inf) bits } return sign | 0x7bff; // unrounded not quite Inf } if (val >= 0x38800000) { return sign | val - 0x38000000 >>> 13; // exp - 127 + 15 } if (val < 0x33000000) { return sign; // becomes +/-0 } val = (fbits & 0x7fffffff) >>> 23; // tmp exp for subnormal calc return sign | ((fbits & 0x7fffff | 0x800000) // add subnormal bit + (0x800000 >>> val - 102) // round depending on cut off >>> 126 - val); // div by 2^(1-(exp-127+15)) and >> 13 | exp=0 } }