// 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 or a value between 2 through MaxBase.
//
// 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 permitted.
// 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)
	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 characters not belonging to the
// number.
//
// TODO(gri) define possible errors more precisely
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
	var ch byte
	if ch, err = r.ReadByte(); err != io.EOF {
		if err == nil {
			err = fmt.Errorf("expected end of string, found %q", ch)
		}
	}

	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 NewFloat(0, prec, 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 NewFloat(0, prec, 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 the 'p' (rather than 'g') format.
func (x *Float) String() string {
	return x.Format('p', 0)
}

// 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)
}
