ratconv.mx raw

   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 rat-to-string conversion functions.
   6  
   7  package big
   8  
   9  import (
  10  	"errors"
  11  	"fmt"
  12  	"io"
  13  	"strconv"
  14  	"bytes"
  15  )
  16  
  17  func ratTok(ch rune) bool {
  18  	return bytes.ContainsRune("+-/0123456789.eE", ch)
  19  }
  20  
  21  var ratZero Rat
  22  var _ fmt.Scanner = &ratZero // *Rat must implement fmt.Scanner
  23  
  24  // Scan is a support routine for fmt.Scanner. It accepts the formats
  25  // 'e', 'E', 'f', 'F', 'g', 'G', and 'v'. All formats are equivalent.
  26  func (z *Rat) Scan(s fmt.ScanState, ch rune) error {
  27  	tok, err := s.Token(true, ratTok)
  28  	if err != nil {
  29  		return err
  30  	}
  31  	if !bytes.ContainsRune("efgEFGv", ch) {
  32  		return errors.New("Rat.Scan: invalid verb")
  33  	}
  34  	if _, ok := z.SetString([]byte(tok)); !ok {
  35  		return errors.New("Rat.Scan: invalid syntax")
  36  	}
  37  	return nil
  38  }
  39  
  40  // SetString sets z to the value of s and returns z and a boolean indicating
  41  // success. s can be given as a (possibly signed) fraction "a/b", or as a
  42  // floating-point number optionally followed by an exponent.
  43  // If a fraction is provided, both the dividend and the divisor may be a
  44  // decimal integer or independently use a prefix of “0b”, “0” or “0o”,
  45  // or “0x” (or their upper-case variants) to denote a binary, octal, or
  46  // hexadecimal integer, respectively. The divisor may not be signed.
  47  // If a floating-point number is provided, it may be in decimal form or
  48  // use any of the same prefixes as above but for “0” to denote a non-decimal
  49  // mantissa. A leading “0” is considered a decimal leading 0; it does not
  50  // indicate octal representation in this case.
  51  // An optional base-10 “e” or base-2 “p” (or their upper-case variants)
  52  // exponent may be provided as well, except for hexadecimal floats which
  53  // only accept an (optional) “p” exponent (because an “e” or “E” cannot
  54  // be distinguished from a mantissa digit). If the exponent's absolute value
  55  // is too large, the operation may fail.
  56  // The entire string, not just a prefix, must be valid for success. If the
  57  // operation failed, the value of z is undefined but the returned value is nil.
  58  func (z *Rat) SetString(s []byte) (*Rat, bool) {
  59  	if len(s) == 0 {
  60  		return nil, false
  61  	}
  62  	// len(s) > 0
  63  
  64  	// parse fraction a/b, if any
  65  	if sep := bytes.Index(s, "/"); sep >= 0 {
  66  		if _, ok := z.a.SetString(s[:sep], 0); !ok {
  67  			return nil, false
  68  		}
  69  		r := bytes.NewReader(s[sep+1:])
  70  		var err error
  71  		if z.b.abs, _, _, err = z.b.abs.scan(r, 0, false); err != nil {
  72  			return nil, false
  73  		}
  74  		// entire string must have been consumed
  75  		if _, err = r.ReadByte(); err != io.EOF {
  76  			return nil, false
  77  		}
  78  		if len(z.b.abs) == 0 {
  79  			return nil, false
  80  		}
  81  		return z.norm(), true
  82  	}
  83  
  84  	// parse floating-point number
  85  	r := bytes.NewReader(s)
  86  
  87  	// sign
  88  	neg, err := scanSign(r)
  89  	if err != nil {
  90  		return nil, false
  91  	}
  92  
  93  	// mantissa
  94  	var base int
  95  	var fcount int // fractional digit count; valid if <= 0
  96  	z.a.abs, base, fcount, err = z.a.abs.scan(r, 0, true)
  97  	if err != nil {
  98  		return nil, false
  99  	}
 100  
 101  	// exponent
 102  	var exp int64
 103  	var ebase int
 104  	exp, ebase, err = scanExponent(r, true, true)
 105  	if err != nil {
 106  		return nil, false
 107  	}
 108  
 109  	// there should be no unread characters left
 110  	if _, err = r.ReadByte(); err != io.EOF {
 111  		return nil, false
 112  	}
 113  
 114  	// special-case 0 (see also issue #16176)
 115  	if len(z.a.abs) == 0 {
 116  		return z.norm(), true
 117  	}
 118  	// len(z.a.abs) > 0
 119  
 120  	// The mantissa may have a radix point (fcount <= 0) and there
 121  	// may be a nonzero exponent exp. The radix point amounts to a
 122  	// division by base**(-fcount), which equals a multiplication by
 123  	// base**fcount. An exponent means multiplication by ebase**exp.
 124  	// Multiplications are commutative, so we can apply them in any
 125  	// order. We only have powers of 2 and 10, and we split powers
 126  	// of 10 into the product of the same powers of 2 and 5. This
 127  	// may reduce the size of shift/multiplication factors or
 128  	// divisors required to create the final fraction, depending
 129  	// on the actual floating-point value.
 130  
 131  	// determine binary or decimal exponent contribution of radix point
 132  	var exp2, exp5 int64
 133  	if fcount < 0 {
 134  		// The mantissa has a radix point ddd.dddd; and
 135  		// -fcount is the number of digits to the right
 136  		// of '.'. Adjust relevant exponent accordingly.
 137  		d := int64(fcount)
 138  		switch base {
 139  		case 10:
 140  			exp5 = d
 141  			exp2 = d // 10**e == 5**e * 2**e
 142  		case 2:
 143  			exp2 = d
 144  		case 8:
 145  			exp2 = d * 3 // octal digits are 3 bits each
 146  		case 16:
 147  			exp2 = d * 4 // hexadecimal digits are 4 bits each
 148  		default:
 149  			panic("unexpected mantissa base")
 150  		}
 151  		// fcount consumed - not needed anymore
 152  	}
 153  
 154  	// take actual exponent into account
 155  	switch ebase {
 156  	case 10:
 157  		exp5 += exp
 158  		exp2 += exp
 159  	case 2:
 160  		exp2 += exp
 161  	default:
 162  		panic("unexpected exponent base")
 163  	}
 164  	// exp consumed - not needed anymore
 165  
 166  	stk := getStack()
 167  	defer stk.free()
 168  
 169  	// apply exp5 contributions
 170  	// (start with exp5 so the numbers to multiply are smaller)
 171  	if exp5 != 0 {
 172  		n := exp5
 173  		if n < 0 {
 174  			n = -n
 175  			if n < 0 {
 176  				// This can occur if -n overflows. -(-1 << 63) would become
 177  				// -1 << 63, which is still negative.
 178  				return nil, false
 179  			}
 180  		}
 181  		if n > 1e6 {
 182  			return nil, false // avoid excessively large exponents
 183  		}
 184  		pow5 := z.b.abs.expNN(stk, natFive, nat(nil).setWord(Word(n)), nil, false) // use underlying array of z.b.abs
 185  		if exp5 > 0 {
 186  			z.a.abs = z.a.abs.mul(stk, z.a.abs, pow5)
 187  			z.b.abs = z.b.abs.setWord(1)
 188  		} else {
 189  			z.b.abs = pow5
 190  		}
 191  	} else {
 192  		z.b.abs = z.b.abs.setWord(1)
 193  	}
 194  
 195  	// apply exp2 contributions
 196  	if exp2 < -1e7 || exp2 > 1e7 {
 197  		return nil, false // avoid excessively large exponents
 198  	}
 199  	if exp2 > 0 {
 200  		z.a.abs = z.a.abs.lsh(z.a.abs, uint(exp2))
 201  	} else if exp2 < 0 {
 202  		z.b.abs = z.b.abs.lsh(z.b.abs, uint(-exp2))
 203  	}
 204  
 205  	z.a.neg = neg && len(z.a.abs) > 0 // 0 has no sign
 206  
 207  	return z.norm(), true
 208  }
 209  
 210  // scanExponent scans the longest possible prefix of r representing a base 10
 211  // (“e”, “E”) or a base 2 (“p”, “P”) exponent, if any. It returns the
 212  // exponent, the exponent base (10 or 2), or a read or syntax error, if any.
 213  //
 214  // If sepOk is set, an underscore character “_” may appear between successive
 215  // exponent digits; such underscores do not change the value of the exponent.
 216  // Incorrect placement of underscores is reported as an error if there are no
 217  // other errors. If sepOk is not set, underscores are not recognized and thus
 218  // terminate scanning like any other character that is not a valid digit.
 219  //
 220  //	exponent = ( "e" | "E" | "p" | "P" ) [ sign ] digits .
 221  //	sign     = "+" | "-" .
 222  //	digits   = digit { [ '_' ] digit } .
 223  //	digit    = "0" ... "9" .
 224  //
 225  // A base 2 exponent is only permitted if base2ok is set.
 226  func scanExponent(r io.ByteScanner, base2ok, sepOk bool) (exp int64, base int, err error) {
 227  	// one char look-ahead
 228  	ch, err := r.ReadByte()
 229  	if err != nil {
 230  		if err == io.EOF {
 231  			err = nil
 232  		}
 233  		return 0, 10, err
 234  	}
 235  
 236  	// exponent char
 237  	switch ch {
 238  	case 'e', 'E':
 239  		base = 10
 240  	case 'p', 'P':
 241  		if base2ok {
 242  			base = 2
 243  			break // ok
 244  		}
 245  		r.UnreadByte() // ch does not belong to exponent anymore
 246  		return 0, 10, nil
 247  	default:
 248  		r.UnreadByte() // ch does not belong to exponent anymore
 249  		return 0, 10, nil
 250  	}
 251  
 252  	// sign
 253  	var digits []byte
 254  	ch, err = r.ReadByte()
 255  	if err == nil && (ch == '+' || ch == '-') {
 256  		if ch == '-' {
 257  			digits = append(digits, '-')
 258  		}
 259  		ch, err = r.ReadByte()
 260  	}
 261  
 262  	// prev encodes the previously seen char: it is one
 263  	// of '_', '0' (a digit), or '.' (anything else). A
 264  	// valid separator '_' may only occur after a digit.
 265  	prev := '.'
 266  	invalSep := false
 267  
 268  	// exponent value
 269  	hasDigits := false
 270  	for err == nil {
 271  		if '0' <= ch && ch <= '9' {
 272  			digits = append(digits, ch)
 273  			prev = '0'
 274  			hasDigits = true
 275  		} else if ch == '_' && sepOk {
 276  			if prev != '0' {
 277  				invalSep = true
 278  			}
 279  			prev = '_'
 280  		} else {
 281  			r.UnreadByte() // ch does not belong to number anymore
 282  			break
 283  		}
 284  		ch, err = r.ReadByte()
 285  	}
 286  
 287  	if err == io.EOF {
 288  		err = nil
 289  	}
 290  	if err == nil && !hasDigits {
 291  		err = errNoDigits
 292  	}
 293  	if err == nil {
 294  		exp, err = strconv.ParseInt([]byte(digits), 10, 64)
 295  	}
 296  	// other errors take precedence over invalid separators
 297  	if err == nil && (invalSep || prev == '_') {
 298  		err = errInvalSep
 299  	}
 300  
 301  	return
 302  }
 303  
 304  // String returns a string representation of x in the form "a/b" (even if b == 1).
 305  func (x *Rat) String() string {
 306  	return string(x.marshal(nil))
 307  }
 308  
 309  // marshal implements [Rat.String] returning a slice of bytes.
 310  // It appends the string representation of x in the form "a/b" (even if b == 1) to buf,
 311  // and returns the extended buffer.
 312  func (x *Rat) marshal(buf []byte) []byte {
 313  	buf = x.a.Append(buf, 10)
 314  	buf = append(buf, '/')
 315  	if len(x.b.abs) != 0 {
 316  		buf = x.b.Append(buf, 10)
 317  	} else {
 318  		buf = append(buf, '1')
 319  	}
 320  	return buf
 321  }
 322  
 323  // RatString returns a string representation of x in the form "a/b" if b != 1,
 324  // and in the form "a" if b == 1.
 325  func (x *Rat) RatString() []byte {
 326  	if x.IsInt() {
 327  		return x.a.String()
 328  	}
 329  	return x.String()
 330  }
 331  
 332  // FloatString returns a string representation of x in decimal form with prec
 333  // digits of precision after the radix point. The last digit is rounded to
 334  // nearest, with halves rounded away from zero.
 335  func (x *Rat) FloatString(prec int) []byte {
 336  	var buf []byte
 337  
 338  	if x.IsInt() {
 339  		buf = x.a.Append(buf, 10)
 340  		if prec > 0 {
 341  			buf = append(buf, '.')
 342  			for i := prec; i > 0; i-- {
 343  				buf = append(buf, '0')
 344  			}
 345  		}
 346  		return []byte(buf)
 347  	}
 348  	// x.b.abs != 0
 349  
 350  	stk := getStack()
 351  	defer stk.free()
 352  	q, r := nat(nil).div(stk, nat(nil), x.a.abs, x.b.abs)
 353  
 354  	p := natOne
 355  	if prec > 0 {
 356  		p = nat(nil).expNN(stk, natTen, nat(nil).setUint64(uint64(prec)), nil, false)
 357  	}
 358  
 359  	r = r.mul(stk, r, p)
 360  	r, r2 := r.div(stk, nat(nil), r, x.b.abs)
 361  
 362  	// see if we need to round up
 363  	r2 = r2.add(r2, r2)
 364  	if x.b.abs.cmp(r2) <= 0 {
 365  		r = r.add(r, natOne)
 366  		if r.cmp(p) >= 0 {
 367  			q = nat(nil).add(q, natOne)
 368  			r = nat(nil).sub(r, p)
 369  		}
 370  	}
 371  
 372  	if x.a.neg {
 373  		buf = append(buf, '-')
 374  	}
 375  	buf = append(buf, q.utoa(10)...) // itoa ignores sign if q == 0
 376  
 377  	if prec > 0 {
 378  		buf = append(buf, '.')
 379  		rs := r.utoa(10)
 380  		for i := prec - len(rs); i > 0; i-- {
 381  			buf = append(buf, '0')
 382  		}
 383  		buf = append(buf, rs...)
 384  	}
 385  
 386  	return []byte(buf)
 387  }
 388  
 389  // Note: FloatPrec (below) is in this file rather than rat.go because
 390  //       its results are relevant for decimal representation/printing.
 391  
 392  // FloatPrec returns the number n of non-repeating digits immediately
 393  // following the decimal point of the decimal representation of x.
 394  // The boolean result indicates whether a decimal representation of x
 395  // with that many fractional digits is exact or rounded.
 396  //
 397  // Examples:
 398  //
 399  //	x      n    exact    decimal representation n fractional digits
 400  //	0      0    true     0
 401  //	1      0    true     1
 402  //	1/2    1    true     0.5
 403  //	1/3    0    false    0       (0.333... rounded)
 404  //	1/4    2    true     0.25
 405  //	1/6    1    false    0.2     (0.166... rounded)
 406  func (x *Rat) FloatPrec() (n int, exact bool) {
 407  	stk := getStack()
 408  	defer stk.free()
 409  
 410  	// Determine q and largest p2, p5 such that d = q·2^p2·5^p5.
 411  	// The results n, exact are:
 412  	//
 413  	//     n = max(p2, p5)
 414  	//     exact = q == 1
 415  	//
 416  	// For details see:
 417  	// https://en.wikipedia.org/wiki/Repeating_decimal#Reciprocals_of_integers_not_coprime_to_10
 418  	d := x.Denom().abs // d >= 1
 419  
 420  	// Determine p2 by counting factors of 2.
 421  	// p2 corresponds to the trailing zero bits in d.
 422  	// Do this first to reduce q as much as possible.
 423  	var q nat
 424  	p2 := d.trailingZeroBits()
 425  	q = q.rsh(d, p2)
 426  
 427  	// Determine p5 by counting factors of 5.
 428  	// Build a table starting with an initial power of 5,
 429  	// and use repeated squaring until the factor doesn't
 430  	// divide q anymore. Then use the table to determine
 431  	// the power of 5 in q.
 432  	const fp = 13        // f == 5^fp
 433  	var tab []nat        // tab[i] == (5^fp)^(2^i) == 5^(fp·2^i)
 434  	f := nat{1220703125} // == 5^fp (must fit into a uint32 Word)
 435  	var t, r nat         // temporaries
 436  	for {
 437  		if _, r = t.div(stk, r, q, f); len(r) != 0 {
 438  			break // f doesn't divide q evenly
 439  		}
 440  		tab = append(tab, f)
 441  		f = nat(nil).sqr(stk, f) // nat(nil) to ensure a new f for each table entry
 442  	}
 443  
 444  	// Factor q using the table entries, if any.
 445  	// We start with the largest factor f = tab[len(tab)-1]
 446  	// that evenly divides q. It does so at most once because
 447  	// otherwise f·f would also divide q. That can't be true
 448  	// because f·f is the next higher table entry, contradicting
 449  	// how f was chosen in the first place.
 450  	// The same reasoning applies to the subsequent factors.
 451  	var p5 uint
 452  	for i := len(tab) - 1; i >= 0; i-- {
 453  		if t, r = t.div(stk, r, q, tab[i]); len(r) == 0 {
 454  			p5 += fp * (1 << i) // tab[i] == 5^(fp·2^i)
 455  			q = q.set(t)
 456  		}
 457  	}
 458  
 459  	// If fp != 1, we may still have multiples of 5 left.
 460  	for {
 461  		if t, r = t.div(stk, r, q, natFive); len(r) != 0 {
 462  			break
 463  		}
 464  		p5++
 465  		q = q.set(t)
 466  	}
 467  
 468  	return int(max(p2, p5)), q.cmp(natOne) == 0
 469  }
 470