URL
https://opencores.org/ocsvn/openrisc/openrisc/trunk
Subversion Repositories openrisc
[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libgo/] [go/] [strconv/] [ftoa.go] - Rev 747
Compare with Previous | Blame | View Log
// Copyright 2009 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.// Binary to decimal floating point conversion.// Algorithm:// 1) store mantissa in multiprecision decimal// 2) shift decimal by exponent// 3) read digits out & formatpackage strconvimport "math"// TODO: move elsewhere?type floatInfo struct {mantbits uintexpbits uintbias int}var float32info = floatInfo{23, 8, -127}var float64info = floatInfo{52, 11, -1023}// FormatFloat converts the floating-point number f to a string,// according to the format fmt and precision prec. It rounds the// result assuming that the original was obtained from a floating-point// value of bitSize bits (32 for float32, 64 for float64).//// The format fmt is one of// 'b' (-ddddp±ddd, a binary exponent),// 'e' (-d.dddde±dd, a decimal exponent),// 'E' (-d.ddddE±dd, a decimal exponent),// 'f' (-ddd.dddd, no exponent),// 'g' ('e' for large exponents, 'f' otherwise), or// 'G' ('E' for large exponents, 'f' otherwise).//// 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.// The special precision -1 uses the smallest number of digits// necessary such that ParseFloat will return f exactly.func FormatFloat(f float64, fmt byte, prec, bitSize int) string {return string(genericFtoa(make([]byte, 0, max(prec+4, 24)), f, fmt, prec, bitSize))}// AppendFloat appends the string form of the floating-point number f,// as generated by FormatFloat, to dst and returns the extended buffer.func AppendFloat(dst []byte, f float64, fmt byte, prec int, bitSize int) []byte {return genericFtoa(dst, f, fmt, prec, bitSize)}func genericFtoa(dst []byte, val float64, fmt byte, prec, bitSize int) []byte {var bits uint64var flt *floatInfoswitch bitSize {case 32:bits = uint64(math.Float32bits(float32(val)))flt = &float32infocase 64:bits = math.Float64bits(val)flt = &float64infodefault:panic("strconv: illegal AppendFloat/FormatFloat bitSize")}neg := bits>>(flt.expbits+flt.mantbits) != 0exp := int(bits>>flt.mantbits) & (1<<flt.expbits - 1)mant := bits & (uint64(1)<<flt.mantbits - 1)switch exp {case 1<<flt.expbits - 1:// Inf, NaNvar s stringswitch {case mant != 0:s = "NaN"case neg:s = "-Inf"default:s = "+Inf"}return append(dst, s...)case 0:// denormalizedexp++default:// add implicit top bitmant |= uint64(1) << flt.mantbits}exp += flt.bias// Pick off easy binary format.if fmt == 'b' {return fmtB(dst, neg, mant, exp, flt)}// Negative precision means "only as much as needed to be exact."shortest := prec < 0d := new(decimal)if shortest {ok := falseif optimize && bitSize == 64 {// Try Grisu3 algorithm.f := new(extFloat)lower, upper := f.AssignComputeBounds(val)ok = f.ShortestDecimal(d, &lower, &upper)}if !ok {// Create exact decimal representation.// The shift is exp - flt.mantbits because mant is a 1-bit integer// followed by a flt.mantbits fraction, and we are treating it as// a 1+flt.mantbits-bit integer.d.Assign(mant)d.Shift(exp - int(flt.mantbits))roundShortest(d, mant, exp, flt)}// Precision for shortest representation mode.if prec < 0 {switch fmt {case 'e', 'E':prec = d.nd - 1case 'f':prec = max(d.nd-d.dp, 0)case 'g', 'G':prec = d.nd}}} else {// Create exact decimal representation.d.Assign(mant)d.Shift(exp - int(flt.mantbits))// Round appropriately.switch fmt {case 'e', 'E':d.Round(prec + 1)case 'f':d.Round(d.dp + prec)case 'g', 'G':if prec == 0 {prec = 1}d.Round(prec)}}switch fmt {case 'e', 'E':return fmtE(dst, neg, d, prec, fmt)case 'f':return fmtF(dst, neg, d, prec)case 'g', 'G':// trailing fractional zeros in 'e' form will be trimmed.eprec := precif eprec > d.nd && d.nd >= d.dp {eprec = d.nd}// %e is used if the exponent from the conversion// is less than -4 or greater than or equal to the precision.// if precision was the shortest possible, use precision 6 for this decision.if shortest {eprec = 6}exp := d.dp - 1if exp < -4 || exp >= eprec {if prec > d.nd {prec = d.nd}return fmtE(dst, neg, d, prec-1, fmt+'e'-'g')}if prec > d.dp {prec = d.nd}return fmtF(dst, neg, d, max(prec-d.dp, 0))}// unknown formatreturn append(dst, '%', fmt)}// Round d (= mant * 2^exp) to the shortest number of digits// that will let the original floating point value be precisely// reconstructed. Size is original floating point size (64 or 32).func roundShortest(d *decimal, mant uint64, exp int, flt *floatInfo) {// If mantissa is zero, the number is zero; stop now.if mant == 0 {d.nd = 0return}// Compute upper and lower such that any decimal number// between upper and lower (possibly inclusive)// will round to the original floating point number.// We may see at once that the number is already shortest.//// Suppose d is not denormal, so that 2^exp <= d < 10^dp.// The closest shorter number is at least 10^(dp-nd) away.// The lower/upper bounds computed below are at distance// at most 2^(exp-mantbits).//// So the number is already shortest if 10^(dp-nd) > 2^(exp-mantbits),// or equivalently log2(10)*(dp-nd) > exp-mantbits.// It is true if 332/100*(dp-nd) >= exp-mantbits (log2(10) > 3.32).minexp := flt.bias + 1 // minimum possible exponentif exp > minexp && 332*(d.dp-d.nd) >= 100*(exp-int(flt.mantbits)) {// The number is already shortest.return}// d = mant << (exp - mantbits)// Next highest floating point number is mant+1 << exp-mantbits.// Our upper bound is halfway inbetween, mant*2+1 << exp-mantbits-1.upper := new(decimal)upper.Assign(mant*2 + 1)upper.Shift(exp - int(flt.mantbits) - 1)// d = mant << (exp - mantbits)// Next lowest floating point number is mant-1 << exp-mantbits,// unless mant-1 drops the significant bit and exp is not the minimum exp,// in which case the next lowest is mant*2-1 << exp-mantbits-1.// Either way, call it mantlo << explo-mantbits.// Our lower bound is halfway inbetween, mantlo*2+1 << explo-mantbits-1.var mantlo uint64var explo intif mant > 1<<flt.mantbits || exp == minexp {mantlo = mant - 1explo = exp} else {mantlo = mant*2 - 1explo = exp - 1}lower := new(decimal)lower.Assign(mantlo*2 + 1)lower.Shift(explo - int(flt.mantbits) - 1)// The upper and lower bounds are possible outputs only if// the original mantissa is even, so that IEEE round-to-even// would round to the original mantissa and not the neighbors.inclusive := mant%2 == 0// Now we can figure out the minimum number of digits required.// Walk along until d has distinguished itself from upper and lower.for i := 0; i < d.nd; i++ {var l, m, u byte // lower, middle, upper digitsif i < lower.nd {l = lower.d[i]} else {l = '0'}m = d.d[i]if i < upper.nd {u = upper.d[i]} else {u = '0'}// Okay to round down (truncate) if lower has a different digit// or if lower is inclusive and is exactly the result of rounding down.okdown := l != m || (inclusive && l == m && i+1 == lower.nd)// Okay to round up if upper has a different digit and// either upper is inclusive or upper is bigger than the result of rounding up.okup := m != u && (inclusive || m+1 < u || i+1 < upper.nd)// If it's okay to do either, then round to the nearest one.// If it's okay to do only one, do it.switch {case okdown && okup:d.Round(i + 1)returncase okdown:d.RoundDown(i + 1)returncase okup:d.RoundUp(i + 1)return}}}// %e: -d.ddddde±ddfunc fmtE(dst []byte, neg bool, d *decimal, prec int, fmt byte) []byte {// signif neg {dst = append(dst, '-')}// first digitch := byte('0')if d.nd != 0 {ch = d.d[0]}dst = append(dst, ch)// .moredigitsif prec > 0 {dst = append(dst, '.')for i := 1; i <= prec; i++ {ch = '0'if i < d.nd {ch = d.d[i]}dst = append(dst, ch)}}// e±dst = append(dst, fmt)exp := d.dp - 1if d.nd == 0 { // special case: 0 has exponent 0exp = 0}if exp < 0 {ch = '-'exp = -exp} else {ch = '+'}dst = append(dst, ch)// ddddvar buf [3]bytei := len(buf)for exp >= 10 {i--buf[i] = byte(exp%10 + '0')exp /= 10}// exp < 10i--buf[i] = byte(exp + '0')// leading zeroesif i > len(buf)-2 {i--buf[i] = '0'}return append(dst, buf[i:]...)}// %f: -ddddddd.dddddfunc fmtF(dst []byte, neg bool, d *decimal, prec int) []byte {// signif neg {dst = append(dst, '-')}// integer, padded with zeros as needed.if d.dp > 0 {var i intfor i = 0; i < d.dp && i < d.nd; i++ {dst = append(dst, d.d[i])}for ; i < d.dp; i++ {dst = append(dst, '0')}} else {dst = append(dst, '0')}// fractionif prec > 0 {dst = append(dst, '.')for i := 0; i < prec; i++ {ch := byte('0')if j := d.dp + i; 0 <= j && j < d.nd {ch = d.d[j]}dst = append(dst, ch)}}return dst}// %b: -ddddddddp+dddfunc fmtB(dst []byte, neg bool, mant uint64, exp int, flt *floatInfo) []byte {var buf [50]bytew := len(buf)exp -= int(flt.mantbits)esign := byte('+')if exp < 0 {esign = '-'exp = -exp}n := 0for exp > 0 || n < 1 {n++w--buf[w] = byte(exp%10 + '0')exp /= 10}w--buf[w] = esignw--buf[w] = 'p'n = 0for mant > 0 || n < 1 {n++w--buf[w] = byte(mant%10 + '0')mant /= 10}if neg {w--buf[w] = '-'}return append(dst, buf[w:]...)}func max(a, b int) int {if a > b {return a}return b}
