]> git.proxmox.com Git - ceph.git/blob - ceph/src/arrow/js/src/util/math.ts
import quincy 17.2.0
[ceph.git] / ceph / src / arrow / js / src / util / math.ts
1 // Licensed to the Apache Software Foundation (ASF) under one
2 // or more contributor license agreements. See the NOTICE file
3 // distributed with this work for additional information
4 // regarding copyright ownership. The ASF licenses this file
5 // to you under the Apache License, Version 2.0 (the
6 // "License"); you may not use this file except in compliance
7 // with the License. You may obtain a copy of the License at
8 //
9 // http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing,
12 // software distributed under the License is distributed on an
13 // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 // KIND, either express or implied. See the License for the
15 // specific language governing permissions and limitations
16 // under the License.
17
18 const f64 = new Float64Array(1);
19 const u32 = new Uint32Array(f64.buffer);
20
21 /**
22 * Convert uint16 (logically a float16) to a JS float64. Inspired by numpy's `npy_half_to_double`:
23 * https://github.com/numpy/numpy/blob/5a5987291dc95376bb098be8d8e5391e89e77a2c/numpy/core/src/npymath/halffloat.c#L29
24 * @param h {number} the uint16 to convert
25 * @private
26 * @ignore
27 */
28 export function uint16ToFloat64(h: number) {
29 const expo = (h & 0x7C00) >> 10;
30 const sigf = (h & 0x03FF) / 1024;
31 const sign = (-1) ** ((h & 0x8000) >> 15);
32 switch (expo) {
33 case 0x1F: return sign * (sigf ? NaN : 1 / 0);
34 case 0x00: return sign * (sigf ? 6.103515625e-5 * sigf : 0);
35 }
36 return sign * (2 ** (expo - 15)) * (1 + sigf);
37 }
38
39 /**
40 * Convert a float64 to uint16 (assuming the float64 is logically a float16). Inspired by numpy's `npy_double_to_half`:
41 * https://github.com/numpy/numpy/blob/5a5987291dc95376bb098be8d8e5391e89e77a2c/numpy/core/src/npymath/halffloat.c#L43
42 * @param d {number} The float64 to convert
43 * @private
44 * @ignore
45 */
46 export function float64ToUint16(d: number) {
47
48 if (d !== d) { return 0x7E00; } // NaN
49
50 f64[0] = d;
51
52 // Magic numbers:
53 // 0x80000000 = 10000000 00000000 00000000 00000000 -- masks the 32nd bit
54 // 0x7ff00000 = 01111111 11110000 00000000 00000000 -- masks the 21st-31st bits
55 // 0x000fffff = 00000000 00001111 11111111 11111111 -- masks the 1st-20th bit
56
57 const sign = (u32[1] & 0x80000000) >> 16 & 0xFFFF;
58 let expo = (u32[1] & 0x7ff00000), sigf = 0x0000;
59
60 if (expo >= 0x40f00000) {
61 //
62 // If exponent overflowed, the float16 is either NaN or Infinity.
63 // Rules to propagate the sign bit: mantissa > 0 ? NaN : +/-Infinity
64 //
65 // Magic numbers:
66 // 0x40F00000 = 01000000 11110000 00000000 00000000 -- 6-bit exponent overflow
67 // 0x7C000000 = 01111100 00000000 00000000 00000000 -- masks the 27th-31st bits
68 //
69 // returns:
70 // qNaN, aka 32256 decimal, 0x7E00 hex, or 01111110 00000000 binary
71 // sNaN, aka 32000 decimal, 0x7D00 hex, or 01111101 00000000 binary
72 // +inf, aka 31744 decimal, 0x7C00 hex, or 01111100 00000000 binary
73 // -inf, aka 64512 decimal, 0xFC00 hex, or 11111100 00000000 binary
74 //
75 // If mantissa is greater than 23 bits, set to +Infinity like numpy
76 if (u32[0] > 0) {
77 expo = 0x7C00;
78 } else {
79 expo = (expo & 0x7C000000) >> 16;
80 sigf = (u32[1] & 0x000fffff) >> 10;
81 }
82 } else if (expo <= 0x3f000000) {
83 //
84 // If exponent underflowed, the float is either signed zero or subnormal.
85 //
86 // Magic numbers:
87 // 0x3F000000 = 00111111 00000000 00000000 00000000 -- 6-bit exponent underflow
88 //
89 sigf = 0x100000 + (u32[1] & 0x000fffff);
90 sigf = 0x100000 + (sigf << ((expo >> 20) - 998)) >> 21;
91 expo = 0;
92 } else {
93 //
94 // No overflow or underflow, rebase the exponent and round the mantissa
95 // Magic numbers:
96 // 0x200 = 00000010 00000000 -- masks off the 10th bit
97 //
98
99 // Ensure the first mantissa bit (the 10th one) is 1 and round
100 expo = (expo - 0x3f000000) >> 10;
101 sigf = ((u32[1] & 0x000fffff) + 0x200) >> 10;
102 }
103
104 return sign | expo | sigf & 0xFFFF;
105 }