1
2
3
4
5 package strconv
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 import (
21 "math/bits"
22 )
23
24 func eiselLemire64(man uint64, exp10 int, neg bool) (f float64, ok bool) {
25
26
27
28
29 if man == 0 {
30 if neg {
31 f = float64frombits(0x8000000000000000)
32 }
33 return f, true
34 }
35 pow, exp2, ok := pow10(exp10)
36 if !ok {
37 return 0, false
38 }
39
40
41 clz := bits.LeadingZeros64(man)
42 man <<= uint(clz)
43 retExp2 := uint64(exp2+63-float64Bias) - uint64(clz)
44
45
46 xHi, xLo := bits.Mul64(man, pow.Hi)
47
48
49 if xHi&0x1FF == 0x1FF && xLo+man < man {
50 yHi, yLo := bits.Mul64(man, pow.Lo)
51 mergedHi, mergedLo := xHi, xLo+yHi
52 if mergedLo < xLo {
53 mergedHi++
54 }
55 if mergedHi&0x1FF == 0x1FF && mergedLo+1 == 0 && yLo+man < man {
56 return 0, false
57 }
58 xHi, xLo = mergedHi, mergedLo
59 }
60
61
62 msb := xHi >> 63
63 retMantissa := xHi >> (msb + 9)
64 retExp2 -= 1 ^ msb
65
66
67 if xLo == 0 && xHi&0x1FF == 0 && retMantissa&3 == 1 {
68 return 0, false
69 }
70
71
72 retMantissa += retMantissa & 1
73 retMantissa >>= 1
74 if retMantissa>>53 > 0 {
75 retMantissa >>= 1
76 retExp2 += 1
77 }
78
79
80
81
82
83 if retExp2-1 >= 0x7FF-1 {
84 return 0, false
85 }
86 retBits := retExp2<<float64MantBits | retMantissa&(1<<float64MantBits-1)
87 if neg {
88 retBits |= 0x8000000000000000
89 }
90 return float64frombits(retBits), true
91 }
92
93 func eiselLemire32(man uint64, exp10 int, neg bool) (f float32, ok bool) {
94
95
96
97
98
99
100
101
102
103
104 if man == 0 {
105 if neg {
106 f = float32frombits(0x80000000)
107 }
108 return f, true
109 }
110 pow, exp2, ok := pow10(exp10)
111 if !ok {
112 return 0, false
113 }
114
115
116 clz := bits.LeadingZeros64(man)
117 man <<= uint(clz)
118 retExp2 := uint64(exp2+63-float32Bias) - uint64(clz)
119
120
121 xHi, xLo := bits.Mul64(man, pow.Hi)
122
123
124 if xHi&0x3FFFFFFFFF == 0x3FFFFFFFFF && xLo+man < man {
125 yHi, yLo := bits.Mul64(man, pow.Lo)
126 mergedHi, mergedLo := xHi, xLo+yHi
127 if mergedLo < xLo {
128 mergedHi++
129 }
130 if mergedHi&0x3FFFFFFFFF == 0x3FFFFFFFFF && mergedLo+1 == 0 && yLo+man < man {
131 return 0, false
132 }
133 xHi, xLo = mergedHi, mergedLo
134 }
135
136
137 msb := xHi >> 63
138 retMantissa := xHi >> (msb + 38)
139 retExp2 -= 1 ^ msb
140
141
142 if xLo == 0 && xHi&0x3FFFFFFFFF == 0 && retMantissa&3 == 1 {
143 return 0, false
144 }
145
146
147 retMantissa += retMantissa & 1
148 retMantissa >>= 1
149 if retMantissa>>24 > 0 {
150 retMantissa >>= 1
151 retExp2 += 1
152 }
153
154
155
156
157
158 if retExp2-1 >= 0xFF-1 {
159 return 0, false
160 }
161 retBits := retExp2<<float32MantBits | retMantissa&(1<<float32MantBits-1)
162 if neg {
163 retBits |= 0x80000000
164 }
165 return float32frombits(uint32(retBits)), true
166 }
167
View as plain text