wgblas 2.1.0 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/dist/wgblas.browser.js +1007 -43
- package/index.d.mts +26 -53
- package/index.mjs +11 -0
- package/package.json +132 -63
- package/src/classes/Complex32.d.mts +43 -0
- package/src/classes/Complex32.mjs +82 -0
- package/src/classes/Complex64.d.mts +44 -0
- package/src/classes/Complex64.mjs +76 -0
- package/src/classes/GpuMatrix.d.mts +41 -41
- package/src/classes/GpuMatrix.mjs +112 -10
- package/src/classes/GpuVector.d.mts +36 -40
- package/src/classes/GpuVector.mjs +39 -2
- package/src/cscal/cscal.d.mts +47 -0
- package/src/cscal/cscal.mjs +98 -0
- package/src/dasum/dasum.mjs +31 -15
- package/src/daxpy/daxpy.d.mts +56 -0
- package/src/daxpy/daxpy.mjs +150 -0
- package/src/dcopy/dcopy.d.mts +52 -0
- package/src/dcopy/dcopy.mjs +140 -0
- package/src/ddot/ddot.d.mts +62 -0
- package/src/ddot/ddot.mjs +184 -0
- package/src/dnrm2/dnrm2.d.mts +50 -0
- package/src/dnrm2/dnrm2.mjs +189 -0
- package/src/drot/drot.d.mts +67 -0
- package/src/drot/drot.mjs +170 -0
- package/src/drotm/drotm.d.mts +67 -0
- package/src/drotm/drotm.mjs +171 -0
- package/src/dscal/dscal.d.mts +52 -0
- package/src/dscal/dscal.mjs +119 -0
- package/src/dswap/dswap.d.mts +57 -0
- package/src/dswap/dswap.mjs +155 -0
- package/src/idamax/idamax.mjs +49 -19
- package/src/init.mjs +6 -3
- package/src/isamax/isamax.mjs +17 -14
- package/src/random/random.d.mts +37 -40
- package/src/random/random.mjs +39 -7
- package/src/sasum/sasum.mjs +13 -11
- package/src/saxpy/saxpy.mjs +9 -8
- package/src/scopy/scopy.mjs +8 -6
- package/src/sdot/sdot.mjs +13 -11
- package/src/sgemm/sgemm.d.mts +2 -2
- package/src/sgemm/sgemm.mjs +91 -35
- package/src/sgemmtr/sgemmtr.d.mts +3 -2
- package/src/sgemmtr/sgemmtr.mjs +92 -35
- package/src/sgemv/sgemv.d.mts +2 -2
- package/src/sgemv/sgemv.mjs +41 -25
- package/src/sger/sger.d.mts +2 -2
- package/src/sger/sger.mjs +38 -16
- package/src/shaders/__test_pipeline_a.wgsl +3 -0
- package/src/shaders/__test_pipeline_b.wgsl +2 -0
- package/src/shaders/cscal.wgsl +33 -0
- package/src/shaders/daxpy.wgsl +66 -0
- package/src/shaders/dcopy.wgsl +34 -0
- package/src/shaders/ddot.wgsl +106 -0
- package/src/shaders/dnrm2.wgsl +167 -0
- package/src/shaders/drot.wgsl +81 -0
- package/src/shaders/drotm.wgsl +99 -0
- package/src/shaders/dscal.wgsl +60 -0
- package/src/shaders/dswap.wgsl +38 -0
- package/src/shaders/f64/utils/add.wgsl +6 -0
- package/src/shaders/f64/utils/divide.wgsl +45 -0
- package/src/shaders/f64/utils/multiply.wgsl +19 -10
- package/src/shaders/f64/utils/sqrt.wgsl +45 -0
- package/src/shaders/index.mjs +69 -0
- package/src/shaders/reduction/scaledSumF64.wgsl +93 -0
- package/src/snrm2/snrm2.mjs +20 -14
- package/src/srot/srot.mjs +10 -7
- package/src/srotm/srotm.mjs +9 -12
- package/src/sscal/sscal.mjs +7 -7
- package/src/sswap/sswap.mjs +14 -8
- package/src/ssymm/ssymm.d.mts +5 -4
- package/src/ssymm/ssymm.mjs +142 -55
- package/src/ssymv/ssymv.d.mts +2 -2
- package/src/ssymv/ssymv.mjs +42 -23
- package/src/ssyr/ssyr.d.mts +2 -2
- package/src/ssyr/ssyr.mjs +34 -15
- package/src/ssyr2/ssyr2.d.mts +2 -2
- package/src/ssyr2/ssyr2.mjs +43 -18
- package/src/ssyr2k/ssyr2k.d.mts +3 -2
- package/src/ssyr2k/ssyr2k.mjs +132 -55
- package/src/ssyrk/ssyrk.d.mts +3 -2
- package/src/ssyrk/ssyrk.mjs +84 -33
- package/src/strmm/strmm.d.mts +5 -4
- package/src/strmm/strmm.mjs +153 -54
- package/src/strmv/strmv.d.mts +2 -2
- package/src/strmv/strmv.mjs +37 -17
- package/src/strsm/strsm.d.mts +6 -4
- package/src/strsm/strsm.mjs +418 -172
- package/src/strsv/strsv.d.mts +5 -3
- package/src/strsv/strsv.mjs +82 -31
- package/src/util/benchmark.mjs +5 -3
- package/src/util/buffer.mjs +33 -12
- package/src/util/complex.mjs +87 -0
- package/src/util/compute.mjs +14 -8
- package/src/util/device.mjs +18 -3
- package/src/util/pipeline.mjs +40 -5
- package/src/util/workgroup.mjs +23 -6
- package/src/shaders/f64add.wgsl +0 -281
package/src/shaders/f64add.wgsl
DELETED
|
@@ -1,281 +0,0 @@
|
|
|
1
|
-
// f64add: adds two doubles, each packed as a [main, aux] pair (main: f32
|
|
2
|
-
// value, aux: raw u32 bits — see src/util/f64pack.mjs; decode()/encode()
|
|
3
|
-
// below are the WGSL mirror of that file's packedToFields()/fieldsToPacked()),
|
|
4
|
-
// producing the sum as another [main, aux] pair.
|
|
5
|
-
//
|
|
6
|
-
// Implements IEEE-754 binary64 addition (align, add/subtract significands,
|
|
7
|
-
// normalize, round-to-nearest-even) using only u32 bitwise/integer
|
|
8
|
-
// arithmetic — WGSL has no 64-bit integer type or arbitrary-precision
|
|
9
|
-
// integers, so each operand's 53-bit significand is carried as a two-word
|
|
10
|
-
// (hi, lo) pair, widened by 3 bits at the bottom to hold guard/round/sticky
|
|
11
|
-
// information while aligning exponents.
|
|
12
|
-
|
|
13
|
-
const EXP_ALL_ONES: u32 = 0x7ffu;
|
|
14
|
-
const BIAS: i32 = 1023;
|
|
15
|
-
const QUIET_NAN_MANTISSA_HI: u32 = 1u << 19u; // bit51 of the 52-bit mantissa -> canonical quiet NaN
|
|
16
|
-
|
|
17
|
-
struct Fields {
|
|
18
|
-
sign: u32,
|
|
19
|
-
rawExp: u32,
|
|
20
|
-
mantissaHi: u32, // 20 bits
|
|
21
|
-
lo: u32, // 32 bits
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
// A packed [main, aux] result — aux stays a raw u32; it must never be stored
|
|
25
|
-
// as an array<f32>/treated as a real float (bit pattern can land on a NaN/
|
|
26
|
-
// Infinity exponent for perfectly ordinary doubles — an f32-typed storage
|
|
27
|
-
// slot canonicalizes/corrupts that on any round-trip). See f64pack.mjs's
|
|
28
|
-
// comment above fieldsToPacked, and dasum.wgsl's xAux/partialsAux bindings.
|
|
29
|
-
struct Packed {
|
|
30
|
-
main: f32,
|
|
31
|
-
aux: u32,
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
// Mirrors packedToFields() in f64pack.mjs.
|
|
35
|
-
fn decode(mainBits: u32, auxBits: u32) -> Fields {
|
|
36
|
-
let sign = mainBits >> 31u;
|
|
37
|
-
let expMain = (mainBits >> 23u) & 0xffu;
|
|
38
|
-
let mantMain = mainBits & 0x7fffffu;
|
|
39
|
-
|
|
40
|
-
let auxSign = auxBits >> 31u;
|
|
41
|
-
let auxExp8 = (auxBits >> 23u) & 0xffu;
|
|
42
|
-
let auxMant23 = auxBits & 0x7fffffu;
|
|
43
|
-
|
|
44
|
-
let expExtra = (auxSign << 2u) | (auxExp8 >> 6u);
|
|
45
|
-
let mantExtra29 = ((auxExp8 & 0x3fu) << 23u) | auxMant23;
|
|
46
|
-
|
|
47
|
-
let rawExp = (expMain << 3u) | expExtra;
|
|
48
|
-
let mantissaHi = mantMain >> 3u;
|
|
49
|
-
let mantTop3 = mantMain & 0x7u;
|
|
50
|
-
let lo = (mantTop3 << 29u) | mantExtra29;
|
|
51
|
-
|
|
52
|
-
return Fields(sign, rawExp, mantissaHi, lo);
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
// Mirrors fieldsToPacked() in f64pack.mjs.
|
|
56
|
-
fn encode(sign: u32, rawExp: u32, mantissaHi: u32, lo: u32) -> Packed {
|
|
57
|
-
let expMain = rawExp >> 3u;
|
|
58
|
-
let expExtra = rawExp & 0x7u;
|
|
59
|
-
|
|
60
|
-
let mantTop3 = lo >> 29u;
|
|
61
|
-
let mantMain = (mantissaHi << 3u) | mantTop3;
|
|
62
|
-
let mantExtra29 = lo & 0x1fffffffu;
|
|
63
|
-
|
|
64
|
-
let mainBits = (sign << 31u) | (expMain << 23u) | mantMain;
|
|
65
|
-
|
|
66
|
-
let auxSign = (expExtra >> 2u) & 0x1u;
|
|
67
|
-
let auxExpTop2 = expExtra & 0x3u;
|
|
68
|
-
let auxExpBot6 = mantExtra29 >> 23u;
|
|
69
|
-
let auxMant23 = mantExtra29 & 0x7fffffu;
|
|
70
|
-
let auxExp8 = (auxExpTop2 << 6u) | auxExpBot6;
|
|
71
|
-
|
|
72
|
-
let auxBits = (auxSign << 31u) | (auxExp8 << 23u) | auxMant23;
|
|
73
|
-
|
|
74
|
-
return Packed(bitcast<f32>(mainBits), auxBits);
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
struct Pair { hi: u32, lo: u32 }
|
|
78
|
-
struct Shifted { hi: u32, lo: u32, sticky: u32 }
|
|
79
|
-
|
|
80
|
-
// Two-word right shift by 0..64+ bits, folding every shifted-out 1 bit into
|
|
81
|
-
// a returned sticky flag — used only for the (potentially huge) exponent
|
|
82
|
-
// alignment shift, where exact bits can't all be kept.
|
|
83
|
-
fn shr_sticky(hi: u32, lo: u32, n: u32) -> Shifted {
|
|
84
|
-
if (n == 0u) {
|
|
85
|
-
return Shifted(hi, lo, 0u);
|
|
86
|
-
}
|
|
87
|
-
if (n >= 64u) {
|
|
88
|
-
return Shifted(0u, 0u, select(0u, 1u, hi != 0u || lo != 0u));
|
|
89
|
-
}
|
|
90
|
-
if (n < 32u) {
|
|
91
|
-
let stickyBits = lo & ((1u << n) - 1u);
|
|
92
|
-
let newLo = (lo >> n) | (hi << (32u - n));
|
|
93
|
-
let newHi = hi >> n;
|
|
94
|
-
return Shifted(newHi, newLo, select(0u, 1u, stickyBits != 0u));
|
|
95
|
-
}
|
|
96
|
-
if (n == 32u) {
|
|
97
|
-
return Shifted(0u, hi, select(0u, 1u, lo != 0u));
|
|
98
|
-
}
|
|
99
|
-
let m = n - 32u;
|
|
100
|
-
let stickyBits = lo | (hi & ((1u << m) - 1u));
|
|
101
|
-
let newLo = hi >> m;
|
|
102
|
-
return Shifted(0u, newLo, select(0u, 1u, stickyBits != 0u));
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
// Two-word left shift by 0..63 bits — used only to renormalize after
|
|
106
|
-
// cancellation, by an amount that exactly matches the leading-zero count,
|
|
107
|
-
// so nothing meaningful is ever lost off the top.
|
|
108
|
-
fn shl(hi: u32, lo: u32, n: u32) -> Pair {
|
|
109
|
-
if (n == 0u) {
|
|
110
|
-
return Pair(hi, lo);
|
|
111
|
-
}
|
|
112
|
-
if (n < 32u) {
|
|
113
|
-
let newHi = (hi << n) | (lo >> (32u - n));
|
|
114
|
-
let newLo = lo << n;
|
|
115
|
-
return Pair(newHi, newLo);
|
|
116
|
-
}
|
|
117
|
-
if (n == 32u) {
|
|
118
|
-
return Pair(lo, 0u);
|
|
119
|
-
}
|
|
120
|
-
let m = n - 32u;
|
|
121
|
-
return Pair(lo << m, 0u);
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
fn add64(aHi: u32, aLo: u32, bHi: u32, bLo: u32) -> Pair {
|
|
125
|
-
let sumLo = aLo + bLo;
|
|
126
|
-
let carry = select(0u, 1u, sumLo < aLo); // wrapped around -> there was a carry
|
|
127
|
-
let sumHi = aHi + bHi + carry;
|
|
128
|
-
return Pair(sumHi, sumLo);
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
// Assumes (aHi:aLo) >= (bHi:bLo) — callers guarantee this so no sign handling is needed.
|
|
132
|
-
fn sub64(aHi: u32, aLo: u32, bHi: u32, bLo: u32) -> Pair {
|
|
133
|
-
let borrow = select(0u, 1u, aLo < bLo);
|
|
134
|
-
let diffLo = aLo - bLo;
|
|
135
|
-
let diffHi = aHi - bHi - borrow;
|
|
136
|
-
return Pair(diffHi, diffLo);
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
fn ge64(aHi: u32, aLo: u32, bHi: u32, bLo: u32) -> bool {
|
|
140
|
-
return aHi > bHi || (aHi == bHi && aLo >= bLo);
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
// The actual IEEE-754 addition, returning decoded Fields rather than an
|
|
144
|
-
// encoded Packed pair — lets a caller that's accumulating many values in a
|
|
145
|
-
// row (e.g. dasum.wgsl's per-thread reduction loop) keep the running total
|
|
146
|
-
// in Fields form the whole time, only encoding once at the very end, instead
|
|
147
|
-
// of paying a decode+encode round-trip on every single addition. computeSum
|
|
148
|
-
// (below) is the Packed-in/Packed-out convenience wrapper around this.
|
|
149
|
-
fn addFields(a: Fields, b: Fields) -> Fields {
|
|
150
|
-
let aIsNaN = a.rawExp == EXP_ALL_ONES && (a.mantissaHi != 0u || a.lo != 0u);
|
|
151
|
-
let bIsNaN = b.rawExp == EXP_ALL_ONES && (b.mantissaHi != 0u || b.lo != 0u);
|
|
152
|
-
if (aIsNaN || bIsNaN) {
|
|
153
|
-
return Fields(0u, EXP_ALL_ONES, QUIET_NAN_MANTISSA_HI, 0u);
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
let aIsInf = a.rawExp == EXP_ALL_ONES; // mantissa==0 here since NaN is excluded above
|
|
157
|
-
let bIsInf = b.rawExp == EXP_ALL_ONES;
|
|
158
|
-
if (aIsInf && bIsInf) {
|
|
159
|
-
if (a.sign != b.sign) {
|
|
160
|
-
return Fields(0u, EXP_ALL_ONES, QUIET_NAN_MANTISSA_HI, 0u);
|
|
161
|
-
}
|
|
162
|
-
return Fields(a.sign, EXP_ALL_ONES, 0u, 0u);
|
|
163
|
-
}
|
|
164
|
-
if (aIsInf) { return Fields(a.sign, EXP_ALL_ONES, 0u, 0u); }
|
|
165
|
-
if (bIsInf) { return Fields(b.sign, EXP_ALL_ONES, 0u, 0u); }
|
|
166
|
-
|
|
167
|
-
let aIsZero = a.rawExp == 0u && a.mantissaHi == 0u && a.lo == 0u;
|
|
168
|
-
let bIsZero = b.rawExp == 0u && b.mantissaHi == 0u && b.lo == 0u;
|
|
169
|
-
if (aIsZero && bIsZero) {
|
|
170
|
-
return Fields(a.sign & b.sign, 0u, 0u, 0u);
|
|
171
|
-
}
|
|
172
|
-
if (aIsZero) { return Fields(b.sign, b.rawExp, b.mantissaHi, b.lo); }
|
|
173
|
-
if (bIsZero) { return Fields(a.sign, a.rawExp, a.mantissaHi, a.lo); }
|
|
174
|
-
|
|
175
|
-
// Effective (unbiased) exponent — subnormals share the smallest normal
|
|
176
|
-
// exponent for alignment purposes and have no implicit leading 1.
|
|
177
|
-
var expA = i32(a.rawExp) - BIAS;
|
|
178
|
-
if (a.rawExp == 0u) { expA = 1 - BIAS; }
|
|
179
|
-
var expB = i32(b.rawExp) - BIAS;
|
|
180
|
-
if (b.rawExp == 0u) { expB = 1 - BIAS; }
|
|
181
|
-
|
|
182
|
-
let implicitA = select(0u, 1u, a.rawExp != 0u);
|
|
183
|
-
let implicitB = select(0u, 1u, b.rawExp != 0u);
|
|
184
|
-
|
|
185
|
-
// Widen each 53-bit significand (implicit + 52-bit mantissa) by 3 zero
|
|
186
|
-
// bits at the bottom — room for guard/round/sticky once alignment shifts happen.
|
|
187
|
-
let sigHiA = (implicitA << 23u) | (a.mantissaHi << 3u) | (a.lo >> 29u);
|
|
188
|
-
let sigLoA = a.lo << 3u;
|
|
189
|
-
let sigHiB = (implicitB << 23u) | (b.mantissaHi << 3u) | (b.lo >> 29u);
|
|
190
|
-
let sigLoB = b.lo << 3u;
|
|
191
|
-
|
|
192
|
-
// P = the operand with the larger exponent (Q = the other); on a tie, P =
|
|
193
|
-
// whichever has the larger significand — keeps subtraction below always
|
|
194
|
-
// non-negative without needing signed magnitudes.
|
|
195
|
-
var signP: u32; var expP: i32; var sigHiP: u32; var sigLoP: u32;
|
|
196
|
-
var signQ: u32; var expQ: i32; var sigHiQ: u32; var sigLoQ: u32;
|
|
197
|
-
if (expA > expB || (expA == expB && ge64(sigHiA, sigLoA, sigHiB, sigLoB))) {
|
|
198
|
-
signP = a.sign; expP = expA; sigHiP = sigHiA; sigLoP = sigLoA;
|
|
199
|
-
signQ = b.sign; expQ = expB; sigHiQ = sigHiB; sigLoQ = sigLoB;
|
|
200
|
-
} else {
|
|
201
|
-
signP = b.sign; expP = expB; sigHiP = sigHiB; sigLoP = sigLoB;
|
|
202
|
-
signQ = a.sign; expQ = expA; sigHiQ = sigHiA; sigLoQ = sigLoA;
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
let diff = u32(expP - expQ);
|
|
206
|
-
let shiftedQ = shr_sticky(sigHiQ, sigLoQ, diff);
|
|
207
|
-
let alignedHiQ = shiftedQ.hi;
|
|
208
|
-
let alignedLoQ = shiftedQ.lo | shiftedQ.sticky; // fold sticky into bit0
|
|
209
|
-
|
|
210
|
-
var sumHi: u32; var sumLo: u32;
|
|
211
|
-
if (signP == signQ) {
|
|
212
|
-
let s = add64(sigHiP, sigLoP, alignedHiQ, alignedLoQ);
|
|
213
|
-
sumHi = s.hi; sumLo = s.lo;
|
|
214
|
-
} else {
|
|
215
|
-
let s = sub64(sigHiP, sigLoP, alignedHiQ, alignedLoQ); // P >= Q(aligned) by construction
|
|
216
|
-
sumHi = s.hi; sumLo = s.lo;
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
if (sumHi == 0u && sumLo == 0u) {
|
|
220
|
-
return Fields(0u, 0u, 0u, 0u); // exact cancellation -> +0
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
// commonExp2: per-bit scale of sumLo's bit0 in the widened representation.
|
|
224
|
-
let commonExp2 = expP - 55;
|
|
225
|
-
|
|
226
|
-
var leadPos: i32;
|
|
227
|
-
if (sumHi != 0u) {
|
|
228
|
-
leadPos = 32 + i32(31u - countLeadingZeros(sumHi));
|
|
229
|
-
} else {
|
|
230
|
-
leadPos = i32(31u - countLeadingZeros(sumLo));
|
|
231
|
-
}
|
|
232
|
-
let tentativeExp = leadPos + commonExp2;
|
|
233
|
-
var targetLSBScale = tentativeExp - 52;
|
|
234
|
-
if (tentativeExp < -1022) { targetLSBScale = -1074; }
|
|
235
|
-
let shiftAmt = targetLSBScale - commonExp2;
|
|
236
|
-
|
|
237
|
-
var keepHi: u32; var keepLo: u32;
|
|
238
|
-
if (shiftAmt <= 0) {
|
|
239
|
-
let sh = shl(sumHi, sumLo, u32(-shiftAmt)); // exact — cancellation only, never loses bits
|
|
240
|
-
keepHi = sh.hi; keepLo = sh.lo;
|
|
241
|
-
} else {
|
|
242
|
-
// Only reached without cancellation (same-sign add, or a tied-exponent
|
|
243
|
-
// subtract with no shrinkage) — shiftAmt here is always exactly 3 or 4,
|
|
244
|
-
// so the dropped bits are fully known from sumLo directly (no sticky
|
|
245
|
-
// approximation needed, unlike the Q-alignment shift above).
|
|
246
|
-
let n = u32(shiftAmt);
|
|
247
|
-
let remainder = sumLo & ((1u << n) - 1u);
|
|
248
|
-
let halfway = 1u << (n - 1u);
|
|
249
|
-
let sh = shr_sticky(sumHi, sumLo, n);
|
|
250
|
-
keepHi = sh.hi; keepLo = sh.lo;
|
|
251
|
-
if (remainder > halfway || (remainder == halfway && (keepLo & 1u) != 0u)) {
|
|
252
|
-
let inc = add64(keepHi, keepLo, 0u, 1u);
|
|
253
|
-
keepHi = inc.hi; keepLo = inc.lo;
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
var resultExpBase = targetLSBScale;
|
|
258
|
-
if ((keepHi & (1u << 21u)) != 0u) { // rounding carried past the 53-bit budget
|
|
259
|
-
let sh = shr_sticky(keepHi, keepLo, 1u); // dropped bit is guaranteed 0 here
|
|
260
|
-
keepHi = sh.hi; keepLo = sh.lo;
|
|
261
|
-
resultExpBase = resultExpBase + 1;
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
let resultSign = signP;
|
|
265
|
-
if ((keepHi & (1u << 20u)) != 0u) { // normal-shaped result
|
|
266
|
-
let unbiasedExp = 52 + resultExpBase;
|
|
267
|
-
let rawExpFinal = unbiasedExp + BIAS;
|
|
268
|
-
if (rawExpFinal >= 2047) {
|
|
269
|
-
return Fields(resultSign, EXP_ALL_ONES, 0u, 0u); // overflow -> Infinity
|
|
270
|
-
}
|
|
271
|
-
return Fields(resultSign, u32(rawExpFinal), keepHi & 0xfffffu, keepLo);
|
|
272
|
-
}
|
|
273
|
-
return Fields(resultSign, 0u, keepHi & 0xfffffu, keepLo); // subnormal result
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
// Packed-in/Packed-out convenience wrapper around addFields — encodes once,
|
|
277
|
-
// after the math, rather than addFields itself needing to know about Packed.
|
|
278
|
-
fn computeSum(a: Fields, b: Fields) -> Packed {
|
|
279
|
-
let f = addFields(a, b);
|
|
280
|
-
return encode(f.sign, f.rawExp, f.mantissaHi, f.lo);
|
|
281
|
-
}
|