diff --git a/src/pkg/math/Makefile b/src/pkg/math/Makefile index 97c5af1b8a1..6657724c2ae 100644 --- a/src/pkg/math/Makefile +++ b/src/pkg/math/Makefile @@ -14,11 +14,13 @@ OFILES_386=\ atan_386.$O\ atan2_386.$O\ exp_386.$O\ + exp2_386.$O\ fabs_386.$O\ floor_386.$O\ fmod_386.$O\ hypot_386.$O\ log_386.$O\ + log1p_386.$O\ modf_386.$O\ sin_386.$O\ sqrt_386.$O\ diff --git a/src/pkg/math/all_test.go b/src/pkg/math/all_test.go index 8c47fd1cf3f..bd1d4006a81 100644 --- a/src/pkg/math/all_test.go +++ b/src/pkg/math/all_test.go @@ -208,6 +208,18 @@ var expm1 = []float64{ 1.842068661871398836913874273e-02, -8.3193870863553801814961137573e-02, } +var exp2 = []float64{ + 3.1537839463286288034313104e+01, + 2.1361549283756232296144849e+02, + 8.2537402562185562902577219e-01, + 3.1021158628740294833424229e-02, + 7.9581744110252191462569661e+02, + 7.6019905892596359262696423e+00, + 3.7506882048388096973183084e+01, + 6.6250893439173561733216375e+00, + 3.5438267900243941544605339e+00, + 2.4281533133513300984289196e-03, +} var fdim = []float64{ 4.9790119248836735e+00, 7.7388724745781045e+00, @@ -1078,6 +1090,19 @@ func TestExpm1(t *testing.T) { } } +func TestExp2(t *testing.T) { + for i := 0; i < len(vf); i++ { + if f := Exp2(vf[i]); !close(exp2[i], f) { + t.Errorf("Exp2(%g) = %g, want %g\n", vf[i], f, exp2[i]) + } + } + for i := 0; i < len(vfexpSC); i++ { + if f := Exp2(vfexpSC[i]); !alike(expSC[i], f) { + t.Errorf("Exp2(%g) = %g, want %g\n", vfexpSC[i], f, expSC[i]) + } + } +} + func TestFdim(t *testing.T) { for i := 0; i < len(vf); i++ { if f := Fdim(vf[i], 0); fdim[i] != f { @@ -1492,6 +1517,12 @@ func BenchmarkExpm1(b *testing.B) { } } +func BenchmarkExp2(b *testing.B) { + for i := 0; i < b.N; i++ { + Exp(.5) + } +} + func BenchmarkFloor(b *testing.B) { for i := 0; i < b.N; i++ { Floor(.5) diff --git a/src/pkg/math/exp.go b/src/pkg/math/exp.go index 5ea58c0fb39..18ec684dfa7 100644 --- a/src/pkg/math/exp.go +++ b/src/pkg/math/exp.go @@ -139,3 +139,8 @@ func Exp(x float64) float64 { // TODO(rsc): make sure Ldexp can handle boundary k return Ldexp(y, k) } + +// Exp2 returns 2^x, the base-2 exponential of x. +// +// Special cases are the same as Exp. +func Exp2(x float64) float64 { return Exp(x * Ln2) } diff --git a/src/pkg/math/exp2_386.s b/src/pkg/math/exp2_386.s new file mode 100644 index 00000000000..ed82a4dd322 --- /dev/null +++ b/src/pkg/math/exp2_386.s @@ -0,0 +1,38 @@ +// Copyright 2010 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. + +// func Exp2(x float64) float64 +TEXT ·Exp2(SB),7,$0 +// test bits for not-finite + MOVL x+4(FP), AX + ANDL $0x7ff00000, AX + CMPL AX, $0x7ff00000 + JEQ not_finite + FMOVD x+0(FP), F0 // F0=x + FMOVD F0, F1 // F0=x, F1=x + FRNDINT // F0=int(x), F1=x + FSUBD F0, F1 // F0=int(x), F1=x-int(x) + FXCHD F0, F1 // F0=x-int(x), F1=int(x) + F2XM1 // F0=2**(x-int(x))-1, F1=int(x) + FLD1 // F0=1, F1=2**(x-int(x))-1, F2=int(x) + FADDDP F0, F1 // F0=2**(x-int(x)), F1=int(x) + FSCALE // F0=2**x, F1=int(x) + FMOVDP F0, F1 // F0=2**x + FMOVDP F0, r+8(FP) + RET +not_finite: +// test bits for -Inf + MOVL x+4(FP), BX + MOVL x+0(FP), CX + CMPL BX, $0xfff00000 + JNE not_neginf + CMPL CX, $0 + JNE not_neginf + MOVL $0, r+8(FP) + MOVL $0, r+12(FP) + RET +not_neginf: + MOVL CX, r+8(FP) + MOVL BX, r+12(FP) + RET diff --git a/src/pkg/math/exp2_decl.go b/src/pkg/math/exp2_decl.go new file mode 100644 index 00000000000..cff7411742d --- /dev/null +++ b/src/pkg/math/exp2_decl.go @@ -0,0 +1,7 @@ +// Copyright 2010 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 math + +func Exp2(x float64) float64 diff --git a/src/pkg/math/log1p_386.s b/src/pkg/math/log1p_386.s new file mode 100644 index 00000000000..30df88e1fba --- /dev/null +++ b/src/pkg/math/log1p_386.s @@ -0,0 +1,25 @@ +// Copyright 2010 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. + +// func Log1p(x float64) float64 +TEXT ·Log1p(SB),7,$0 + FMOVD $(2.928932188134524e-01), F0 + FMOVD x+0(FP), F0 // F0=x, F1=1-sqrt(2)/2 = 0.29289321881345247559915564 + FABS // F0=|x|, F1=1-sqrt(2)/2 + FUCOMPP F0, F1 // compare F0 to F1 + FSTSW AX + FLDLN2 // F0=log(2) + ANDW $0x0100, AX + JEQ use_fyl2x // jump if F0 >= F1 + FMOVD x+0(FP), F0 // F0=x, F1=log(2) + FYL2XP1 // F0=log(1+x)=log2(1+x)*log(2) + FMOVDP F0, r+8(FP) + RET +use_fyl2x: + FLD1 // F0=1, F2=log(2) + FADDD x+0(FP), F0 // F0=1+x, F1=log(2) + FYL2X // F0=log(1+x)=log2(1+x)*log(2) + FMOVDP F0, r+8(FP) + RET + diff --git a/src/pkg/math/log1p_decl.go b/src/pkg/math/log1p_decl.go new file mode 100644 index 00000000000..84b6030fbca --- /dev/null +++ b/src/pkg/math/log1p_decl.go @@ -0,0 +1,7 @@ +// Copyright 2010 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 math + +func Log1p(x float64) float64