mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
First draft of converted Go compiler, using rsc.io/c2go rev 83d795a. Change-Id: I29f4c7010de07d2ff1947bbca9865879d83c32c3 Reviewed-on: https://go-review.googlesource.com/4851 Reviewed-by: Rob Pike <r@golang.org>
377 lines
5.5 KiB
Go
377 lines
5.5 KiB
Go
// 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 (
|
|
"fmt"
|
|
"math"
|
|
)
|
|
|
|
/*
|
|
* returns the leading non-zero
|
|
* word of the number
|
|
*/
|
|
func sigfig(a *Mpflt) int {
|
|
var i int
|
|
|
|
for i = Mpprec - 1; i >= 0; i-- {
|
|
if a.Val.A[i] != 0 {
|
|
break
|
|
}
|
|
}
|
|
|
|
//print("sigfig %d %d\n", i-z+1, z);
|
|
return i + 1
|
|
}
|
|
|
|
/*
|
|
* sets the exponent.
|
|
* a too large exponent is an error.
|
|
* a too small exponent rounds the number to zero.
|
|
*/
|
|
func mpsetexp(a *Mpflt, exp int) {
|
|
if int(int16(exp)) != exp {
|
|
if exp > 0 {
|
|
Yyerror("float constant is too large")
|
|
a.Exp = 0x7fff
|
|
} else {
|
|
Mpmovecflt(a, 0)
|
|
}
|
|
} else {
|
|
a.Exp = int16(exp)
|
|
}
|
|
}
|
|
|
|
/*
|
|
* shifts the leading non-zero
|
|
* word of the number to Mpnorm
|
|
*/
|
|
func mpnorm(a *Mpflt) {
|
|
var s int
|
|
var os int
|
|
var x int
|
|
|
|
os = sigfig(a)
|
|
if os == 0 {
|
|
// zero
|
|
a.Exp = 0
|
|
|
|
a.Val.Neg = 0
|
|
return
|
|
}
|
|
|
|
// this will normalize to the nearest word
|
|
x = a.Val.A[os-1]
|
|
|
|
s = (Mpnorm - os) * Mpscale
|
|
|
|
// further normalize to the nearest bit
|
|
for {
|
|
x <<= 1
|
|
if x&Mpbase != 0 {
|
|
break
|
|
}
|
|
s++
|
|
if x == 0 {
|
|
// this error comes from trying to
|
|
// convert an Inf or something
|
|
// where the initial x=0x80000000
|
|
s = (Mpnorm - os) * Mpscale
|
|
|
|
break
|
|
}
|
|
}
|
|
|
|
Mpshiftfix(&a.Val, s)
|
|
mpsetexp(a, int(a.Exp)-s)
|
|
}
|
|
|
|
/// implements float arihmetic
|
|
|
|
func mpaddfltflt(a *Mpflt, b *Mpflt) {
|
|
var sa int
|
|
var sb int
|
|
var s int
|
|
var c Mpflt
|
|
|
|
if Mpdebug != 0 /*TypeKind(100016)*/ {
|
|
fmt.Printf("\n%v + %v", Fconv(a, 0), Fconv(b, 0))
|
|
}
|
|
|
|
sa = sigfig(a)
|
|
if sa == 0 {
|
|
mpmovefltflt(a, b)
|
|
goto out
|
|
}
|
|
|
|
sb = sigfig(b)
|
|
if sb == 0 {
|
|
goto out
|
|
}
|
|
|
|
s = int(a.Exp) - int(b.Exp)
|
|
if s > 0 {
|
|
// a is larger, shift b right
|
|
mpmovefltflt(&c, b)
|
|
|
|
Mpshiftfix(&c.Val, -s)
|
|
mpaddfixfix(&a.Val, &c.Val, 0)
|
|
goto out
|
|
}
|
|
|
|
if s < 0 {
|
|
// b is larger, shift a right
|
|
Mpshiftfix(&a.Val, s)
|
|
|
|
mpsetexp(a, int(a.Exp)-s)
|
|
mpaddfixfix(&a.Val, &b.Val, 0)
|
|
goto out
|
|
}
|
|
|
|
mpaddfixfix(&a.Val, &b.Val, 0)
|
|
|
|
out:
|
|
mpnorm(a)
|
|
if Mpdebug != 0 /*TypeKind(100016)*/ {
|
|
fmt.Printf(" = %v\n\n", Fconv(a, 0))
|
|
}
|
|
}
|
|
|
|
func mpmulfltflt(a *Mpflt, b *Mpflt) {
|
|
var sa int
|
|
var sb int
|
|
|
|
if Mpdebug != 0 /*TypeKind(100016)*/ {
|
|
fmt.Printf("%v\n * %v\n", Fconv(a, 0), Fconv(b, 0))
|
|
}
|
|
|
|
sa = sigfig(a)
|
|
if sa == 0 {
|
|
// zero
|
|
a.Exp = 0
|
|
|
|
a.Val.Neg = 0
|
|
return
|
|
}
|
|
|
|
sb = sigfig(b)
|
|
if sb == 0 {
|
|
// zero
|
|
mpmovefltflt(a, b)
|
|
|
|
return
|
|
}
|
|
|
|
mpmulfract(&a.Val, &b.Val)
|
|
mpsetexp(a, (int(a.Exp)+int(b.Exp))+Mpscale*Mpprec-Mpscale-1)
|
|
|
|
mpnorm(a)
|
|
if Mpdebug != 0 /*TypeKind(100016)*/ {
|
|
fmt.Printf(" = %v\n\n", Fconv(a, 0))
|
|
}
|
|
}
|
|
|
|
func mpdivfltflt(a *Mpflt, b *Mpflt) {
|
|
var sa int
|
|
var sb int
|
|
var c Mpflt
|
|
|
|
if Mpdebug != 0 /*TypeKind(100016)*/ {
|
|
fmt.Printf("%v\n / %v\n", Fconv(a, 0), Fconv(b, 0))
|
|
}
|
|
|
|
sb = sigfig(b)
|
|
if sb == 0 {
|
|
// zero and ovfl
|
|
a.Exp = 0
|
|
|
|
a.Val.Neg = 0
|
|
a.Val.Ovf = 1
|
|
Yyerror("constant division by zero")
|
|
return
|
|
}
|
|
|
|
sa = sigfig(a)
|
|
if sa == 0 {
|
|
// zero
|
|
a.Exp = 0
|
|
|
|
a.Val.Neg = 0
|
|
return
|
|
}
|
|
|
|
// adjust b to top
|
|
mpmovefltflt(&c, b)
|
|
|
|
Mpshiftfix(&c.Val, Mpscale)
|
|
|
|
// divide
|
|
mpdivfract(&a.Val, &c.Val)
|
|
|
|
mpsetexp(a, (int(a.Exp)-int(c.Exp))-Mpscale*(Mpprec-1)+1)
|
|
|
|
mpnorm(a)
|
|
if Mpdebug != 0 /*TypeKind(100016)*/ {
|
|
fmt.Printf(" = %v\n\n", Fconv(a, 0))
|
|
}
|
|
}
|
|
|
|
func mpgetfltN(a *Mpflt, prec int, bias int) float64 {
|
|
var s int
|
|
var i int
|
|
var e int
|
|
var minexp int
|
|
var v uint64
|
|
var f float64
|
|
|
|
if a.Val.Ovf != 0 && nsavederrors+nerrors == 0 {
|
|
Yyerror("mpgetflt ovf")
|
|
}
|
|
|
|
s = sigfig(a)
|
|
if s == 0 {
|
|
return 0
|
|
}
|
|
|
|
if s != Mpnorm {
|
|
Yyerror("mpgetflt norm")
|
|
mpnorm(a)
|
|
}
|
|
|
|
for a.Val.A[Mpnorm-1]&Mpsign == 0 {
|
|
Mpshiftfix(&a.Val, 1)
|
|
mpsetexp(a, int(a.Exp)-1) // can set 'a' to zero
|
|
s = sigfig(a)
|
|
if s == 0 {
|
|
return 0
|
|
}
|
|
}
|
|
|
|
// pick up the mantissa, a rounding bit, and a tie-breaking bit in a uvlong
|
|
s = prec + 2
|
|
|
|
v = 0
|
|
for i = Mpnorm - 1; s >= Mpscale; i-- {
|
|
v = v<<Mpscale | uint64(a.Val.A[i])
|
|
s -= Mpscale
|
|
}
|
|
|
|
if s > 0 {
|
|
v = v<<uint(s) | uint64(a.Val.A[i])>>uint(Mpscale-s)
|
|
if a.Val.A[i]&((1<<uint(Mpscale-s))-1) != 0 {
|
|
v |= 1
|
|
}
|
|
i--
|
|
}
|
|
|
|
for ; i >= 0; i-- {
|
|
if a.Val.A[i] != 0 {
|
|
v |= 1
|
|
}
|
|
}
|
|
|
|
// gradual underflow
|
|
e = Mpnorm*Mpscale + int(a.Exp) - prec
|
|
|
|
minexp = bias + 1 - prec + 1
|
|
if e < minexp {
|
|
s = minexp - e
|
|
if s > prec+1 {
|
|
s = prec + 1
|
|
}
|
|
if v&((1<<uint(s))-1) != 0 {
|
|
v |= 1 << uint(s)
|
|
}
|
|
v >>= uint(s)
|
|
e = minexp
|
|
}
|
|
|
|
// round to even
|
|
v |= (v & 4) >> 2
|
|
|
|
v += v & 1
|
|
v >>= 2
|
|
|
|
f = float64(v)
|
|
f = math.Ldexp(f, e)
|
|
|
|
if a.Val.Neg != 0 {
|
|
f = -f
|
|
}
|
|
|
|
return f
|
|
}
|
|
|
|
func mpgetflt(a *Mpflt) float64 {
|
|
return mpgetfltN(a, 53, -1023)
|
|
}
|
|
|
|
func mpgetflt32(a *Mpflt) float64 {
|
|
return mpgetfltN(a, 24, -127)
|
|
}
|
|
|
|
func Mpmovecflt(a *Mpflt, c float64) {
|
|
var i int
|
|
var f float64
|
|
var l int
|
|
|
|
if Mpdebug != 0 /*TypeKind(100016)*/ {
|
|
fmt.Printf("\nconst %g", c)
|
|
}
|
|
Mpmovecfix(&a.Val, 0)
|
|
a.Exp = 0
|
|
if c == 0 {
|
|
goto out
|
|
}
|
|
if c < 0 {
|
|
a.Val.Neg = 1
|
|
c = -c
|
|
}
|
|
|
|
f, i = math.Frexp(c)
|
|
a.Exp = int16(i)
|
|
|
|
for i = 0; i < 10; i++ {
|
|
f = f * Mpbase
|
|
l = int(math.Floor(f))
|
|
f = f - float64(l)
|
|
a.Exp -= Mpscale
|
|
a.Val.A[0] = l
|
|
if f == 0 {
|
|
break
|
|
}
|
|
Mpshiftfix(&a.Val, Mpscale)
|
|
}
|
|
|
|
out:
|
|
mpnorm(a)
|
|
if Mpdebug != 0 /*TypeKind(100016)*/ {
|
|
fmt.Printf(" = %v\n", Fconv(a, 0))
|
|
}
|
|
}
|
|
|
|
func mpnegflt(a *Mpflt) {
|
|
a.Val.Neg ^= 1
|
|
}
|
|
|
|
func mptestflt(a *Mpflt) int {
|
|
var s int
|
|
|
|
if Mpdebug != 0 /*TypeKind(100016)*/ {
|
|
fmt.Printf("\n%v?", Fconv(a, 0))
|
|
}
|
|
s = sigfig(a)
|
|
if s != 0 {
|
|
s = +1
|
|
if a.Val.Neg != 0 {
|
|
s = -1
|
|
}
|
|
}
|
|
|
|
if Mpdebug != 0 /*TypeKind(100016)*/ {
|
|
fmt.Printf(" = %d\n", s)
|
|
}
|
|
return s
|
|
}
|