// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// This file implements float-to-string conversion functions.

package big

import (
	"fmt"
	"io"
	"strconv"
	"strings"
)

// SetString sets z to the value of s and returns z and a boolean indicating
// success. s must be a floating-point number of the same format as accepted
// by Scan, with number prefixes permitted.
func (z *Float) SetString(s string) (*Float, bool) {
	r := strings.NewReader(s)

	f, _, err := z.Scan(r, 0)
	if err != nil {
		return nil, false
	}

	// there should be no unread characters left
	if _, _, err = r.ReadRune(); err != io.EOF {
		return nil, false
	}

	return f, true
}

// Scan scans the number corresponding to the longest possible prefix
// of r representing a floating-point number with a mantissa in the
// given conversion base (the exponent is always a decimal number).
// It returns the corresponding Float f, the actual base b, and an
// error err, if any. The number must be of the form:
//
//	number   = [ sign ] [ prefix ] mantissa [ exponent ] .
//	sign     = "+" | "-" .
//      prefix   = "0" ( "x" | "X" | "b" | "B" ) .
//	mantissa = digits | digits "." [ digits ] | "." digits .
//	exponent = ( "E" | "e" | "p" ) [ sign ] digits .
//	digits   = digit { digit } .
//	digit    = "0" ... "9" | "a" ... "z" | "A" ... "Z" .
//
// The base argument must be 0, 2, 10, or 16. Providing an invalid base
// argument will lead to a run-time panic.
//
// For base 0, the number prefix determines the actual base: A prefix of
// ``0x'' or ``0X'' selects base 16, and a ``0b'' or ``0B'' prefix selects
// base 2; otherwise, the actual base is 10 and no prefix is accepted.
// The octal prefix ``0'' is not supported.
//
// A "p" exponent indicates power of 2 for the exponent; for instance "1.2p3"
// with base 0 or 10 corresponds to the value 1.2 * 2**3.
//
// BUG(gri) This signature conflicts with Scan(s fmt.ScanState, ch rune) error.
// TODO(gri) What should the default precision be?
func (z *Float) Scan(r io.ByteScanner, base int) (f *Float, b int, err error) {
	// sign
	z.neg, err = scanSign(r)
	if err != nil {
		return
	}

	// mantissa
	var ecorr int // decimal exponent correction; valid if <= 0
	z.mant, b, ecorr, err = z.mant.scan(r, base, true)
	if err != nil {
		return
	}

	// exponent
	var exp int64
	var ebase int
	exp, ebase, err = scanExponent(r, true)
	if err != nil {
		return
	}
	// special-case 0
	if len(z.mant) == 0 {
		z.exp = 0
		f = z
		return
	}
	// len(z.mant) > 0

	// determine binary (exp2) and decimal (exp) exponent
	exp2 := int64(len(z.mant)*_W - int(fnorm(z.mant)))
	if ebase == 2 {
		exp2 += exp
		exp = 0
	}
	if ecorr < 0 {
		exp += int64(ecorr)
	}

	z.setExp(exp2)
	if exp == 0 {
		// no decimal exponent
		z.round(0)
		f = z
		return
	}
	// exp != 0

	// compute decimal exponent power
	expabs := exp
	if expabs < 0 {
		expabs = -expabs
	}
	powTen := new(Float).SetInt(new(Int).SetBits(nat(nil).expNN(natTen, nat(nil).setWord(Word(expabs)), nil)))

	// correct result
	if exp < 0 {
		z.uquo(z, powTen)
	} else {
		z.umul(z, powTen)
	}

	f = z
	return
}

// Parse is like z.Scan(r, base), but instead of reading from an
// io.ByteScanner, it parses the string s. An error is returned if
// the string contains invalid or trailing bytes not belonging to
// the number.
func (z *Float) Parse(s string, base int) (f *Float, b int, err error) {
	r := strings.NewReader(s)

	if f, b, err = z.Scan(r, base); err != nil {
		return
	}

	// entire string must have been consumed
	if ch, err2 := r.ReadByte(); err2 == nil {
		err = fmt.Errorf("expected end of string, found %q", ch)
	} else if err2 != io.EOF {
		err = err2
	}

	return
}

// ScanFloat is like f.Scan(r, base) with f set to the given precision
// and rounding mode.
func ScanFloat(r io.ByteScanner, base int, prec uint, mode RoundingMode) (f *Float, b int, err error) {
	return new(Float).SetPrec(prec).SetMode(mode).Scan(r, base)
}

// ParseFloat is like f.Parse(s, base) with f set to the given precision
// and rounding mode.
func ParseFloat(s string, base int, prec uint, mode RoundingMode) (f *Float, b int, err error) {
	return new(Float).SetPrec(prec).SetMode(mode).Parse(s, base)
}

// Format converts the floating-point number x to a string according
// to the given format and precision prec. The format is one of:
//
//	'e'	-d.dddde±dd, decimal exponent, at least two (possibly 0) exponent digits
//	'E'	-d.ddddE±dd, decimal exponent, at least two (possibly 0) exponent digits
//	'f'	-ddddd.dddd, no exponent
//	'g'	like 'e' for large exponents, like 'f' otherwise
//	'G'	like 'E' for large exponents, like 'f' otherwise
//	'b'	-ddddddp±dd, binary exponent
//	'p'	-0x.dddp±dd, binary exponent, hexadecimal mantissa
//
// For the binary exponent formats, the mantissa is printed in normalized form:
//
//	'b'	decimal integer mantissa using x.Precision() bits, or -0
//	'p'	hexadecimal fraction with 0.5 <= 0.mantissa < 1.0, or -0
//
// The precision prec controls the number of digits (excluding the exponent)
// printed by the 'e', 'E', 'f', 'g', and 'G' formats. For 'e', 'E', and 'f'
// it is the number of digits after the decimal point. For 'g' and 'G' it is
// the total number of digits. A negative precision selects the smallest
// number of digits necessary such that ParseFloat will return f exactly.
// The prec value is ignored for the 'b' or 'p' format.
//
// BUG(gri) Currently, Format does not accept negative precisions.
func (x *Float) Format(format byte, prec int) string {
	const extra = 10 // TODO(gri) determine a good/better value here
	return string(x.Append(make([]byte, 0, prec+extra), format, prec))
}

// Append appends the string form of the floating-point number x,
// as generated by x.Format, to buf and returns the extended buffer.
func (x *Float) Append(buf []byte, format byte, prec int) []byte {
	// TODO(gri) factor out handling of sign?

	// Inf
	if x.IsInf(0) {
		var ch byte = '+'
		if x.neg {
			ch = '-'
		}
		buf = append(buf, ch)
		return append(buf, "Inf"...)
	}

	// easy formats
	switch format {
	case 'b':
		return x.bstring(buf)
	case 'p':
		return x.pstring(buf)
	}

	return x.bigFtoa(buf, format, prec)
}

// BUG(gri): Currently, String uses x.Format('g', 10) rather than x.Format('g', -1).
func (x *Float) String() string {
	return x.Format('g', 10)
}

// bstring appends the string of x in the format ["-"] mantissa "p" exponent
// with a decimal mantissa and a binary exponent, or ["-"] "0" if x is zero,
// and returns the extended buffer.
// The mantissa is normalized such that is uses x.Precision() bits in binary
// representation.
func (x *Float) bstring(buf []byte) []byte {
	if x.neg {
		buf = append(buf, '-')
	}
	if len(x.mant) == 0 {
		return append(buf, '0')
	}
	// x != 0
	// normalize mantissa
	m := x.mant
	t := uint(len(x.mant)*_W) - x.prec // 0 <= t < _W
	if t > 0 {
		m = nat(nil).shr(m, t)
	}
	buf = append(buf, m.decimalString()...)
	buf = append(buf, 'p')
	e := int64(x.exp) - int64(x.prec)
	if e >= 0 {
		buf = append(buf, '+')
	}
	return strconv.AppendInt(buf, e, 10)
}

// pstring appends the string of x in the format ["-"] "0x." mantissa "p" exponent
// with a hexadecimal mantissa and a binary exponent, or ["-"] "0" if x is zero,
// ad returns the extended buffer.
// The mantissa is normalized such that 0.5 <= 0.mantissa < 1.0.
func (x *Float) pstring(buf []byte) []byte {
	if x.neg {
		buf = append(buf, '-')
	}
	if len(x.mant) == 0 {
		return append(buf, '0')
	}
	// x != 0
	// mantissa is stored in normalized form
	buf = append(buf, "0x."...)
	buf = append(buf, strings.TrimRight(x.mant.hexString(), "0")...)
	buf = append(buf, 'p')
	return strconv.AppendInt(buf, int64(x.exp), 10)
}
