github.com/q45/go@v0.0.0-20151101211701-a4fb8c13db3f/src/cmd/compile/internal/big/floatconv.go (about) 1 // Copyright 2015 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // This file implements string-to-Float conversion functions. 6 7 package big 8 9 import ( 10 "fmt" 11 "io" 12 "strings" 13 ) 14 15 // SetString sets z to the value of s and returns z and a boolean indicating 16 // success. s must be a floating-point number of the same format as accepted 17 // by Parse, with base argument 0. 18 func (z *Float) SetString(s string) (*Float, bool) { 19 if f, _, err := z.Parse(s, 0); err == nil { 20 return f, true 21 } 22 return nil, false 23 } 24 25 // scan is like Parse but reads the longest possible prefix representing a valid 26 // floating point number from an io.ByteScanner rather than a string. It serves 27 // as the implementation of Parse. It does not recognize ±Inf and does not expect 28 // EOF at the end. 29 func (z *Float) scan(r io.ByteScanner, base int) (f *Float, b int, err error) { 30 prec := z.prec 31 if prec == 0 { 32 prec = 64 33 } 34 35 // A reasonable value in case of an error. 36 z.form = zero 37 38 // sign 39 z.neg, err = scanSign(r) 40 if err != nil { 41 return 42 } 43 44 // mantissa 45 var fcount int // fractional digit count; valid if <= 0 46 z.mant, b, fcount, err = z.mant.scan(r, base, true) 47 if err != nil { 48 return 49 } 50 51 // exponent 52 var exp int64 53 var ebase int 54 exp, ebase, err = scanExponent(r, true) 55 if err != nil { 56 return 57 } 58 59 // special-case 0 60 if len(z.mant) == 0 { 61 z.prec = prec 62 z.acc = Exact 63 z.form = zero 64 f = z 65 return 66 } 67 // len(z.mant) > 0 68 69 // The mantissa may have a decimal point (fcount <= 0) and there 70 // may be a nonzero exponent exp. The decimal point amounts to a 71 // division by b**(-fcount). An exponent means multiplication by 72 // ebase**exp. Finally, mantissa normalization (shift left) requires 73 // a correcting multiplication by 2**(-shiftcount). Multiplications 74 // are commutative, so we can apply them in any order as long as there 75 // is no loss of precision. We only have powers of 2 and 10; keep 76 // track via separate exponents exp2 and exp10. 77 78 // normalize mantissa and get initial binary exponent 79 var exp2 = int64(len(z.mant))*_W - fnorm(z.mant) 80 81 // determine binary or decimal exponent contribution of decimal point 82 var exp10 int64 83 if fcount < 0 { 84 // The mantissa has a "decimal" point ddd.dddd; and 85 // -fcount is the number of digits to the right of '.'. 86 // Adjust relevant exponent accodingly. 87 switch b { 88 case 16: 89 fcount *= 4 // hexadecimal digits are 4 bits each 90 fallthrough 91 case 2: 92 exp2 += int64(fcount) 93 default: // b == 10 94 exp10 = int64(fcount) 95 } 96 // we don't need fcount anymore 97 } 98 99 // take actual exponent into account 100 if ebase == 2 { 101 exp2 += exp 102 } else { // ebase == 10 103 exp10 += exp 104 } 105 // we don't need exp anymore 106 107 // apply 2**exp2 108 if MinExp <= exp2 && exp2 <= MaxExp { 109 z.prec = prec 110 z.form = finite 111 z.exp = int32(exp2) 112 f = z 113 } else { 114 err = fmt.Errorf("exponent overflow") 115 return 116 } 117 118 if exp10 == 0 { 119 // no decimal exponent to consider 120 z.round(0) 121 return 122 } 123 // exp10 != 0 124 125 // apply 10**exp10 126 p := new(Float).SetPrec(z.Prec() + 64) // use more bits for p -- TODO(gri) what is the right number? 127 if exp10 < 0 { 128 z.Quo(z, p.pow10(-exp10)) 129 } else { 130 z.Mul(z, p.pow10(exp10)) 131 } 132 133 return 134 } 135 136 // These powers of 10 can be represented exactly as a float64. 137 var pow10tab = [...]float64{ 138 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 139 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, 140 } 141 142 // pow10 sets z to 10**n and returns z. 143 // n must not be negative. 144 func (z *Float) pow10(n int64) *Float { 145 if n < 0 { 146 panic("pow10 called with negative argument") 147 } 148 149 const m = int64(len(pow10tab) - 1) 150 if n <= m { 151 return z.SetFloat64(pow10tab[n]) 152 } 153 // n > m 154 155 z.SetFloat64(pow10tab[m]) 156 n -= m 157 158 // use more bits for f than for z 159 // TODO(gri) what is the right number? 160 f := new(Float).SetPrec(z.Prec() + 64).SetInt64(10) 161 162 for n > 0 { 163 if n&1 != 0 { 164 z.Mul(z, f) 165 } 166 f.Mul(f, f) 167 n >>= 1 168 } 169 170 return z 171 } 172 173 // Parse parses s which must contain a text representation of a floating- 174 // point number with a mantissa in the given conversion base (the exponent 175 // is always a decimal number), or a string representing an infinite value. 176 // 177 // It sets z to the (possibly rounded) value of the corresponding floating- 178 // point value, and returns z, the actual base b, and an error err, if any. 179 // If z's precision is 0, it is changed to 64 before rounding takes effect. 180 // The number must be of the form: 181 // 182 // number = [ sign ] [ prefix ] mantissa [ exponent ] | infinity . 183 // sign = "+" | "-" . 184 // prefix = "0" ( "x" | "X" | "b" | "B" ) . 185 // mantissa = digits | digits "." [ digits ] | "." digits . 186 // exponent = ( "E" | "e" | "p" ) [ sign ] digits . 187 // digits = digit { digit } . 188 // digit = "0" ... "9" | "a" ... "z" | "A" ... "Z" . 189 // infinity = [ sign ] ( "inf" | "Inf" ) . 190 // 191 // The base argument must be 0, 2, 10, or 16. Providing an invalid base 192 // argument will lead to a run-time panic. 193 // 194 // For base 0, the number prefix determines the actual base: A prefix of 195 // "0x" or "0X" selects base 16, and a "0b" or "0B" prefix selects 196 // base 2; otherwise, the actual base is 10 and no prefix is accepted. 197 // The octal prefix "0" is not supported (a leading "0" is simply 198 // considered a "0"). 199 // 200 // A "p" exponent indicates a binary (rather then decimal) exponent; 201 // for instance "0x1.fffffffffffffp1023" (using base 0) represents the 202 // maximum float64 value. For hexadecimal mantissae, the exponent must 203 // be binary, if present (an "e" or "E" exponent indicator cannot be 204 // distinguished from a mantissa digit). 205 // 206 // The returned *Float f is nil and the value of z is valid but not 207 // defined if an error is reported. 208 // 209 func (z *Float) Parse(s string, base int) (f *Float, b int, err error) { 210 // scan doesn't handle ±Inf 211 if len(s) == 3 && (s == "Inf" || s == "inf") { 212 f = z.SetInf(false) 213 return 214 } 215 if len(s) == 4 && (s[0] == '+' || s[0] == '-') && (s[1:] == "Inf" || s[1:] == "inf") { 216 f = z.SetInf(s[0] == '-') 217 return 218 } 219 220 r := strings.NewReader(s) 221 if f, b, err = z.scan(r, base); err != nil { 222 return 223 } 224 225 // entire string must have been consumed 226 if ch, err2 := r.ReadByte(); err2 == nil { 227 err = fmt.Errorf("expected end of string, found %q", ch) 228 } else if err2 != io.EOF { 229 err = err2 230 } 231 232 return 233 } 234 235 // ParseFloat is like f.Parse(s, base) with f set to the given precision 236 // and rounding mode. 237 func ParseFloat(s string, base int, prec uint, mode RoundingMode) (f *Float, b int, err error) { 238 return new(Float).SetPrec(prec).SetMode(mode).Parse(s, base) 239 }