-
Notifications
You must be signed in to change notification settings - Fork 14
/
f128_mul.go
241 lines (227 loc) · 6.44 KB
/
f128_mul.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
package eos_math
func (a Float128) Mul(b Float128) Float128 {
var uiA64, uiA0 uint64
var signA bool
var expA int32
var sigA Uint128
var uiB64, uiB0 uint64
var signB bool
var expB int32
var sigB Uint128
var signZ bool
var magBits uint64
var normExpSig exp32_sig128
var expZ int32
var sig256Z [4]uint64
var sigZExtra uint64
var sigZ Uint128
var sig128Extra uint128Extra
var uiZ Uint128
var uZ Float128
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
uiA64 = a.High
uiA0 = a.Low
signA = signF128UI64(uiA64)
expA = int32(expF128UI64(uiA64))
sigA.High = fracF128UI64(uiA64)
sigA.Low = uiA0
uiB64 = b.High
uiB0 = b.Low
signB = signF128UI64(uiB64)
expB = int32(expF128UI64(uiB64))
sigB.High = fracF128UI64(uiB64)
sigB.Low = uiB0
//signZ = signA ^ signB
if (signA && signB) || (signA == false && signB == false) {
signZ = false
} else {
signZ = true
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if expA == 0x7FFF {
if (sigA.High|sigA.Low) != 0 || ((expB == 0x7FFF) && (sigB.High|sigB.Low) != 0) {
goto propagateNaN
}
magBits = uint64(expB) | sigB.High | sigB.Low
goto infArg
}
if expB == 0x7FFF {
if sigB.High|sigB.Low != 0 {
goto propagateNaN
}
magBits = uint64(expA) | sigA.High | sigA.Low
goto infArg
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if expA == 0 {
if (sigA.High | sigA.Low) == 0 {
goto zero
}
normExpSig = softfloat_normSubnormalF128Sig(sigA.High, sigA.Low)
expA = normExpSig.exp
sigA = normExpSig.sig
}
if expB == 0 {
if (sigB.High | sigB.Low) == 0 {
goto zero
}
normExpSig = softfloat_normSubnormalF128Sig(sigB.High, sigB.Low)
expB = normExpSig.exp
sigB = normExpSig.sig
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
expZ = expA + expB - 0x4000
sigA.High |= uint64(0x0001000000000000)
sigB = softfloat_shortShiftLeft128(sigB.High, sigB.Low, 16)
sig256Z = softfloat_mul128To256M(sigA.High, sigA.Low, sigB.High, sigB.Low, sig256Z) //TODO
//sigZExtra = sig256Z[indexWord( 4, 1 )] | (sig256Z[indexWord( 4, 0 )] != 0)
if sig256Z[indexWord(4, 0)] != 0 {
sigZExtra = sig256Z[indexWord(4, 1)] | 1
} else {
sigZExtra = sig256Z[indexWord(4, 1)] | 0
}
sigZ = softfloat_add128(sig256Z[indexWord(4, 3)], sig256Z[indexWord(4, 2)], sigA.High, sigA.Low)
if uint64(0x0002000000000000) <= sigZ.High {
expZ += 1
sig128Extra = softfloat_shortShiftRightJam128Extra(sigZ.High, sigZ.Low, sigZExtra, 1)
sigZ = sig128Extra.v
sigZExtra = sig128Extra.extra
}
return softfloat_roundPackToF128(signZ, expZ, sigZ.High, sigZ.Low, sigZExtra)
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
propagateNaN:
uiZ = softfloat_propagateNaNF128UI(uiA64, uiA0, uiB64, uiB0)
goto uiZ
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
infArg:
if magBits == 0 {
softfloat_raiseFlags(softfloat_flag_invalid)
uiZ.High = defaultNaNF128UI64
uiZ.Low = defaultNaNF128UI0
goto uiZ
}
//uiZ.High = packToF128UI64( signZ, 0x7FFF, 0 )
if signZ {
uiZ.High = packToF128UI64(1, 0x7FFF, 0)
} else {
uiZ.High = packToF128UI64(0, 0x7FFF, 0)
}
goto uiZ0
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
zero:
//uiZ.High = packToF128UI64( signZ, 0, 0 );
if signZ {
uiZ.High = packToF128UI64(1, 0, 0)
} else {
uiZ.High = packToF128UI64(0, 0, 0)
}
uiZ0:
uiZ.Low = 0
uiZ:
uZ.High = uiZ.High
uZ.Low = uiZ.Low
return uZ
}
//#define wordIncr 1
//#define indexWord( total, n ) (n)
//#define indexWordHi( total ) ((total) - 1)
//#define indexWordLo( total ) 0
//#define indexMultiword( total, m, n ) (n)
//#define indexMultiwordHi( total, n ) ((total) - (n))
//#define indexMultiwordLo( total, n ) 0
//#define indexMultiwordHiBut( total, n ) (n)
//#define indexMultiwordLoBut( total, n ) 0
//#define INIT_UINTM4( v3, v2, v1, v0 ) { v0, v1, v2, v3 }
func indexWord(total, n uint8) uint8 {
return n
}
func softfloat_normSubnormalF128Sig(sig64, sig0 uint64) exp32_sig128 {
var shiftDist int8
var z exp32_sig128
if sig64 == 0 {
shiftDist = int8(softfloat_countLeadingZeros64(sig0)) - 15
z.exp = int32(-63 - shiftDist)
if shiftDist < 0 {
z.sig.High = sig0 >> uint8(-shiftDist)
z.sig.Low = sig0 << uint8(shiftDist&63)
} else {
z.sig.High = sig0 << uint8(shiftDist)
z.sig.Low = 0
}
} else {
shiftDist = int8(softfloat_countLeadingZeros64(sig64)) - 15
z.exp = int32(1 - shiftDist)
z.sig = softfloat_shortShiftLeft128(sig64, sig0, uint8(shiftDist))
}
return z
}
func softfloat_mul128To256M(a64, a0, b64, b0 uint64, zPtr [4]uint64) [4]uint64 {
var p0, p64, p128 Uint128
var z64, z128, z192 uint64
p0 = softfloat_mul64To128(a0, b0)
zPtr[indexWord(4, 0)] = p0.Low
p64 = softfloat_mul64To128(a64, b0)
z64 = p64.Low + p0.High
//z128 = p64.High + (z64 < p64.Low)
if z64 < p64.Low {
z128 = p64.High + 1
} else {
z128 = p64.High
}
p128 = softfloat_mul64To128(a64, b64)
z128 += p128.Low
//z192 = p128.High + (z128 < p128.Low)
if z128 < p128.Low {
z192 = p128.High + 1
} else {
z192 = p128.High
}
p64 = softfloat_mul64To128(a0, b64)
z64 += p64.Low
zPtr[indexWord(4, 1)] = z64
//p64.High += (z64 < p64.Low);
if z64 < p64.Low {
p64.High += 1
}
z128 += p64.High
zPtr[indexWord(4, 2)] = z128
//zPtr[indexWord( 4, 3 )] = z192 + (z128 < p64.High)
if z128 < p64.High {
zPtr[indexWord(4, 3)] = z192 + 1
} else {
zPtr[indexWord(4, 3)] = z192
}
return zPtr
}
func softfloat_mul64To128(a, b uint64) Uint128 {
var a32, a0, b32, b0 uint32
var z Uint128
var mid1, mid uint64
a32 = uint32(a >> 32)
a0 = uint32(a)
b32 = uint32(b >> 32)
b0 = uint32(b)
z.Low = uint64(a0) * uint64(b0)
mid1 = uint64(a32) * uint64(b0)
mid = mid1 + uint64(a0)*uint64(b32)
z.High = uint64(a32) * uint64(b32)
if mid < mid1 {
z.High += uint64(1)<<32 | mid>>32
} else {
z.High += uint64(0)<<32 | mid>>32
}
mid <<= 32
z.Low += mid
//z.High += (z.Low < mid)
if z.Low < mid {
z.High += 1
}
return z
}