Home | History | Annotate | Download | only in big
      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.uquo(z, p.pow10(-exp10))
    129 	} else {
    130 		z.umul(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 }
    240