2 * Copyright (c) 2010-2023 Contributors to the openHAB project
4 * See the NOTICE file(s) distributed with this work for additional
7 * This program and the accompanying materials are made available under the
8 * terms of the Eclipse Public License 2.0 which is available at
9 * http://www.eclipse.org/legal/epl-2.0
11 * SPDX-License-Identifier: EPL-2.0
13 package org.openhab.binding.souliss.internal.protocol;
15 import org.eclipse.jdt.annotation.NonNullByDefault;
18 * Helper class to conver half precision float to int int are used on analogue
19 * typicals (2 bytes) and should be reversed because of endianess
20 * http://stackoverflow.com/users/237321/x4u
22 * @author Tonino Fazio - Initial contribution
23 * @author Luca Calcaterra - Refactor for OH3
26 public final class HalfFloatUtils {
28 public static boolean isNaN(float x) {
32 // ignores the higher 16 bits
33 public static float toFloat(int hbits) {
35 int mant = hbits & 0x03ff;
37 int exp = hbits & 0x7c00;
42 } else if (exp != 0) {
45 if (mant == 0 && exp > 0x1c400) {
46 return Float.intBitsToFloat((hbits & 0x8000) << 16 | exp << 13 | 0x3ff);
48 // && exp==0 -> subnormal
49 } else if (mant != 0) {
58 } while ((mant & 0x400) == 0);
59 // discard subnormal bit
64 return Float.intBitsToFloat(
65 // sign << ( 31 - 15 )
66 (hbits & 0x8000) << 16
67 // value << ( 23 - 10 )
68 | (exp | mant) << 13);
71 // returns all higher 16 bits as 0 for all results
72 public static int fromFloat(float fval) {
73 var fbits = Float.floatToIntBits(fval);
75 int sign = fbits >>> 16 & 0x8000;
77 int val = (fbits & 0x7fffffff) + 0x1000;
79 // might be or become NaN/Inf
80 if (val >= 0x47800000)
81 // avoid Inf due to rounding
85 if ((fbits & 0x7fffffff) >= 0x47800000) {
86 if (val < 0x7f800000) {
90 // remains +/-Inf or NaN
91 return sign | 0x7c00 |
92 // keep NaN (and Inf) bits
93 (fbits & 0x007fffff) >>> 13;
95 // unrounded not quite Inf
98 if (val >= 0x38800000) {
100 return sign | val - 0x38000000 >>> 13;
102 if (val < 0x33000000) {
106 // tmp exp for subnormal calc
107 val = (fbits & 0x7fffffff) >>> 23;
109 return sign | ((fbits & 0x7fffff | 0x800000)
110 // round depending on cut off
111 + (0x800000 >>> val - 102)
112 // div by 2^(1-(exp-127+15)) and >> 13 | exp=0