github.com/flyinox/gosm@v0.0.0-20171117061539-16768cb62077/src/math/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 var floatZero Float 16 17 // SetString sets z to the value of s and returns z and a boolean indicating 18 // success. s must be a floating-point number of the same format as accepted 19 // by Parse, with base argument 0. The entire string (not just a prefix) must 20 // be valid for success. If the operation failed, the value of z is undefined 21 // but the returned value is nil. 22 func (z *Float) SetString(s string) (*Float, bool) { 23 if f, _, err := z.Parse(s, 0); err == nil { 24 return f, true 25 } 26 return nil, false 27 } 28 29 // scan is like Parse but reads the longest possible prefix representing a valid 30 // floating point number from an io.ByteScanner rather than a string. It serves 31 // as the implementation of Parse. It does not recognize ±Inf and does not expect 32 // EOF at the end. 33 func (z *Float) scan(r io.ByteScanner, base int) (f *Float, b int, err error) { 34 prec := z.prec 35 if prec == 0 { 36 prec = 64 37 } 38 39 // A reasonable value in case of an error. 40 z.form = zero 41 42 // sign 43 z.neg, err = scanSign(r) 44 if err != nil { 45 return 46 } 47 48 // mantissa 49 var fcount int // fractional digit count; valid if <= 0 50 z.mant, b, fcount, err = z.mant.scan(r, base, true) 51 if err != nil { 52 return 53 } 54 55 // exponent 56 var exp int64 57 var ebase int 58 exp, ebase, err = scanExponent(r, true) 59 if err != nil { 60 return 61 } 62 63 // special-case 0 64 if len(z.mant) == 0 { 65 z.prec = prec 66 z.acc = Exact 67 z.form = zero 68 f = z 69 return 70 } 71 // len(z.mant) > 0 72 73 // The mantissa may have a decimal point (fcount <= 0) and there 74 // may be a nonzero exponent exp. The decimal point amounts to a 75 // division by b**(-fcount). An exponent means multiplication by 76 // ebase**exp. Finally, mantissa normalization (shift left) requires 77 // a correcting multiplication by 2**(-shiftcount). Multiplications 78 // are commutative, so we can apply them in any order as long as there 79 // is no loss of precision. We only have powers of 2 and 10, and 80 // we split powers of 10 into the product of the same powers of 81 // 2 and 5. This reduces the size of the multiplication factor 82 // needed for base-10 exponents. 83 84 // normalize mantissa and determine initial exponent contributions 85 exp2 := int64(len(z.mant))*_W - fnorm(z.mant) 86 exp5 := int64(0) 87 88 // determine binary or decimal exponent contribution of decimal point 89 if fcount < 0 { 90 // The mantissa has a "decimal" point ddd.dddd; and 91 // -fcount is the number of digits to the right of '.'. 92 // Adjust relevant exponent accordingly. 93 d := int64(fcount) 94 switch b { 95 case 10: 96 exp5 = d 97 fallthrough // 10**e == 5**e * 2**e 98 case 2: 99 exp2 += d 100 case 16: 101 exp2 += d * 4 // hexadecimal digits are 4 bits each 102 default: 103 panic("unexpected mantissa base") 104 } 105 // fcount consumed - not needed anymore 106 } 107 108 // take actual exponent into account 109 switch ebase { 110 case 10: 111 exp5 += exp 112 fallthrough 113 case 2: 114 exp2 += exp 115 default: 116 panic("unexpected exponent base") 117 } 118 // exp consumed - not needed anymore 119 120 // apply 2**exp2 121 if MinExp <= exp2 && exp2 <= MaxExp { 122 z.prec = prec 123 z.form = finite 124 z.exp = int32(exp2) 125 f = z 126 } else { 127 err = fmt.Errorf("exponent overflow") 128 return 129 } 130 131 if exp5 == 0 { 132 // no decimal exponent contribution 133 z.round(0) 134 return 135 } 136 // exp5 != 0 137 138 // apply 5**exp5 139 p := new(Float).SetPrec(z.Prec() + 64) // use more bits for p -- TODO(gri) what is the right number? 140 if exp5 < 0 { 141 z.Quo(z, p.pow5(uint64(-exp5))) 142 } else { 143 z.Mul(z, p.pow5(uint64(exp5))) 144 } 145 146 return 147 } 148 149 // These powers of 5 fit into a uint64. 150 // 151 // for p, q := uint64(0), uint64(1); p < q; p, q = q, q*5 { 152 // fmt.Println(q) 153 // } 154 // 155 var pow5tab = [...]uint64{ 156 1, 157 5, 158 25, 159 125, 160 625, 161 3125, 162 15625, 163 78125, 164 390625, 165 1953125, 166 9765625, 167 48828125, 168 244140625, 169 1220703125, 170 6103515625, 171 30517578125, 172 152587890625, 173 762939453125, 174 3814697265625, 175 19073486328125, 176 95367431640625, 177 476837158203125, 178 2384185791015625, 179 11920928955078125, 180 59604644775390625, 181 298023223876953125, 182 1490116119384765625, 183 7450580596923828125, 184 } 185 186 // pow5 sets z to 5**n and returns z. 187 // n must not be negative. 188 func (z *Float) pow5(n uint64) *Float { 189 const m = uint64(len(pow5tab) - 1) 190 if n <= m { 191 return z.SetUint64(pow5tab[n]) 192 } 193 // n > m 194 195 z.SetUint64(pow5tab[m]) 196 n -= m 197 198 // use more bits for f than for z 199 // TODO(gri) what is the right number? 200 f := new(Float).SetPrec(z.Prec() + 64).SetUint64(5) 201 202 for n > 0 { 203 if n&1 != 0 { 204 z.Mul(z, f) 205 } 206 f.Mul(f, f) 207 n >>= 1 208 } 209 210 return z 211 } 212 213 // Parse parses s which must contain a text representation of a floating- 214 // point number with a mantissa in the given conversion base (the exponent 215 // is always a decimal number), or a string representing an infinite value. 216 // 217 // It sets z to the (possibly rounded) value of the corresponding floating- 218 // point value, and returns z, the actual base b, and an error err, if any. 219 // The entire string (not just a prefix) must be consumed for success. 220 // If z's precision is 0, it is changed to 64 before rounding takes effect. 221 // The number must be of the form: 222 // 223 // number = [ sign ] [ prefix ] mantissa [ exponent ] | infinity . 224 // sign = "+" | "-" . 225 // prefix = "0" ( "x" | "X" | "b" | "B" ) . 226 // mantissa = digits | digits "." [ digits ] | "." digits . 227 // exponent = ( "E" | "e" | "p" ) [ sign ] digits . 228 // digits = digit { digit } . 229 // digit = "0" ... "9" | "a" ... "z" | "A" ... "Z" . 230 // infinity = [ sign ] ( "inf" | "Inf" ) . 231 // 232 // The base argument must be 0, 2, 10, or 16. Providing an invalid base 233 // argument will lead to a run-time panic. 234 // 235 // For base 0, the number prefix determines the actual base: A prefix of 236 // "0x" or "0X" selects base 16, and a "0b" or "0B" prefix selects 237 // base 2; otherwise, the actual base is 10 and no prefix is accepted. 238 // The octal prefix "0" is not supported (a leading "0" is simply 239 // considered a "0"). 240 // 241 // A "p" exponent indicates a binary (rather then decimal) exponent; 242 // for instance "0x1.fffffffffffffp1023" (using base 0) represents the 243 // maximum float64 value. For hexadecimal mantissae, the exponent must 244 // be binary, if present (an "e" or "E" exponent indicator cannot be 245 // distinguished from a mantissa digit). 246 // 247 // The returned *Float f is nil and the value of z is valid but not 248 // defined if an error is reported. 249 // 250 func (z *Float) Parse(s string, base int) (f *Float, b int, err error) { 251 // scan doesn't handle ±Inf 252 if len(s) == 3 && (s == "Inf" || s == "inf") { 253 f = z.SetInf(false) 254 return 255 } 256 if len(s) == 4 && (s[0] == '+' || s[0] == '-') && (s[1:] == "Inf" || s[1:] == "inf") { 257 f = z.SetInf(s[0] == '-') 258 return 259 } 260 261 r := strings.NewReader(s) 262 if f, b, err = z.scan(r, base); err != nil { 263 return 264 } 265 266 // entire string must have been consumed 267 if ch, err2 := r.ReadByte(); err2 == nil { 268 err = fmt.Errorf("expected end of string, found %q", ch) 269 } else if err2 != io.EOF { 270 err = err2 271 } 272 273 return 274 } 275 276 // ParseFloat is like f.Parse(s, base) with f set to the given precision 277 // and rounding mode. 278 func ParseFloat(s string, base int, prec uint, mode RoundingMode) (f *Float, b int, err error) { 279 return new(Float).SetPrec(prec).SetMode(mode).Parse(s, base) 280 } 281 282 var _ fmt.Scanner = &floatZero // *Float must implement fmt.Scanner 283 284 // Scan is a support routine for fmt.Scanner; it sets z to the value of 285 // the scanned number. It accepts formats whose verbs are supported by 286 // fmt.Scan for floating point values, which are: 287 // 'b' (binary), 'e', 'E', 'f', 'F', 'g' and 'G'. 288 // Scan doesn't handle ±Inf. 289 func (z *Float) Scan(s fmt.ScanState, ch rune) error { 290 s.SkipSpace() 291 _, _, err := z.scan(byteReader{s}, 0) 292 return err 293 }