github.com/aloncn/graphics-go@v0.0.1/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  // 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, and
    76  	// we split powers of 10 into the product of the same powers of
    77  	// 2 and 5. This reduces the size of the multiplication factor
    78  	// needed for base-10 exponents.
    79  
    80  	// normalize mantissa and determine initial exponent contributions
    81  	exp2 := int64(len(z.mant))*_W - fnorm(z.mant)
    82  	exp5 := int64(0)
    83  
    84  	// determine binary or decimal exponent contribution of decimal point
    85  	if fcount < 0 {
    86  		// The mantissa has a "decimal" point ddd.dddd; and
    87  		// -fcount is the number of digits to the right of '.'.
    88  		// Adjust relevant exponent accodingly.
    89  		d := int64(fcount)
    90  		switch b {
    91  		case 10:
    92  			exp5 = d
    93  			fallthrough // 10**e == 5**e * 2**e
    94  		case 2:
    95  			exp2 += d
    96  		case 16:
    97  			exp2 += d * 4 // hexadecimal digits are 4 bits each
    98  		default:
    99  			panic("unexpected mantissa base")
   100  		}
   101  		// fcount consumed - not needed anymore
   102  	}
   103  
   104  	// take actual exponent into account
   105  	switch ebase {
   106  	case 10:
   107  		exp5 += exp
   108  		fallthrough
   109  	case 2:
   110  		exp2 += exp
   111  	default:
   112  		panic("unexpected exponent base")
   113  	}
   114  	// exp consumed - not needed anymore
   115  
   116  	// apply 2**exp2
   117  	if MinExp <= exp2 && exp2 <= MaxExp {
   118  		z.prec = prec
   119  		z.form = finite
   120  		z.exp = int32(exp2)
   121  		f = z
   122  	} else {
   123  		err = fmt.Errorf("exponent overflow")
   124  		return
   125  	}
   126  
   127  	if exp5 == 0 {
   128  		// no decimal exponent contribution
   129  		z.round(0)
   130  		return
   131  	}
   132  	// exp5 != 0
   133  
   134  	// apply 5**exp5
   135  	p := new(Float).SetPrec(z.Prec() + 64) // use more bits for p -- TODO(gri) what is the right number?
   136  	if exp5 < 0 {
   137  		z.Quo(z, p.pow5(uint64(-exp5)))
   138  	} else {
   139  		z.Mul(z, p.pow5(uint64(exp5)))
   140  	}
   141  
   142  	return
   143  }
   144  
   145  // These powers of 5 fit into a uint64.
   146  //
   147  //	for p, q := uint64(0), uint64(1); p < q; p, q = q, q*5 {
   148  //		fmt.Println(q)
   149  //	}
   150  //
   151  var pow5tab = [...]uint64{
   152  	1,
   153  	5,
   154  	25,
   155  	125,
   156  	625,
   157  	3125,
   158  	15625,
   159  	78125,
   160  	390625,
   161  	1953125,
   162  	9765625,
   163  	48828125,
   164  	244140625,
   165  	1220703125,
   166  	6103515625,
   167  	30517578125,
   168  	152587890625,
   169  	762939453125,
   170  	3814697265625,
   171  	19073486328125,
   172  	95367431640625,
   173  	476837158203125,
   174  	2384185791015625,
   175  	11920928955078125,
   176  	59604644775390625,
   177  	298023223876953125,
   178  	1490116119384765625,
   179  	7450580596923828125,
   180  }
   181  
   182  // pow5 sets z to 5**n and returns z.
   183  // n must not be negative.
   184  func (z *Float) pow5(n uint64) *Float {
   185  	const m = uint64(len(pow5tab) - 1)
   186  	if n <= m {
   187  		return z.SetUint64(pow5tab[n])
   188  	}
   189  	// n > m
   190  
   191  	z.SetUint64(pow5tab[m])
   192  	n -= m
   193  
   194  	// use more bits for f than for z
   195  	// TODO(gri) what is the right number?
   196  	f := new(Float).SetPrec(z.Prec() + 64).SetUint64(5)
   197  
   198  	for n > 0 {
   199  		if n&1 != 0 {
   200  			z.Mul(z, f)
   201  		}
   202  		f.Mul(f, f)
   203  		n >>= 1
   204  	}
   205  
   206  	return z
   207  }
   208  
   209  // Parse parses s which must contain a text representation of a floating-
   210  // point number with a mantissa in the given conversion base (the exponent
   211  // is always a decimal number), or a string representing an infinite value.
   212  //
   213  // It sets z to the (possibly rounded) value of the corresponding floating-
   214  // point value, and returns z, the actual base b, and an error err, if any.
   215  // If z's precision is 0, it is changed to 64 before rounding takes effect.
   216  // The number must be of the form:
   217  //
   218  //	number   = [ sign ] [ prefix ] mantissa [ exponent ] | infinity .
   219  //	sign     = "+" | "-" .
   220  //      prefix   = "0" ( "x" | "X" | "b" | "B" ) .
   221  //	mantissa = digits | digits "." [ digits ] | "." digits .
   222  //	exponent = ( "E" | "e" | "p" ) [ sign ] digits .
   223  //	digits   = digit { digit } .
   224  //	digit    = "0" ... "9" | "a" ... "z" | "A" ... "Z" .
   225  //      infinity = [ sign ] ( "inf" | "Inf" ) .
   226  //
   227  // The base argument must be 0, 2, 10, or 16. Providing an invalid base
   228  // argument will lead to a run-time panic.
   229  //
   230  // For base 0, the number prefix determines the actual base: A prefix of
   231  // "0x" or "0X" selects base 16, and a "0b" or "0B" prefix selects
   232  // base 2; otherwise, the actual base is 10 and no prefix is accepted.
   233  // The octal prefix "0" is not supported (a leading "0" is simply
   234  // considered a "0").
   235  //
   236  // A "p" exponent indicates a binary (rather then decimal) exponent;
   237  // for instance "0x1.fffffffffffffp1023" (using base 0) represents the
   238  // maximum float64 value. For hexadecimal mantissae, the exponent must
   239  // be binary, if present (an "e" or "E" exponent indicator cannot be
   240  // distinguished from a mantissa digit).
   241  //
   242  // The returned *Float f is nil and the value of z is valid but not
   243  // defined if an error is reported.
   244  //
   245  func (z *Float) Parse(s string, base int) (f *Float, b int, err error) {
   246  	// scan doesn't handle ±Inf
   247  	if len(s) == 3 && (s == "Inf" || s == "inf") {
   248  		f = z.SetInf(false)
   249  		return
   250  	}
   251  	if len(s) == 4 && (s[0] == '+' || s[0] == '-') && (s[1:] == "Inf" || s[1:] == "inf") {
   252  		f = z.SetInf(s[0] == '-')
   253  		return
   254  	}
   255  
   256  	r := strings.NewReader(s)
   257  	if f, b, err = z.scan(r, base); err != nil {
   258  		return
   259  	}
   260  
   261  	// entire string must have been consumed
   262  	if ch, err2 := r.ReadByte(); err2 == nil {
   263  		err = fmt.Errorf("expected end of string, found %q", ch)
   264  	} else if err2 != io.EOF {
   265  		err = err2
   266  	}
   267  
   268  	return
   269  }
   270  
   271  // ParseFloat is like f.Parse(s, base) with f set to the given precision
   272  // and rounding mode.
   273  func ParseFloat(s string, base int, prec uint, mode RoundingMode) (f *Float, b int, err error) {
   274  	return new(Float).SetPrec(prec).SetMode(mode).Parse(s, base)
   275  }