Commit 5750b711 authored by Robert Griesemer's avatar Robert Griesemer

cmd/internal/gc: move fix and flt functions into respective files (cleanups)

Also:
- introduce Mpprec (remove old constants)
- no semantic changes

Change-Id: Ie0e77e8e09bd68e09bcf8747a3d875270e736081
Reviewed-on: https://go-review.googlesource.com/8171Reviewed-by: 's avatarRuss Cox <rsc@golang.org>
parent 5bb89eb0
...@@ -24,8 +24,6 @@ func truncfltlit(oldv *Mpflt, t *Type) *Mpflt { ...@@ -24,8 +24,6 @@ func truncfltlit(oldv *Mpflt, t *Type) *Mpflt {
overflow(v, t) overflow(v, t)
fv := newMpflt() fv := newMpflt()
// *fv = *oldv
mpmovefltflt(fv, oldv) mpmovefltflt(fv, oldv)
// convert large precision literal floating // convert large precision literal floating
......
...@@ -57,9 +57,9 @@ const ( ...@@ -57,9 +57,9 @@ const (
) )
const ( const (
// TODO(gri) replace these with a single precision constant. // TODO(gri) consider increasing Mpprec to 512 or perhaps 1024
Mpscale = 29 // safely smaller than bits in a long // (this would permit enabling additional tests).
Mpprec = 16 // Mpscale*Mpprec is max number of bits Mpprec = 16 * 29 // == 464, to match original value
Mpdebug = 0 Mpdebug = 0
) )
......
// 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.
package gc
import (
"cmd/internal/gc/big"
"cmd/internal/obj"
"fmt"
)
func Mpcmpfixfix(a, b *Mpint) int {
return a.Val.Cmp(&b.Val)
}
func mpcmpfixc(b *Mpint, c int64) int {
return b.Val.Cmp(big.NewInt(c))
}
func mpcmpfltflt(a *Mpflt, b *Mpflt) int {
return a.Val.Cmp(&b.Val)
}
func mpcmpfltc(b *Mpflt, c float64) int {
var a Mpflt
Mpmovecflt(&a, c)
return mpcmpfltflt(b, &a)
}
func mpsubfixfix(a, b *Mpint) {
a.Val.Sub(&a.Val, &b.Val)
}
func mpsubfltflt(a *Mpflt, b *Mpflt) {
if Mpdebug != 0 {
fmt.Printf("\n%v - %v", Fconv(a, 0), Fconv(b, 0))
}
a.Val.Sub(&a.Val, &b.Val)
if Mpdebug != 0 {
fmt.Printf(" = %v\n\n", Fconv(a, 0))
}
}
func mpaddcflt(a *Mpflt, c float64) {
var b Mpflt
Mpmovecflt(&b, c)
mpaddfltflt(a, &b)
}
func mpmulcflt(a *Mpflt, c float64) {
var b Mpflt
Mpmovecflt(&b, c)
mpmulfltflt(a, &b)
}
func mpdivfixfix(a, b *Mpint) {
a.Val.Quo(&a.Val, &b.Val)
}
func mpmodfixfix(a, b *Mpint) {
a.Val.Rem(&a.Val, &b.Val)
}
func Mpmovefixflt(a *Mpflt, b *Mpint) {
if b.Ovf {
// sign doesn't really matter but copy anyway
a.Val.SetInf(b.Val.Sign() < 0)
return
}
a.Val.SetInt(&b.Val)
}
func mpmovefltfix(a *Mpint, b *Mpflt) int {
if _, acc := b.Val.Int(&a.Val); acc == big.Exact {
return 0
}
const delta = Mpscale // a reasonably small number of bits > 0
var t big.Float
t.SetPrec(Mpscale*Mpprec - delta)
// try rounding down a little
t.SetMode(big.ToZero)
t.Set(&b.Val)
if _, acc := t.Int(&a.Val); acc == big.Exact {
return 0
}
// try rounding up a little
t.SetMode(big.AwayFromZero)
t.Set(&b.Val)
if _, acc := t.Int(&a.Val); acc == big.Exact {
return 0
}
return -1
}
func mpmovefixfix(a, b *Mpint) {
a.Val.Set(&b.Val)
}
func mpmovefltflt(a *Mpflt, b *Mpflt) {
a.Val.Set(&b.Val)
}
//
// floating point input
// required syntax is [+-]d*[.]d*[e[+-]d*] or [+-]0xH*[e[+-]d*]
//
func mpatoflt(a *Mpflt, as string) {
for len(as) > 0 && (as[0] == ' ' || as[0] == '\t') {
as = as[1:]
}
f, ok := a.Val.SetString(as)
if !ok {
// At the moment we lose precise error cause;
// the old code additionally distinguished between:
// - malformed hex constant
// - decimal point in hex constant
// - constant exponent out of range
// - decimal point and binary point in constant
// TODO(gri) use different conversion function or check separately
Yyerror("malformed constant: %s", as)
a.Val.SetUint64(0)
}
if f.IsInf() {
Yyerror("constant too large: %s", as)
a.Val.SetUint64(0)
}
}
func mpatofix(a *Mpint, as string) {
_, ok := a.Val.SetString(as, 0)
if !ok {
// required syntax is [+-][0[x]]d*
// At the moment we lose precise error cause;
// the old code distinguished between:
// - malformed hex constant
// - malformed octal constant
// - malformed decimal constant
// TODO(gri) use different conversion function
Yyerror("malformed integer constant: %s", as)
a.Val.SetUint64(0)
return
}
if mptestovf(a, 0) {
Yyerror("constant too large: %s", as)
}
}
func Bconv(xval *Mpint, flag int) string {
if flag&obj.FmtSharp != 0 {
return fmt.Sprintf("%#x", &xval.Val)
}
return xval.Val.String()
}
func Fconv(fvp *Mpflt, flag int) string {
if flag&obj.FmtSharp != 0 {
return fvp.Val.Format('g', 6)
}
return fvp.Val.Format('b', 0)
}
...@@ -4,19 +4,11 @@ ...@@ -4,19 +4,11 @@
package gc package gc
// shift left by s (or right by -s) import (
func Mpshiftfix(a *Mpint, s int) { "cmd/internal/gc/big"
switch { "cmd/internal/obj"
case s > 0: "fmt"
if mptestovf(a, s) { )
Yyerror("constant shift overflow")
return
}
a.Val.Lsh(&a.Val, uint(s))
case s < 0:
a.Val.Rsh(&a.Val, uint(-s))
}
}
/// implements fix arithmetic /// implements fix arithmetic
...@@ -28,17 +20,49 @@ func mpsetovf(a *Mpint) { ...@@ -28,17 +20,49 @@ func mpsetovf(a *Mpint) {
func mptestovf(a *Mpint, extra int) bool { func mptestovf(a *Mpint, extra int) bool {
// We don't need to be precise here, any reasonable upper limit would do. // We don't need to be precise here, any reasonable upper limit would do.
// For now, use existing limit so we pass all the tests unchanged. // For now, use existing limit so we pass all the tests unchanged.
const limit = Mpscale * Mpprec if a.Val.BitLen()+extra > Mpprec {
if a.Val.BitLen()+extra > limit {
mpsetovf(a) mpsetovf(a)
} }
return a.Ovf return a.Ovf
} }
func mpmovefixfix(a, b *Mpint) {
a.Val.Set(&b.Val)
}
func mpmovefltfix(a *Mpint, b *Mpflt) int {
if _, acc := b.Val.Int(&a.Val); acc == big.Exact {
return 0
}
// TODO(gri) reduce the value of delta - currently
// we use the size of a mp-word of the old implementation
// for approximately similar behavior.
const delta = 29 // a reasonably small number of bits > 0
var t big.Float
t.SetPrec(Mpprec - delta)
// try rounding down a little
t.SetMode(big.ToZero)
t.Set(&b.Val)
if _, acc := t.Int(&a.Val); acc == big.Exact {
return 0
}
// try rounding up a little
t.SetMode(big.AwayFromZero)
t.Set(&b.Val)
if _, acc := t.Int(&a.Val); acc == big.Exact {
return 0
}
return -1
}
func mpaddfixfix(a, b *Mpint, quiet int) { func mpaddfixfix(a, b *Mpint, quiet int) {
if a.Ovf || b.Ovf { if a.Ovf || b.Ovf {
if nsavederrors+nerrors == 0 { if nsavederrors+nerrors == 0 {
Yyerror("ovf in mpaddxx") Yyerror("ovf in mpaddfixfix")
} }
mpsetovf(a) mpsetovf(a)
return return
...@@ -51,6 +75,22 @@ func mpaddfixfix(a, b *Mpint, quiet int) { ...@@ -51,6 +75,22 @@ func mpaddfixfix(a, b *Mpint, quiet int) {
} }
} }
func mpsubfixfix(a, b *Mpint) {
if a.Ovf || b.Ovf {
if nsavederrors+nerrors == 0 {
Yyerror("ovf in mpsubfixfix")
}
mpsetovf(a)
return
}
a.Val.Sub(&a.Val, &b.Val)
if mptestovf(a, 0) {
Yyerror("constant subtraction overflow")
}
}
func mpmulfixfix(a, b *Mpint) { func mpmulfixfix(a, b *Mpint) {
if a.Ovf || b.Ovf { if a.Ovf || b.Ovf {
if nsavederrors+nerrors == 0 { if nsavederrors+nerrors == 0 {
...@@ -67,6 +107,40 @@ func mpmulfixfix(a, b *Mpint) { ...@@ -67,6 +107,40 @@ func mpmulfixfix(a, b *Mpint) {
} }
} }
func mpdivfixfix(a, b *Mpint) {
if a.Ovf || b.Ovf {
if nsavederrors+nerrors == 0 {
Yyerror("ovf in mpdivfixfix")
}
mpsetovf(a)
return
}
a.Val.Quo(&a.Val, &b.Val)
if mptestovf(a, 0) {
// can only happen for div-0 which should be checked elsewhere
Yyerror("constant division overflow")
}
}
func mpmodfixfix(a, b *Mpint) {
if a.Ovf || b.Ovf {
if nsavederrors+nerrors == 0 {
Yyerror("ovf in mpmodfixfix")
}
mpsetovf(a)
return
}
a.Val.Rem(&a.Val, &b.Val)
if mptestovf(a, 0) {
// should never happen
Yyerror("constant modulo overflow")
}
}
func mporfixfix(a, b *Mpint) { func mporfixfix(a, b *Mpint) {
if a.Ovf || b.Ovf { if a.Ovf || b.Ovf {
if nsavederrors+nerrors == 0 { if nsavederrors+nerrors == 0 {
...@@ -115,6 +189,20 @@ func mpxorfixfix(a, b *Mpint) { ...@@ -115,6 +189,20 @@ func mpxorfixfix(a, b *Mpint) {
a.Val.Xor(&a.Val, &b.Val) a.Val.Xor(&a.Val, &b.Val)
} }
// shift left by s (or right by -s)
func Mpshiftfix(a *Mpint, s int) {
switch {
case s > 0:
if mptestovf(a, s) {
Yyerror("constant shift overflow")
return
}
a.Val.Lsh(&a.Val, uint(s))
case s < 0:
a.Val.Rsh(&a.Val, uint(-s))
}
}
func mplshfixfix(a, b *Mpint) { func mplshfixfix(a, b *Mpint) {
if a.Ovf || b.Ovf { if a.Ovf || b.Ovf {
if nsavederrors+nerrors == 0 { if nsavederrors+nerrors == 0 {
...@@ -125,7 +213,7 @@ func mplshfixfix(a, b *Mpint) { ...@@ -125,7 +213,7 @@ func mplshfixfix(a, b *Mpint) {
} }
s := Mpgetfix(b) s := Mpgetfix(b)
if s < 0 || s >= Mpprec*Mpscale { if s < 0 || s >= Mpprec {
Yyerror("stupid shift: %d", s) Yyerror("stupid shift: %d", s)
Mpmovecfix(a, 0) Mpmovecfix(a, 0)
return return
...@@ -144,7 +232,7 @@ func mprshfixfix(a, b *Mpint) { ...@@ -144,7 +232,7 @@ func mprshfixfix(a, b *Mpint) {
} }
s := Mpgetfix(b) s := Mpgetfix(b)
if s < 0 || s >= Mpprec*Mpscale { if s < 0 || s >= Mpprec {
Yyerror("stupid shift: %d", s) Yyerror("stupid shift: %d", s)
if a.Val.Sign() < 0 { if a.Val.Sign() < 0 {
Mpmovecfix(a, -1) Mpmovecfix(a, -1)
...@@ -157,6 +245,14 @@ func mprshfixfix(a, b *Mpint) { ...@@ -157,6 +245,14 @@ func mprshfixfix(a, b *Mpint) {
Mpshiftfix(a, int(-s)) Mpshiftfix(a, int(-s))
} }
func Mpcmpfixfix(a, b *Mpint) int {
return a.Val.Cmp(&b.Val)
}
func mpcmpfixc(b *Mpint, c int64) int {
return b.Val.Cmp(big.NewInt(c))
}
func mpnegfix(a *Mpint) { func mpnegfix(a *Mpint) {
a.Val.Neg(&a.Val) a.Val.Neg(&a.Val)
} }
...@@ -175,3 +271,29 @@ func Mpgetfix(a *Mpint) int64 { ...@@ -175,3 +271,29 @@ func Mpgetfix(a *Mpint) int64 {
func Mpmovecfix(a *Mpint, c int64) { func Mpmovecfix(a *Mpint, c int64) {
a.Val.SetInt64(c) a.Val.SetInt64(c)
} }
func mpatofix(a *Mpint, as string) {
_, ok := a.Val.SetString(as, 0)
if !ok {
// required syntax is [+-][0[x]]d*
// At the moment we lose precise error cause;
// the old code distinguished between:
// - malformed hex constant
// - malformed octal constant
// - malformed decimal constant
// TODO(gri) use different conversion function
Yyerror("malformed integer constant: %s", as)
a.Val.SetUint64(0)
return
}
if mptestovf(a, 0) {
Yyerror("constant too large: %s", as)
}
}
func Bconv(xval *Mpint, flag int) string {
if flag&obj.FmtSharp != 0 {
return fmt.Sprintf("%#x", &xval.Val)
}
return xval.Val.String()
}
...@@ -5,17 +5,31 @@ ...@@ -5,17 +5,31 @@
package gc package gc
import ( import (
"cmd/internal/obj"
"fmt" "fmt"
"math" "math"
) )
/// implements float arihmetic
func newMpflt() *Mpflt { func newMpflt() *Mpflt {
var a Mpflt var a Mpflt
a.Val.SetPrec(Mpscale * Mpprec) a.Val.SetPrec(Mpprec)
return &a return &a
} }
/// implements float arihmetic func Mpmovefixflt(a *Mpflt, b *Mpint) {
if b.Ovf {
// sign doesn't really matter but copy anyway
a.Val.SetInf(b.Val.Sign() < 0)
return
}
a.Val.SetInt(&b.Val)
}
func mpmovefltflt(a *Mpflt, b *Mpflt) {
a.Val.Set(&b.Val)
}
func mpaddfltflt(a *Mpflt, b *Mpflt) { func mpaddfltflt(a *Mpflt, b *Mpflt) {
if Mpdebug != 0 { if Mpdebug != 0 {
...@@ -29,6 +43,25 @@ func mpaddfltflt(a *Mpflt, b *Mpflt) { ...@@ -29,6 +43,25 @@ func mpaddfltflt(a *Mpflt, b *Mpflt) {
} }
} }
func mpaddcflt(a *Mpflt, c float64) {
var b Mpflt
Mpmovecflt(&b, c)
mpaddfltflt(a, &b)
}
func mpsubfltflt(a *Mpflt, b *Mpflt) {
if Mpdebug != 0 {
fmt.Printf("\n%v - %v", Fconv(a, 0), Fconv(b, 0))
}
a.Val.Sub(&a.Val, &b.Val)
if Mpdebug != 0 {
fmt.Printf(" = %v\n\n", Fconv(a, 0))
}
}
func mpmulfltflt(a *Mpflt, b *Mpflt) { func mpmulfltflt(a *Mpflt, b *Mpflt) {
if Mpdebug != 0 { if Mpdebug != 0 {
fmt.Printf("%v\n * %v\n", Fconv(a, 0), Fconv(b, 0)) fmt.Printf("%v\n * %v\n", Fconv(a, 0), Fconv(b, 0))
...@@ -41,6 +74,13 @@ func mpmulfltflt(a *Mpflt, b *Mpflt) { ...@@ -41,6 +74,13 @@ func mpmulfltflt(a *Mpflt, b *Mpflt) {
} }
} }
func mpmulcflt(a *Mpflt, c float64) {
var b Mpflt
Mpmovecflt(&b, c)
mpmulfltflt(a, &b)
}
func mpdivfltflt(a *Mpflt, b *Mpflt) { func mpdivfltflt(a *Mpflt, b *Mpflt) {
if Mpdebug != 0 { if Mpdebug != 0 {
fmt.Printf("%v\n / %v\n", Fconv(a, 0), Fconv(b, 0)) fmt.Printf("%v\n / %v\n", Fconv(a, 0), Fconv(b, 0))
...@@ -53,6 +93,17 @@ func mpdivfltflt(a *Mpflt, b *Mpflt) { ...@@ -53,6 +93,17 @@ func mpdivfltflt(a *Mpflt, b *Mpflt) {
} }
} }
func mpcmpfltflt(a *Mpflt, b *Mpflt) int {
return a.Val.Cmp(&b.Val)
}
func mpcmpfltc(b *Mpflt, c float64) int {
var a Mpflt
Mpmovecflt(&a, c)
return mpcmpfltflt(b, &a)
}
func mpgetfltN(a *Mpflt, prec int, bias int) float64 { func mpgetfltN(a *Mpflt, prec int, bias int) float64 {
var x float64 var x float64
switch prec { switch prec {
...@@ -103,3 +154,38 @@ func Mpmovecflt(a *Mpflt, c float64) { ...@@ -103,3 +154,38 @@ func Mpmovecflt(a *Mpflt, c float64) {
func mpnegflt(a *Mpflt) { func mpnegflt(a *Mpflt) {
a.Val.Neg(&a.Val) a.Val.Neg(&a.Val)
} }
//
// floating point input
// required syntax is [+-]d*[.]d*[e[+-]d*] or [+-]0xH*[e[+-]d*]
//
func mpatoflt(a *Mpflt, as string) {
for len(as) > 0 && (as[0] == ' ' || as[0] == '\t') {
as = as[1:]
}
f, ok := a.Val.SetString(as)
if !ok {
// At the moment we lose precise error cause;
// the old code additionally distinguished between:
// - malformed hex constant
// - decimal point in hex constant
// - constant exponent out of range
// - decimal point and binary point in constant
// TODO(gri) use different conversion function or check separately
Yyerror("malformed constant: %s", as)
a.Val.SetUint64(0)
}
if f.IsInf() {
Yyerror("constant too large: %s", as)
a.Val.SetUint64(0)
}
}
func Fconv(fvp *Mpflt, flag int) string {
if flag&obj.FmtSharp != 0 {
return fvp.Val.Format('g', 6)
}
return fvp.Val.Format('b', 0)
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment