mirror of
https://github.com/golang/go
synced 2024-09-06 00:19:45 +00:00
cmd/gc: check exponent overflow and underflow in mparith
A too large float constant is an error. A too small float constant is rounded to zero. Fixes #7419 Update #6902 LGTM=iant R=golang-codereviews, iant CC=golang-codereviews https://golang.org/cl/76730046
This commit is contained in:
parent
50f1e1a6b9
commit
cb50277510
|
@ -1255,6 +1255,7 @@ void mpmovecflt(Mpflt *a, double c);
|
||||||
void mpmulfltflt(Mpflt *a, Mpflt *b);
|
void mpmulfltflt(Mpflt *a, Mpflt *b);
|
||||||
void mpnegflt(Mpflt *a);
|
void mpnegflt(Mpflt *a);
|
||||||
void mpnorm(Mpflt *a);
|
void mpnorm(Mpflt *a);
|
||||||
|
void mpsetexp(Mpflt *a, int exp);
|
||||||
int mptestflt(Mpflt *a);
|
int mptestflt(Mpflt *a);
|
||||||
int sigfig(Mpflt *a);
|
int sigfig(Mpflt *a);
|
||||||
|
|
||||||
|
|
|
@ -416,7 +416,7 @@ mpatoflt(Mpflt *a, char *as)
|
||||||
if(eb) {
|
if(eb) {
|
||||||
if(dp)
|
if(dp)
|
||||||
goto bad;
|
goto bad;
|
||||||
a->exp += ex;
|
mpsetexp(a, a->exp+ex);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -427,8 +427,13 @@ mpatoflt(Mpflt *a, char *as)
|
||||||
mppow10flt(&b, ex-dp);
|
mppow10flt(&b, ex-dp);
|
||||||
mpmulfltflt(a, &b);
|
mpmulfltflt(a, &b);
|
||||||
} else {
|
} else {
|
||||||
mppow10flt(&b, dp-ex);
|
if((short)(dp-ex) != dp-ex) {
|
||||||
mpdivfltflt(a, &b);
|
mpmovecflt(a, 0.0);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
mppow10flt(&b, dp-ex);
|
||||||
|
mpdivfltflt(a, &b);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,27 @@ sigfig(Mpflt *a)
|
||||||
return i+1;
|
return i+1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* sets the exponent.
|
||||||
|
* a too large exponent is an error.
|
||||||
|
* a too small exponent rounds the number to zero.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
mpsetexp(Mpflt *a, int exp) {
|
||||||
|
if((short)exp != exp) {
|
||||||
|
if(exp > 0) {
|
||||||
|
yyerror("float constant is too large");
|
||||||
|
a->exp = 0x7fff;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
mpmovecflt(a, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
a->exp = exp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* shifts the leading non-zero
|
* shifts the leading non-zero
|
||||||
* word of the number to Mpnorm
|
* word of the number to Mpnorm
|
||||||
|
@ -60,7 +81,7 @@ mpnorm(Mpflt *a)
|
||||||
}
|
}
|
||||||
|
|
||||||
mpshiftfix(&a->val, s);
|
mpshiftfix(&a->val, s);
|
||||||
a->exp -= s;
|
mpsetexp(a, a->exp-s);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// implements float arihmetic
|
/// implements float arihmetic
|
||||||
|
@ -95,7 +116,7 @@ mpaddfltflt(Mpflt *a, Mpflt *b)
|
||||||
if(s < 0) {
|
if(s < 0) {
|
||||||
// b is larger, shift a right
|
// b is larger, shift a right
|
||||||
mpshiftfix(&a->val, s);
|
mpshiftfix(&a->val, s);
|
||||||
a->exp -= s;
|
mpsetexp(a, a->exp-s);
|
||||||
mpaddfixfix(&a->val, &b->val, 0);
|
mpaddfixfix(&a->val, &b->val, 0);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
@ -131,7 +152,7 @@ mpmulfltflt(Mpflt *a, Mpflt *b)
|
||||||
}
|
}
|
||||||
|
|
||||||
mpmulfract(&a->val, &b->val);
|
mpmulfract(&a->val, &b->val);
|
||||||
a->exp = (a->exp + b->exp) + Mpscale*Mpprec - Mpscale - 1;
|
mpsetexp(a, (a->exp + b->exp) + Mpscale*Mpprec - Mpscale - 1);
|
||||||
|
|
||||||
mpnorm(a);
|
mpnorm(a);
|
||||||
if(Mpdebug)
|
if(Mpdebug)
|
||||||
|
@ -171,7 +192,7 @@ mpdivfltflt(Mpflt *a, Mpflt *b)
|
||||||
|
|
||||||
// divide
|
// divide
|
||||||
mpdivfract(&a->val, &c.val);
|
mpdivfract(&a->val, &c.val);
|
||||||
a->exp = (a->exp-c.exp) - Mpscale*(Mpprec-1) + 1;
|
mpsetexp(a, (a->exp-c.exp) - Mpscale*(Mpprec-1) + 1);
|
||||||
|
|
||||||
mpnorm(a);
|
mpnorm(a);
|
||||||
if(Mpdebug)
|
if(Mpdebug)
|
||||||
|
@ -199,7 +220,10 @@ mpgetflt(Mpflt *a)
|
||||||
|
|
||||||
while((a->val.a[Mpnorm-1] & Mpsign) == 0) {
|
while((a->val.a[Mpnorm-1] & Mpsign) == 0) {
|
||||||
mpshiftfix(&a->val, 1);
|
mpshiftfix(&a->val, 1);
|
||||||
a->exp -= 1;
|
mpsetexp(a, a->exp-1); // can set 'a' to zero
|
||||||
|
s = sigfig(a);
|
||||||
|
if(s == 0)
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// the magic numbers (64, 63, 53, 10, -1074) are
|
// the magic numbers (64, 63, 53, 10, -1074) are
|
||||||
|
|
25
test/fixedbugs/issue7419.go
Normal file
25
test/fixedbugs/issue7419.go
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
// run
|
||||||
|
|
||||||
|
// Copyright 2014 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.
|
||||||
|
|
||||||
|
// Issue 7419: odd behavior for float constants underflowing to 0
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
var x = 1e-779137
|
||||||
|
var y = 1e-779138
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
if x != 0 {
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
if y != 0 {
|
||||||
|
os.Exit(2)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue