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  }