annotate libgo/go/strconv/atof.go @ 158:494b0b89df80 default tip

...
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Mon, 25 May 2020 18:13:55 +0900
parents 1830386684a0
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
111
kono
parents:
diff changeset
1 // Copyright 2009 The Go Authors. All rights reserved.
kono
parents:
diff changeset
2 // Use of this source code is governed by a BSD-style
kono
parents:
diff changeset
3 // license that can be found in the LICENSE file.
kono
parents:
diff changeset
4
kono
parents:
diff changeset
5 package strconv
kono
parents:
diff changeset
6
kono
parents:
diff changeset
7 // decimal to binary floating point conversion.
kono
parents:
diff changeset
8 // Algorithm:
kono
parents:
diff changeset
9 // 1) Store input in multiprecision decimal.
kono
parents:
diff changeset
10 // 2) Multiply/divide decimal by powers of two until in range [0.5, 1)
kono
parents:
diff changeset
11 // 3) Multiply by 2^precision and round to get mantissa.
kono
parents:
diff changeset
12
kono
parents:
diff changeset
13 import "math"
kono
parents:
diff changeset
14 import "runtime"
kono
parents:
diff changeset
15
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
16 var optimize = true // set to false to force slow-path conversions for testing
111
kono
parents:
diff changeset
17
kono
parents:
diff changeset
18 func equalIgnoreCase(s1, s2 string) bool {
kono
parents:
diff changeset
19 if len(s1) != len(s2) {
kono
parents:
diff changeset
20 return false
kono
parents:
diff changeset
21 }
kono
parents:
diff changeset
22 for i := 0; i < len(s1); i++ {
kono
parents:
diff changeset
23 c1 := s1[i]
kono
parents:
diff changeset
24 if 'A' <= c1 && c1 <= 'Z' {
kono
parents:
diff changeset
25 c1 += 'a' - 'A'
kono
parents:
diff changeset
26 }
kono
parents:
diff changeset
27 c2 := s2[i]
kono
parents:
diff changeset
28 if 'A' <= c2 && c2 <= 'Z' {
kono
parents:
diff changeset
29 c2 += 'a' - 'A'
kono
parents:
diff changeset
30 }
kono
parents:
diff changeset
31 if c1 != c2 {
kono
parents:
diff changeset
32 return false
kono
parents:
diff changeset
33 }
kono
parents:
diff changeset
34 }
kono
parents:
diff changeset
35 return true
kono
parents:
diff changeset
36 }
kono
parents:
diff changeset
37
kono
parents:
diff changeset
38 func special(s string) (f float64, ok bool) {
kono
parents:
diff changeset
39 if len(s) == 0 {
kono
parents:
diff changeset
40 return
kono
parents:
diff changeset
41 }
kono
parents:
diff changeset
42 switch s[0] {
kono
parents:
diff changeset
43 default:
kono
parents:
diff changeset
44 return
kono
parents:
diff changeset
45 case '+':
kono
parents:
diff changeset
46 if equalIgnoreCase(s, "+inf") || equalIgnoreCase(s, "+infinity") {
kono
parents:
diff changeset
47 return math.Inf(1), true
kono
parents:
diff changeset
48 }
kono
parents:
diff changeset
49 case '-':
kono
parents:
diff changeset
50 if equalIgnoreCase(s, "-inf") || equalIgnoreCase(s, "-infinity") {
kono
parents:
diff changeset
51 return math.Inf(-1), true
kono
parents:
diff changeset
52 }
kono
parents:
diff changeset
53 case 'n', 'N':
kono
parents:
diff changeset
54 if equalIgnoreCase(s, "nan") {
kono
parents:
diff changeset
55 return math.NaN(), true
kono
parents:
diff changeset
56 }
kono
parents:
diff changeset
57 case 'i', 'I':
kono
parents:
diff changeset
58 if equalIgnoreCase(s, "inf") || equalIgnoreCase(s, "infinity") {
kono
parents:
diff changeset
59 return math.Inf(1), true
kono
parents:
diff changeset
60 }
kono
parents:
diff changeset
61 }
kono
parents:
diff changeset
62 return
kono
parents:
diff changeset
63 }
kono
parents:
diff changeset
64
kono
parents:
diff changeset
65 func (b *decimal) set(s string) (ok bool) {
kono
parents:
diff changeset
66 i := 0
kono
parents:
diff changeset
67 b.neg = false
kono
parents:
diff changeset
68 b.trunc = false
kono
parents:
diff changeset
69
kono
parents:
diff changeset
70 // optional sign
kono
parents:
diff changeset
71 if i >= len(s) {
kono
parents:
diff changeset
72 return
kono
parents:
diff changeset
73 }
kono
parents:
diff changeset
74 switch {
kono
parents:
diff changeset
75 case s[i] == '+':
kono
parents:
diff changeset
76 i++
kono
parents:
diff changeset
77 case s[i] == '-':
kono
parents:
diff changeset
78 b.neg = true
kono
parents:
diff changeset
79 i++
kono
parents:
diff changeset
80 }
kono
parents:
diff changeset
81
kono
parents:
diff changeset
82 // digits
kono
parents:
diff changeset
83 sawdot := false
kono
parents:
diff changeset
84 sawdigits := false
kono
parents:
diff changeset
85 for ; i < len(s); i++ {
kono
parents:
diff changeset
86 switch {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
87 case s[i] == '_':
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
88 // readFloat already checked underscores
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
89 continue
111
kono
parents:
diff changeset
90 case s[i] == '.':
kono
parents:
diff changeset
91 if sawdot {
kono
parents:
diff changeset
92 return
kono
parents:
diff changeset
93 }
kono
parents:
diff changeset
94 sawdot = true
kono
parents:
diff changeset
95 b.dp = b.nd
kono
parents:
diff changeset
96 continue
kono
parents:
diff changeset
97
kono
parents:
diff changeset
98 case '0' <= s[i] && s[i] <= '9':
kono
parents:
diff changeset
99 sawdigits = true
kono
parents:
diff changeset
100 if s[i] == '0' && b.nd == 0 { // ignore leading zeros
kono
parents:
diff changeset
101 b.dp--
kono
parents:
diff changeset
102 continue
kono
parents:
diff changeset
103 }
kono
parents:
diff changeset
104 if b.nd < len(b.d) {
kono
parents:
diff changeset
105 b.d[b.nd] = s[i]
kono
parents:
diff changeset
106 b.nd++
kono
parents:
diff changeset
107 } else if s[i] != '0' {
kono
parents:
diff changeset
108 b.trunc = true
kono
parents:
diff changeset
109 }
kono
parents:
diff changeset
110 continue
kono
parents:
diff changeset
111 }
kono
parents:
diff changeset
112 break
kono
parents:
diff changeset
113 }
kono
parents:
diff changeset
114 if !sawdigits {
kono
parents:
diff changeset
115 return
kono
parents:
diff changeset
116 }
kono
parents:
diff changeset
117 if !sawdot {
kono
parents:
diff changeset
118 b.dp = b.nd
kono
parents:
diff changeset
119 }
kono
parents:
diff changeset
120
kono
parents:
diff changeset
121 // optional exponent moves decimal point.
kono
parents:
diff changeset
122 // if we read a very large, very long number,
kono
parents:
diff changeset
123 // just be sure to move the decimal point by
kono
parents:
diff changeset
124 // a lot (say, 100000). it doesn't matter if it's
kono
parents:
diff changeset
125 // not the exact number.
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
126 if i < len(s) && lower(s[i]) == 'e' {
111
kono
parents:
diff changeset
127 i++
kono
parents:
diff changeset
128 if i >= len(s) {
kono
parents:
diff changeset
129 return
kono
parents:
diff changeset
130 }
kono
parents:
diff changeset
131 esign := 1
kono
parents:
diff changeset
132 if s[i] == '+' {
kono
parents:
diff changeset
133 i++
kono
parents:
diff changeset
134 } else if s[i] == '-' {
kono
parents:
diff changeset
135 i++
kono
parents:
diff changeset
136 esign = -1
kono
parents:
diff changeset
137 }
kono
parents:
diff changeset
138 if i >= len(s) || s[i] < '0' || s[i] > '9' {
kono
parents:
diff changeset
139 return
kono
parents:
diff changeset
140 }
kono
parents:
diff changeset
141 e := 0
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
142 for ; i < len(s) && ('0' <= s[i] && s[i] <= '9' || s[i] == '_'); i++ {
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
143 if s[i] == '_' {
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
144 // readFloat already checked underscores
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
145 continue
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
146 }
111
kono
parents:
diff changeset
147 if e < 10000 {
kono
parents:
diff changeset
148 e = e*10 + int(s[i]) - '0'
kono
parents:
diff changeset
149 }
kono
parents:
diff changeset
150 }
kono
parents:
diff changeset
151 b.dp += e * esign
kono
parents:
diff changeset
152 }
kono
parents:
diff changeset
153
kono
parents:
diff changeset
154 if i != len(s) {
kono
parents:
diff changeset
155 return
kono
parents:
diff changeset
156 }
kono
parents:
diff changeset
157
kono
parents:
diff changeset
158 ok = true
kono
parents:
diff changeset
159 return
kono
parents:
diff changeset
160 }
kono
parents:
diff changeset
161
kono
parents:
diff changeset
162 // readFloat reads a decimal mantissa and exponent from a float
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
163 // string representation. It returns ok==false if the number
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
164 // is invalid.
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
165 func readFloat(s string) (mantissa uint64, exp int, neg, trunc, hex, ok bool) {
111
kono
parents:
diff changeset
166 i := 0
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
167 underscores := false
111
kono
parents:
diff changeset
168
kono
parents:
diff changeset
169 // optional sign
kono
parents:
diff changeset
170 if i >= len(s) {
kono
parents:
diff changeset
171 return
kono
parents:
diff changeset
172 }
kono
parents:
diff changeset
173 switch {
kono
parents:
diff changeset
174 case s[i] == '+':
kono
parents:
diff changeset
175 i++
kono
parents:
diff changeset
176 case s[i] == '-':
kono
parents:
diff changeset
177 neg = true
kono
parents:
diff changeset
178 i++
kono
parents:
diff changeset
179 }
kono
parents:
diff changeset
180
kono
parents:
diff changeset
181 // digits
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
182 base := uint64(10)
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
183 maxMantDigits := 19 // 10^19 fits in uint64
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
184 expChar := byte('e')
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
185 if i+2 < len(s) && s[i] == '0' && lower(s[i+1]) == 'x' {
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
186 base = 16
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
187 maxMantDigits = 16 // 16^16 fits in uint64
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
188 i += 2
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
189 expChar = 'p'
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
190 hex = true
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
191 }
111
kono
parents:
diff changeset
192 sawdot := false
kono
parents:
diff changeset
193 sawdigits := false
kono
parents:
diff changeset
194 nd := 0
kono
parents:
diff changeset
195 ndMant := 0
kono
parents:
diff changeset
196 dp := 0
kono
parents:
diff changeset
197 for ; i < len(s); i++ {
kono
parents:
diff changeset
198 switch c := s[i]; true {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
199 case c == '_':
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
200 underscores = true
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
201 continue
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
202
111
kono
parents:
diff changeset
203 case c == '.':
kono
parents:
diff changeset
204 if sawdot {
kono
parents:
diff changeset
205 return
kono
parents:
diff changeset
206 }
kono
parents:
diff changeset
207 sawdot = true
kono
parents:
diff changeset
208 dp = nd
kono
parents:
diff changeset
209 continue
kono
parents:
diff changeset
210
kono
parents:
diff changeset
211 case '0' <= c && c <= '9':
kono
parents:
diff changeset
212 sawdigits = true
kono
parents:
diff changeset
213 if c == '0' && nd == 0 { // ignore leading zeros
kono
parents:
diff changeset
214 dp--
kono
parents:
diff changeset
215 continue
kono
parents:
diff changeset
216 }
kono
parents:
diff changeset
217 nd++
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
218 if ndMant < maxMantDigits {
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
219 mantissa *= base
111
kono
parents:
diff changeset
220 mantissa += uint64(c - '0')
kono
parents:
diff changeset
221 ndMant++
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
222 } else if c != '0' {
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
223 trunc = true
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
224 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
225 continue
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
226
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
227 case base == 16 && 'a' <= lower(c) && lower(c) <= 'f':
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
228 sawdigits = true
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
229 nd++
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
230 if ndMant < maxMantDigits {
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
231 mantissa *= 16
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
232 mantissa += uint64(lower(c) - 'a' + 10)
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
233 ndMant++
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
234 } else {
111
kono
parents:
diff changeset
235 trunc = true
kono
parents:
diff changeset
236 }
kono
parents:
diff changeset
237 continue
kono
parents:
diff changeset
238 }
kono
parents:
diff changeset
239 break
kono
parents:
diff changeset
240 }
kono
parents:
diff changeset
241 if !sawdigits {
kono
parents:
diff changeset
242 return
kono
parents:
diff changeset
243 }
kono
parents:
diff changeset
244 if !sawdot {
kono
parents:
diff changeset
245 dp = nd
kono
parents:
diff changeset
246 }
kono
parents:
diff changeset
247
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
248 if base == 16 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
249 dp *= 4
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
250 ndMant *= 4
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
251 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
252
111
kono
parents:
diff changeset
253 // optional exponent moves decimal point.
kono
parents:
diff changeset
254 // if we read a very large, very long number,
kono
parents:
diff changeset
255 // just be sure to move the decimal point by
kono
parents:
diff changeset
256 // a lot (say, 100000). it doesn't matter if it's
kono
parents:
diff changeset
257 // not the exact number.
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
258 if i < len(s) && lower(s[i]) == expChar {
111
kono
parents:
diff changeset
259 i++
kono
parents:
diff changeset
260 if i >= len(s) {
kono
parents:
diff changeset
261 return
kono
parents:
diff changeset
262 }
kono
parents:
diff changeset
263 esign := 1
kono
parents:
diff changeset
264 if s[i] == '+' {
kono
parents:
diff changeset
265 i++
kono
parents:
diff changeset
266 } else if s[i] == '-' {
kono
parents:
diff changeset
267 i++
kono
parents:
diff changeset
268 esign = -1
kono
parents:
diff changeset
269 }
kono
parents:
diff changeset
270 if i >= len(s) || s[i] < '0' || s[i] > '9' {
kono
parents:
diff changeset
271 return
kono
parents:
diff changeset
272 }
kono
parents:
diff changeset
273 e := 0
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
274 for ; i < len(s) && ('0' <= s[i] && s[i] <= '9' || s[i] == '_'); i++ {
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
275 if s[i] == '_' {
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
276 underscores = true
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
277 continue
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
278 }
111
kono
parents:
diff changeset
279 if e < 10000 {
kono
parents:
diff changeset
280 e = e*10 + int(s[i]) - '0'
kono
parents:
diff changeset
281 }
kono
parents:
diff changeset
282 }
kono
parents:
diff changeset
283 dp += e * esign
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
284 } else if base == 16 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
285 // Must have exponent.
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
286 return
111
kono
parents:
diff changeset
287 }
kono
parents:
diff changeset
288
kono
parents:
diff changeset
289 if i != len(s) {
kono
parents:
diff changeset
290 return
kono
parents:
diff changeset
291 }
kono
parents:
diff changeset
292
kono
parents:
diff changeset
293 if mantissa != 0 {
kono
parents:
diff changeset
294 exp = dp - ndMant
kono
parents:
diff changeset
295 }
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
296
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
297 if underscores && !underscoreOK(s) {
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
298 return
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
299 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
300
111
kono
parents:
diff changeset
301 ok = true
kono
parents:
diff changeset
302 return
kono
parents:
diff changeset
303 }
kono
parents:
diff changeset
304
kono
parents:
diff changeset
305 // decimal power of ten to binary power of two.
kono
parents:
diff changeset
306 var powtab = []int{1, 3, 6, 9, 13, 16, 19, 23, 26}
kono
parents:
diff changeset
307
kono
parents:
diff changeset
308 func (d *decimal) floatBits(flt *floatInfo) (b uint64, overflow bool) {
kono
parents:
diff changeset
309 var exp int
kono
parents:
diff changeset
310 var mant uint64
kono
parents:
diff changeset
311
kono
parents:
diff changeset
312 // Zero is always a special case.
kono
parents:
diff changeset
313 if d.nd == 0 {
kono
parents:
diff changeset
314 mant = 0
kono
parents:
diff changeset
315 exp = flt.bias
kono
parents:
diff changeset
316 goto out
kono
parents:
diff changeset
317 }
kono
parents:
diff changeset
318
kono
parents:
diff changeset
319 // Obvious overflow/underflow.
kono
parents:
diff changeset
320 // These bounds are for 64-bit floats.
kono
parents:
diff changeset
321 // Will have to change if we want to support 80-bit floats in the future.
kono
parents:
diff changeset
322 if d.dp > 310 {
kono
parents:
diff changeset
323 goto overflow
kono
parents:
diff changeset
324 }
kono
parents:
diff changeset
325 if d.dp < -330 {
kono
parents:
diff changeset
326 // zero
kono
parents:
diff changeset
327 mant = 0
kono
parents:
diff changeset
328 exp = flt.bias
kono
parents:
diff changeset
329 goto out
kono
parents:
diff changeset
330 }
kono
parents:
diff changeset
331
kono
parents:
diff changeset
332 // Scale by powers of two until in range [0.5, 1.0)
kono
parents:
diff changeset
333 exp = 0
kono
parents:
diff changeset
334 for d.dp > 0 {
kono
parents:
diff changeset
335 var n int
kono
parents:
diff changeset
336 if d.dp >= len(powtab) {
kono
parents:
diff changeset
337 n = 27
kono
parents:
diff changeset
338 } else {
kono
parents:
diff changeset
339 n = powtab[d.dp]
kono
parents:
diff changeset
340 }
kono
parents:
diff changeset
341 d.Shift(-n)
kono
parents:
diff changeset
342 exp += n
kono
parents:
diff changeset
343 }
kono
parents:
diff changeset
344 for d.dp < 0 || d.dp == 0 && d.d[0] < '5' {
kono
parents:
diff changeset
345 var n int
kono
parents:
diff changeset
346 if -d.dp >= len(powtab) {
kono
parents:
diff changeset
347 n = 27
kono
parents:
diff changeset
348 } else {
kono
parents:
diff changeset
349 n = powtab[-d.dp]
kono
parents:
diff changeset
350 }
kono
parents:
diff changeset
351 d.Shift(n)
kono
parents:
diff changeset
352 exp -= n
kono
parents:
diff changeset
353 }
kono
parents:
diff changeset
354
kono
parents:
diff changeset
355 // Our range is [0.5,1) but floating point range is [1,2).
kono
parents:
diff changeset
356 exp--
kono
parents:
diff changeset
357
kono
parents:
diff changeset
358 // Minimum representable exponent is flt.bias+1.
kono
parents:
diff changeset
359 // If the exponent is smaller, move it up and
kono
parents:
diff changeset
360 // adjust d accordingly.
kono
parents:
diff changeset
361 if exp < flt.bias+1 {
kono
parents:
diff changeset
362 n := flt.bias + 1 - exp
kono
parents:
diff changeset
363 d.Shift(-n)
kono
parents:
diff changeset
364 exp += n
kono
parents:
diff changeset
365 }
kono
parents:
diff changeset
366
kono
parents:
diff changeset
367 if exp-flt.bias >= 1<<flt.expbits-1 {
kono
parents:
diff changeset
368 goto overflow
kono
parents:
diff changeset
369 }
kono
parents:
diff changeset
370
kono
parents:
diff changeset
371 // Extract 1+flt.mantbits bits.
kono
parents:
diff changeset
372 d.Shift(int(1 + flt.mantbits))
kono
parents:
diff changeset
373 mant = d.RoundedInteger()
kono
parents:
diff changeset
374
kono
parents:
diff changeset
375 // Rounding might have added a bit; shift down.
kono
parents:
diff changeset
376 if mant == 2<<flt.mantbits {
kono
parents:
diff changeset
377 mant >>= 1
kono
parents:
diff changeset
378 exp++
kono
parents:
diff changeset
379 if exp-flt.bias >= 1<<flt.expbits-1 {
kono
parents:
diff changeset
380 goto overflow
kono
parents:
diff changeset
381 }
kono
parents:
diff changeset
382 }
kono
parents:
diff changeset
383
kono
parents:
diff changeset
384 // Denormalized?
kono
parents:
diff changeset
385 if mant&(1<<flt.mantbits) == 0 {
kono
parents:
diff changeset
386 exp = flt.bias
kono
parents:
diff changeset
387 }
kono
parents:
diff changeset
388 goto out
kono
parents:
diff changeset
389
kono
parents:
diff changeset
390 overflow:
kono
parents:
diff changeset
391 // ±Inf
kono
parents:
diff changeset
392 mant = 0
kono
parents:
diff changeset
393 exp = 1<<flt.expbits - 1 + flt.bias
kono
parents:
diff changeset
394 overflow = true
kono
parents:
diff changeset
395
kono
parents:
diff changeset
396 out:
kono
parents:
diff changeset
397 // Assemble bits.
kono
parents:
diff changeset
398 bits := mant & (uint64(1)<<flt.mantbits - 1)
kono
parents:
diff changeset
399 bits |= uint64((exp-flt.bias)&(1<<flt.expbits-1)) << flt.mantbits
kono
parents:
diff changeset
400 if d.neg {
kono
parents:
diff changeset
401 bits |= 1 << flt.mantbits << flt.expbits
kono
parents:
diff changeset
402 }
kono
parents:
diff changeset
403 return bits, overflow
kono
parents:
diff changeset
404 }
kono
parents:
diff changeset
405
kono
parents:
diff changeset
406 // Exact powers of 10.
kono
parents:
diff changeset
407 var float64pow10 = []float64{
kono
parents:
diff changeset
408 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9,
kono
parents:
diff changeset
409 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
kono
parents:
diff changeset
410 1e20, 1e21, 1e22,
kono
parents:
diff changeset
411 }
kono
parents:
diff changeset
412 var float32pow10 = []float32{1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10}
kono
parents:
diff changeset
413
kono
parents:
diff changeset
414 // If possible to convert decimal representation to 64-bit float f exactly,
kono
parents:
diff changeset
415 // entirely in floating-point math, do so, avoiding the expense of decimalToFloatBits.
kono
parents:
diff changeset
416 // Three common cases:
kono
parents:
diff changeset
417 // value is exact integer
kono
parents:
diff changeset
418 // value is exact integer * exact power of ten
kono
parents:
diff changeset
419 // value is exact integer / exact power of ten
kono
parents:
diff changeset
420 // These all produce potentially inexact but correctly rounded answers.
kono
parents:
diff changeset
421 func atof64exact(mantissa uint64, exp int, neg bool) (f float64, ok bool) {
kono
parents:
diff changeset
422 if mantissa>>float64info.mantbits != 0 {
kono
parents:
diff changeset
423 return
kono
parents:
diff changeset
424 }
kono
parents:
diff changeset
425 // gccgo gets this wrong on 32-bit i386 when not using -msse.
kono
parents:
diff changeset
426 // See TestRoundTrip in atof_test.go for a test case.
kono
parents:
diff changeset
427 if runtime.GOARCH == "386" {
kono
parents:
diff changeset
428 return
kono
parents:
diff changeset
429 }
kono
parents:
diff changeset
430 f = float64(mantissa)
kono
parents:
diff changeset
431 if neg {
kono
parents:
diff changeset
432 f = -f
kono
parents:
diff changeset
433 }
kono
parents:
diff changeset
434 switch {
kono
parents:
diff changeset
435 case exp == 0:
kono
parents:
diff changeset
436 // an integer.
kono
parents:
diff changeset
437 return f, true
kono
parents:
diff changeset
438 // Exact integers are <= 10^15.
kono
parents:
diff changeset
439 // Exact powers of ten are <= 10^22.
kono
parents:
diff changeset
440 case exp > 0 && exp <= 15+22: // int * 10^k
kono
parents:
diff changeset
441 // If exponent is big but number of digits is not,
kono
parents:
diff changeset
442 // can move a few zeros into the integer part.
kono
parents:
diff changeset
443 if exp > 22 {
kono
parents:
diff changeset
444 f *= float64pow10[exp-22]
kono
parents:
diff changeset
445 exp = 22
kono
parents:
diff changeset
446 }
kono
parents:
diff changeset
447 if f > 1e15 || f < -1e15 {
kono
parents:
diff changeset
448 // the exponent was really too large.
kono
parents:
diff changeset
449 return
kono
parents:
diff changeset
450 }
kono
parents:
diff changeset
451 return f * float64pow10[exp], true
kono
parents:
diff changeset
452 case exp < 0 && exp >= -22: // int / 10^k
kono
parents:
diff changeset
453 return f / float64pow10[-exp], true
kono
parents:
diff changeset
454 }
kono
parents:
diff changeset
455 return
kono
parents:
diff changeset
456 }
kono
parents:
diff changeset
457
kono
parents:
diff changeset
458 // If possible to compute mantissa*10^exp to 32-bit float f exactly,
kono
parents:
diff changeset
459 // entirely in floating-point math, do so, avoiding the machinery above.
kono
parents:
diff changeset
460 func atof32exact(mantissa uint64, exp int, neg bool) (f float32, ok bool) {
kono
parents:
diff changeset
461 if mantissa>>float32info.mantbits != 0 {
kono
parents:
diff changeset
462 return
kono
parents:
diff changeset
463 }
kono
parents:
diff changeset
464 f = float32(mantissa)
kono
parents:
diff changeset
465 if neg {
kono
parents:
diff changeset
466 f = -f
kono
parents:
diff changeset
467 }
kono
parents:
diff changeset
468 switch {
kono
parents:
diff changeset
469 case exp == 0:
kono
parents:
diff changeset
470 return f, true
kono
parents:
diff changeset
471 // Exact integers are <= 10^7.
kono
parents:
diff changeset
472 // Exact powers of ten are <= 10^10.
kono
parents:
diff changeset
473 case exp > 0 && exp <= 7+10: // int * 10^k
kono
parents:
diff changeset
474 // If exponent is big but number of digits is not,
kono
parents:
diff changeset
475 // can move a few zeros into the integer part.
kono
parents:
diff changeset
476 if exp > 10 {
kono
parents:
diff changeset
477 f *= float32pow10[exp-10]
kono
parents:
diff changeset
478 exp = 10
kono
parents:
diff changeset
479 }
kono
parents:
diff changeset
480 if f > 1e7 || f < -1e7 {
kono
parents:
diff changeset
481 // the exponent was really too large.
kono
parents:
diff changeset
482 return
kono
parents:
diff changeset
483 }
kono
parents:
diff changeset
484 return f * float32pow10[exp], true
kono
parents:
diff changeset
485 case exp < 0 && exp >= -10: // int / 10^k
kono
parents:
diff changeset
486 return f / float32pow10[-exp], true
kono
parents:
diff changeset
487 }
kono
parents:
diff changeset
488 return
kono
parents:
diff changeset
489 }
kono
parents:
diff changeset
490
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
491 // atofHex converts the hex floating-point string s
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
492 // to a rounded float32 or float64 value (depending on flt==&float32info or flt==&float64info)
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
493 // and returns it as a float64.
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
494 // The string s has already been parsed into a mantissa, exponent, and sign (neg==true for negative).
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
495 // If trunc is true, trailing non-zero bits have been omitted from the mantissa.
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
496 func atofHex(s string, flt *floatInfo, mantissa uint64, exp int, neg, trunc bool) (float64, error) {
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
497 maxExp := 1<<flt.expbits + flt.bias - 2
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
498 minExp := flt.bias + 1
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
499 exp += int(flt.mantbits) // mantissa now implicitly divided by 2^mantbits.
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
500
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
501 // Shift mantissa and exponent to bring representation into float range.
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
502 // Eventually we want a mantissa with a leading 1-bit followed by mantbits other bits.
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
503 // For rounding, we need two more, where the bottom bit represents
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
504 // whether that bit or any later bit was non-zero.
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
505 // (If the mantissa has already lost non-zero bits, trunc is true,
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
506 // and we OR in a 1 below after shifting left appropriately.)
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
507 for mantissa != 0 && mantissa>>(flt.mantbits+2) == 0 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
508 mantissa <<= 1
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
509 exp--
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
510 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
511 if trunc {
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
512 mantissa |= 1
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
513 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
514 for mantissa>>(1+flt.mantbits+2) != 0 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
515 mantissa = mantissa>>1 | mantissa&1
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
516 exp++
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
517 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
518
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
519 // If exponent is too negative,
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
520 // denormalize in hopes of making it representable.
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
521 // (The -2 is for the rounding bits.)
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
522 for mantissa > 1 && exp < minExp-2 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
523 mantissa = mantissa>>1 | mantissa&1
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
524 exp++
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
525 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
526
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
527 // Round using two bottom bits.
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
528 round := mantissa & 3
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
529 mantissa >>= 2
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
530 round |= mantissa & 1 // round to even (round up if mantissa is odd)
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
531 exp += 2
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
532 if round == 3 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
533 mantissa++
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
534 if mantissa == 1<<(1+flt.mantbits) {
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
535 mantissa >>= 1
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
536 exp++
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
537 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
538 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
539
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
540 if mantissa>>flt.mantbits == 0 { // Denormal or zero.
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
541 exp = flt.bias
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
542 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
543 var err error
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
544 if exp > maxExp { // infinity and range error
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
545 mantissa = 1 << flt.mantbits
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
546 exp = maxExp + 1
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
547 err = rangeError(fnParseFloat, s)
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
548 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
549
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
550 bits := mantissa & (1<<flt.mantbits - 1)
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
551 bits |= uint64((exp-flt.bias)&(1<<flt.expbits-1)) << flt.mantbits
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
552 if neg {
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
553 bits |= 1 << flt.mantbits << flt.expbits
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
554 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
555 if flt == &float32info {
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
556 return float64(math.Float32frombits(uint32(bits))), err
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
557 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
558 return math.Float64frombits(bits), err
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
559 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
560
111
kono
parents:
diff changeset
561 const fnParseFloat = "ParseFloat"
kono
parents:
diff changeset
562
kono
parents:
diff changeset
563 func atof32(s string) (f float32, err error) {
kono
parents:
diff changeset
564 if val, ok := special(s); ok {
kono
parents:
diff changeset
565 return float32(val), nil
kono
parents:
diff changeset
566 }
kono
parents:
diff changeset
567
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
568 mantissa, exp, neg, trunc, hex, ok := readFloat(s)
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
569 if !ok {
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
570 return 0, syntaxError(fnParseFloat, s)
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
571 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
572
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
573 if hex {
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
574 f, err := atofHex(s, &float32info, mantissa, exp, neg, trunc)
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
575 return float32(f), err
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
576 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
577
111
kono
parents:
diff changeset
578 if optimize {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
579 // Try pure floating-point arithmetic conversion.
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
580 if !trunc {
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
581 if f, ok := atof32exact(mantissa, exp, neg); ok {
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
582 return f, nil
111
kono
parents:
diff changeset
583 }
kono
parents:
diff changeset
584 }
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
585 // Try another fast path.
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
586 ext := new(extFloat)
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
587 if ok := ext.AssignDecimal(mantissa, exp, neg, trunc, &float32info); ok {
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
588 b, ovf := ext.floatBits(&float32info)
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
589 f = math.Float32frombits(uint32(b))
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
590 if ovf {
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
591 err = rangeError(fnParseFloat, s)
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
592 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
593 return f, err
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
594 }
111
kono
parents:
diff changeset
595 }
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
596
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
597 // Slow fallback.
111
kono
parents:
diff changeset
598 var d decimal
kono
parents:
diff changeset
599 if !d.set(s) {
kono
parents:
diff changeset
600 return 0, syntaxError(fnParseFloat, s)
kono
parents:
diff changeset
601 }
kono
parents:
diff changeset
602 b, ovf := d.floatBits(&float32info)
kono
parents:
diff changeset
603 f = math.Float32frombits(uint32(b))
kono
parents:
diff changeset
604 if ovf {
kono
parents:
diff changeset
605 err = rangeError(fnParseFloat, s)
kono
parents:
diff changeset
606 }
kono
parents:
diff changeset
607 return f, err
kono
parents:
diff changeset
608 }
kono
parents:
diff changeset
609
kono
parents:
diff changeset
610 func atof64(s string) (f float64, err error) {
kono
parents:
diff changeset
611 if val, ok := special(s); ok {
kono
parents:
diff changeset
612 return val, nil
kono
parents:
diff changeset
613 }
kono
parents:
diff changeset
614
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
615 mantissa, exp, neg, trunc, hex, ok := readFloat(s)
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
616 if !ok {
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
617 return 0, syntaxError(fnParseFloat, s)
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
618 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
619
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
620 if hex {
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
621 return atofHex(s, &float64info, mantissa, exp, neg, trunc)
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
622 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
623
111
kono
parents:
diff changeset
624 if optimize {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
625 // Try pure floating-point arithmetic conversion.
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
626 if !trunc {
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
627 if f, ok := atof64exact(mantissa, exp, neg); ok {
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
628 return f, nil
111
kono
parents:
diff changeset
629 }
kono
parents:
diff changeset
630 }
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
631 // Try another fast path.
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
632 ext := new(extFloat)
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
633 if ok := ext.AssignDecimal(mantissa, exp, neg, trunc, &float64info); ok {
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
634 b, ovf := ext.floatBits(&float64info)
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
635 f = math.Float64frombits(b)
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
636 if ovf {
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
637 err = rangeError(fnParseFloat, s)
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
638 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
639 return f, err
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
640 }
111
kono
parents:
diff changeset
641 }
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
642
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
643 // Slow fallback.
111
kono
parents:
diff changeset
644 var d decimal
kono
parents:
diff changeset
645 if !d.set(s) {
kono
parents:
diff changeset
646 return 0, syntaxError(fnParseFloat, s)
kono
parents:
diff changeset
647 }
kono
parents:
diff changeset
648 b, ovf := d.floatBits(&float64info)
kono
parents:
diff changeset
649 f = math.Float64frombits(b)
kono
parents:
diff changeset
650 if ovf {
kono
parents:
diff changeset
651 err = rangeError(fnParseFloat, s)
kono
parents:
diff changeset
652 }
kono
parents:
diff changeset
653 return f, err
kono
parents:
diff changeset
654 }
kono
parents:
diff changeset
655
kono
parents:
diff changeset
656 // ParseFloat converts the string s to a floating-point number
kono
parents:
diff changeset
657 // with the precision specified by bitSize: 32 for float32, or 64 for float64.
kono
parents:
diff changeset
658 // When bitSize=32, the result still has type float64, but it will be
kono
parents:
diff changeset
659 // convertible to float32 without changing its value.
kono
parents:
diff changeset
660 //
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
661 // ParseFloat accepts decimal and hexadecimal floating-point number syntax.
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
662 // If s is well-formed and near a valid floating-point number,
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
663 // ParseFloat returns the nearest floating-point number rounded
111
kono
parents:
diff changeset
664 // using IEEE754 unbiased rounding.
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
665 // (Parsing a hexadecimal floating-point value only rounds when
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
666 // there are more bits in the hexadecimal representation than
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
667 // will fit in the mantissa.)
111
kono
parents:
diff changeset
668 //
kono
parents:
diff changeset
669 // The errors that ParseFloat returns have concrete type *NumError
kono
parents:
diff changeset
670 // and include err.Num = s.
kono
parents:
diff changeset
671 //
kono
parents:
diff changeset
672 // If s is not syntactically well-formed, ParseFloat returns err.Err = ErrSyntax.
kono
parents:
diff changeset
673 //
kono
parents:
diff changeset
674 // If s is syntactically well-formed but is more than 1/2 ULP
kono
parents:
diff changeset
675 // away from the largest floating point number of the given size,
kono
parents:
diff changeset
676 // ParseFloat returns f = ±Inf, err.Err = ErrRange.
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
677 //
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
678 // ParseFloat recognizes the strings "NaN", "+Inf", and "-Inf" as their
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
679 // respective special floating point values. It ignores case when matching.
111
kono
parents:
diff changeset
680 func ParseFloat(s string, bitSize int) (float64, error) {
kono
parents:
diff changeset
681 if bitSize == 32 {
kono
parents:
diff changeset
682 f, err := atof32(s)
kono
parents:
diff changeset
683 return float64(f), err
kono
parents:
diff changeset
684 }
kono
parents:
diff changeset
685 return atof64(s)
kono
parents:
diff changeset
686 }