]> git.basschouten.com Git - openhab-addons.git/blob
548256ab61d55b133fb0eba96ae6457e27755dd7
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2023 Contributors to the openHAB project
3  *
4  * See the NOTICE file(s) distributed with this work for additional
5  * information.
6  *
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
10  *
11  * SPDX-License-Identifier: EPL-2.0
12  */
13 package org.openhab.binding.souliss.internal.protocol;
14
15 import org.eclipse.jdt.annotation.NonNullByDefault;
16
17 /**
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
21  *
22  * @author Tonino Fazio - Initial contribution
23  * @author Luca Calcaterra - Refactor for OH3
24  */
25 @NonNullByDefault
26 public final class HalfFloatUtils {
27
28     public static boolean isNaN(float x) {
29         return x != x;
30     }
31
32     // ignores the higher 16 bits
33     public static float toFloat(int hbits) {
34         // 10 bits mantissa
35         int mant = hbits & 0x03ff;
36         // 5 bits exponent
37         int exp = hbits & 0x7c00;
38         if (exp == 0x7c00) {
39             // -> NaN/Inf
40             exp = 0x3fc00;
41             // normalized value
42         } else if (exp != 0) {
43             // exp - 15 + 127
44             exp += 0x1c000;
45             if (mant == 0 && exp > 0x1c400) {
46                 return Float.intBitsToFloat((hbits & 0x8000) << 16 | exp << 13 | 0x3ff);
47             }
48             // && exp==0 -> subnormal
49         } else if (mant != 0) {
50             // make it normal
51             exp = 0x1c400;
52             do {
53                 // mantissa * 2
54                 mant <<= 1;
55                 // decrease exp by 1
56                 exp -= 0x400;
57                 // while not normal
58             } while ((mant & 0x400) == 0);
59             // discard subnormal bit
60             mant &= 0x3ff;
61             // else +/-0 -> +/-0
62         }
63         // combine all parts
64         return Float.intBitsToFloat(
65                 // sign << ( 31 - 15 )
66                 (hbits & 0x8000) << 16
67                         // value << ( 23 - 10 )
68                         | (exp | mant) << 13);
69     }
70
71     // returns all higher 16 bits as 0 for all results
72     public static int fromFloat(float fval) {
73         var fbits = Float.floatToIntBits(fval);
74         // sign only
75         int sign = fbits >>> 16 & 0x8000;
76         // rounded value
77         int val = (fbits & 0x7fffffff) + 0x1000;
78
79         // might be or become NaN/Inf
80         if (val >= 0x47800000)
81         // avoid Inf due to rounding
82         {
83             // is or must become
84             // NaN/Inf
85             if ((fbits & 0x7fffffff) >= 0x47800000) {
86                 if (val < 0x7f800000) {
87                     // make it +/-Inf
88                     return sign | 0x7c00;
89                 }
90                 // remains +/-Inf or NaN
91                 return sign | 0x7c00 |
92                 // keep NaN (and Inf) bits
93                         (fbits & 0x007fffff) >>> 13;
94             }
95             // unrounded not quite Inf
96             return sign | 0x7bff;
97         }
98         if (val >= 0x38800000) {
99             // exp - 127 + 15
100             return sign | val - 0x38000000 >>> 13;
101         }
102         if (val < 0x33000000) {
103             // becomes +/-0
104             return sign;
105         }
106         // tmp exp for subnormal calc
107         val = (fbits & 0x7fffffff) >>> 23;
108         // add subnormal bit
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
113                 >>> 126 - val);
114     }
115 }