diff options
author | Ondřej Surý <ondrej@sury.org> | 2011-01-17 12:40:45 +0100 |
---|---|---|
committer | Ondřej Surý <ondrej@sury.org> | 2011-01-17 12:40:45 +0100 |
commit | 3e45412327a2654a77944249962b3652e6142299 (patch) | |
tree | bc3bf69452afa055423cbe0c5cfa8ca357df6ccf /src/pkg/math | |
parent | c533680039762cacbc37db8dc7eed074c3e497be (diff) | |
download | golang-upstream/2011.01.12.tar.gz |
Imported Upstream version 2011.01.12upstream/2011.01.12
Diffstat (limited to 'src/pkg/math')
-rw-r--r-- | src/pkg/math/Makefile | 10 | ||||
-rw-r--r-- | src/pkg/math/all_test.go | 700 | ||||
-rw-r--r-- | src/pkg/math/bits.go | 2 | ||||
-rw-r--r-- | src/pkg/math/const.go | 10 | ||||
-rw-r--r-- | src/pkg/math/exp.go | 129 | ||||
-rw-r--r-- | src/pkg/math/exp2.go | 2 | ||||
-rw-r--r-- | src/pkg/math/exp_amd64.s | 92 | ||||
-rw-r--r-- | src/pkg/math/exp_port.go | 192 | ||||
-rw-r--r-- | src/pkg/math/exp_test.go | 10 | ||||
-rw-r--r-- | src/pkg/math/frexp.go | 4 | ||||
-rw-r--r-- | src/pkg/math/hypot_amd64.s | 50 | ||||
-rw-r--r-- | src/pkg/math/log.go | 8 | ||||
-rw-r--r-- | src/pkg/math/log10.go | 13 | ||||
-rw-r--r-- | src/pkg/math/log10_386.s | 19 | ||||
-rw-r--r-- | src/pkg/math/log10_decl.go | 8 | ||||
-rw-r--r-- | src/pkg/math/log_386.s | 16 | ||||
-rw-r--r-- | src/pkg/math/log_amd64.s | 109 | ||||
-rw-r--r-- | src/pkg/math/log_decl.go | 2 | ||||
-rw-r--r-- | src/pkg/math/logb.go | 4 | ||||
-rw-r--r-- | src/pkg/math/modf.go | 6 | ||||
-rw-r--r-- | src/pkg/math/sincos_amd64.s | 143 | ||||
-rw-r--r-- | src/pkg/math/sqrt_port.go | 4 | ||||
-rw-r--r-- | src/pkg/math/tan.go | 2 |
23 files changed, 995 insertions, 540 deletions
diff --git a/src/pkg/math/Makefile b/src/pkg/math/Makefile index a2d11e43d..71347b7fa 100644 --- a/src/pkg/math/Makefile +++ b/src/pkg/math/Makefile @@ -2,7 +2,7 @@ # Use of this source code is governed by a BSD-style # license that can be found in the LICENSE file. -include ../../Make.$(GOARCH) +include ../../Make.inc TARG=math @@ -10,6 +10,9 @@ OFILES_amd64=\ exp_amd64.$O\ fabs_amd64.$O\ fdim_amd64.$O\ + hypot_amd64.$O\ + log_amd64.$O\ + sincos_amd64.$O\ sqrt_amd64.$O\ OFILES_386=\ @@ -26,6 +29,7 @@ OFILES_386=\ hypot_386.$O\ ldexp_386.$O\ log_386.$O\ + log10_386.$O\ log1p_386.$O\ modf_386.$O\ remainder_386.$O\ @@ -50,6 +54,7 @@ ALLGOFILES=\ copysign.go\ erf.go\ exp.go\ + exp_port.go\ exp2.go\ expm1.go\ fabs.go\ @@ -63,11 +68,12 @@ ALLGOFILES=\ j0.go\ j1.go\ jn.go\ - logb.go\ lgamma.go\ ldexp.go\ log.go\ + log10.go\ log1p.go\ + logb.go\ modf.go\ nextafter.go\ pow.go\ diff --git a/src/pkg/math/all_test.go b/src/pkg/math/all_test.go index 18a3f1b31..6033d37e3 100644 --- a/src/pkg/math/all_test.go +++ b/src/pkg/math/all_test.go @@ -7,6 +7,7 @@ package math_test import ( "fmt" . "math" + "runtime" "testing" ) @@ -286,16 +287,16 @@ type fi struct { } var frexp = []fi{ - fi{6.2237649061045918750e-01, 3}, - fi{9.6735905932226306250e-01, 3}, - fi{-5.5376011438400318000e-01, -1}, - fi{-6.2632545228388436250e-01, 3}, - fi{6.02268356699901081250e-01, 4}, - fi{7.3159430981099115000e-01, 2}, - fi{6.5363542893241332500e-01, 3}, - fi{6.8198497760900255000e-01, 2}, - fi{9.1265404584042750000e-01, 1}, - fi{-5.4287029803597508250e-01, 4}, + {6.2237649061045918750e-01, 3}, + {9.6735905932226306250e-01, 3}, + {-5.5376011438400318000e-01, -1}, + {-6.2632545228388436250e-01, 3}, + {6.02268356699901081250e-01, 4}, + {7.3159430981099115000e-01, 2}, + {6.5363542893241332500e-01, 3}, + {6.8198497760900255000e-01, 2}, + {9.1265404584042750000e-01, 1}, + {-5.4287029803597508250e-01, 4}, } var gamma = []float64{ 2.3254348370739963835386613898e+01, @@ -358,16 +359,16 @@ var jM3 = []float64{ -2.3762660886100206491674503e-01, } var lgamma = []fi{ - fi{3.146492141244545774319734e+00, 1}, - fi{8.003414490659126375852113e+00, 1}, - fi{1.517575735509779707488106e+00, -1}, - fi{-2.588480028182145853558748e-01, 1}, - fi{1.1989897050205555002007985e+01, 1}, - fi{6.262899811091257519386906e-01, 1}, - fi{3.5287924899091566764846037e+00, 1}, - fi{4.5725644770161182299423372e-01, 1}, - fi{-6.363667087767961257654854e-02, 1}, - fi{-1.077385130910300066425564e+01, -1}, + {3.146492141244545774319734e+00, 1}, + {8.003414490659126375852113e+00, 1}, + {1.517575735509779707488106e+00, -1}, + {-2.588480028182145853558748e-01, 1}, + {1.1989897050205555002007985e+01, 1}, + {6.262899811091257519386906e-01, 1}, + {3.5287924899091566764846037e+00, 1}, + {4.5725644770161182299423372e-01, 1}, + {-6.363667087767961257654854e-02, 1}, + {-1.077385130910300066425564e+01, -1}, } var log = []float64{ 1.605231462693062999102599e+00, @@ -382,16 +383,16 @@ var log = []float64{ 2.161703872847352815363655e+00, } var logb = []float64{ - 3.0000000000000000e+00, - 3.0000000000000000e+00, - -1.0000000000000000e+00, - 3.0000000000000000e+00, - 4.0000000000000000e+00, + 2.0000000000000000e+00, + 2.0000000000000000e+00, + -2.0000000000000000e+00, 2.0000000000000000e+00, 3.0000000000000000e+00, + 1.0000000000000000e+00, 2.0000000000000000e+00, 1.0000000000000000e+00, - 4.0000000000000000e+00, + 0.0000000000000000e+00, + 3.0000000000000000e+00, } var log10 = []float64{ 6.9714316642508290997617083e-01, @@ -430,16 +431,16 @@ var log2 = []float64{ 3.118679457227342224364709e+00, } var modf = [][2]float64{ - [2]float64{4.0000000000000000e+00, 9.7901192488367350108546816e-01}, - [2]float64{7.0000000000000000e+00, 7.3887247457810456552351752e-01}, - [2]float64{0.0000000000000000e+00, -2.7688005719200159404635997e-01}, - [2]float64{-5.0000000000000000e+00, -1.060361827107492160848778e-02}, - [2]float64{9.0000000000000000e+00, 6.3629370719841737980004837e-01}, - [2]float64{2.0000000000000000e+00, 9.2637723924396464525443662e-01}, - [2]float64{5.0000000000000000e+00, 2.2908343145930665230025625e-01}, - [2]float64{2.0000000000000000e+00, 7.2793991043601025126008608e-01}, - [2]float64{1.0000000000000000e+00, 8.2530809168085506044576505e-01}, - [2]float64{-8.0000000000000000e+00, -6.8592476857560136238589621e-01}, + {4.0000000000000000e+00, 9.7901192488367350108546816e-01}, + {7.0000000000000000e+00, 7.3887247457810456552351752e-01}, + {0.0000000000000000e+00, -2.7688005719200159404635997e-01}, + {-5.0000000000000000e+00, -1.060361827107492160848778e-02}, + {9.0000000000000000e+00, 6.3629370719841737980004837e-01}, + {2.0000000000000000e+00, 9.2637723924396464525443662e-01}, + {5.0000000000000000e+00, 2.2908343145930665230025625e-01}, + {2.0000000000000000e+00, 7.2793991043601025126008608e-01}, + {1.0000000000000000e+00, 8.2530809168085506044576505e-01}, + {-8.0000000000000000e+00, -6.8592476857560136238589621e-01}, } var nextafter = []float64{ 4.97901192488367438926388786e+00, @@ -707,41 +708,41 @@ var atanhSC = []float64{ NaN(), } var vfatan2SC = [][2]float64{ - [2]float64{Inf(-1), Inf(-1)}, - [2]float64{Inf(-1), -Pi}, - [2]float64{Inf(-1), 0}, - [2]float64{Inf(-1), +Pi}, - [2]float64{Inf(-1), Inf(1)}, - [2]float64{Inf(-1), NaN()}, - [2]float64{-Pi, Inf(-1)}, - [2]float64{-Pi, 0}, - [2]float64{-Pi, Inf(1)}, - [2]float64{-Pi, NaN()}, - [2]float64{Copysign(0, -1), Inf(-1)}, - [2]float64{Copysign(0, -1), -Pi}, - [2]float64{Copysign(0, -1), Copysign(0, -1)}, - [2]float64{Copysign(0, -1), 0}, - [2]float64{Copysign(0, -1), +Pi}, - [2]float64{Copysign(0, -1), Inf(1)}, - [2]float64{Copysign(0, -1), NaN()}, - [2]float64{0, Inf(-1)}, - [2]float64{0, -Pi}, - [2]float64{0, Copysign(0, -1)}, - [2]float64{0, 0}, - [2]float64{0, +Pi}, - [2]float64{0, Inf(1)}, - [2]float64{0, NaN()}, - [2]float64{+Pi, Inf(-1)}, - [2]float64{+Pi, 0}, - [2]float64{+Pi, Inf(1)}, - [2]float64{+Pi, NaN()}, - [2]float64{Inf(1), Inf(-1)}, - [2]float64{Inf(1), -Pi}, - [2]float64{Inf(1), 0}, - [2]float64{Inf(1), +Pi}, - [2]float64{Inf(1), Inf(1)}, - [2]float64{Inf(1), NaN()}, - [2]float64{NaN(), NaN()}, + {Inf(-1), Inf(-1)}, + {Inf(-1), -Pi}, + {Inf(-1), 0}, + {Inf(-1), +Pi}, + {Inf(-1), Inf(1)}, + {Inf(-1), NaN()}, + {-Pi, Inf(-1)}, + {-Pi, 0}, + {-Pi, Inf(1)}, + {-Pi, NaN()}, + {Copysign(0, -1), Inf(-1)}, + {Copysign(0, -1), -Pi}, + {Copysign(0, -1), Copysign(0, -1)}, + {Copysign(0, -1), 0}, + {Copysign(0, -1), +Pi}, + {Copysign(0, -1), Inf(1)}, + {Copysign(0, -1), NaN()}, + {0, Inf(-1)}, + {0, -Pi}, + {0, Copysign(0, -1)}, + {0, 0}, + {0, +Pi}, + {0, Inf(1)}, + {0, NaN()}, + {+Pi, Inf(-1)}, + {+Pi, 0}, + {+Pi, Inf(1)}, + {+Pi, NaN()}, + {Inf(1), Inf(-1)}, + {Inf(1), -Pi}, + {Inf(1), 0}, + {Inf(1), +Pi}, + {Inf(1), Inf(1)}, + {Inf(1), NaN()}, + {NaN(), NaN()}, } var atan2SC = []float64{ -3 * Pi / 4, // atan2(-Inf, -Inf) @@ -876,11 +877,15 @@ var erfcSC = []float64{ var vfexpSC = []float64{ Inf(-1), + -2000, + 2000, Inf(1), NaN(), } var expSC = []float64{ 0, + 0, + Inf(1), Inf(1), NaN(), } @@ -916,40 +921,40 @@ var fabsSC = []float64{ } var vffmodSC = [][2]float64{ - [2]float64{Inf(-1), Inf(-1)}, - [2]float64{Inf(-1), -Pi}, - [2]float64{Inf(-1), 0}, - [2]float64{Inf(-1), Pi}, - [2]float64{Inf(-1), Inf(1)}, - [2]float64{Inf(-1), NaN()}, - [2]float64{-Pi, Inf(-1)}, - [2]float64{-Pi, 0}, - [2]float64{-Pi, Inf(1)}, - [2]float64{-Pi, NaN()}, - [2]float64{Copysign(0, -1), Inf(-1)}, - [2]float64{Copysign(0, -1), 0}, - [2]float64{Copysign(0, -1), Inf(1)}, - [2]float64{Copysign(0, -1), NaN()}, - [2]float64{0, Inf(-1)}, - [2]float64{0, 0}, - [2]float64{0, Inf(1)}, - [2]float64{0, NaN()}, - [2]float64{Pi, Inf(-1)}, - [2]float64{Pi, 0}, - [2]float64{Pi, Inf(1)}, - [2]float64{Pi, NaN()}, - [2]float64{Inf(1), Inf(-1)}, - [2]float64{Inf(1), -Pi}, - [2]float64{Inf(1), 0}, - [2]float64{Inf(1), Pi}, - [2]float64{Inf(1), Inf(1)}, - [2]float64{Inf(1), NaN()}, - [2]float64{NaN(), Inf(-1)}, - [2]float64{NaN(), -Pi}, - [2]float64{NaN(), 0}, - [2]float64{NaN(), Pi}, - [2]float64{NaN(), Inf(1)}, - [2]float64{NaN(), NaN()}, + {Inf(-1), Inf(-1)}, + {Inf(-1), -Pi}, + {Inf(-1), 0}, + {Inf(-1), Pi}, + {Inf(-1), Inf(1)}, + {Inf(-1), NaN()}, + {-Pi, Inf(-1)}, + {-Pi, 0}, + {-Pi, Inf(1)}, + {-Pi, NaN()}, + {Copysign(0, -1), Inf(-1)}, + {Copysign(0, -1), 0}, + {Copysign(0, -1), Inf(1)}, + {Copysign(0, -1), NaN()}, + {0, Inf(-1)}, + {0, 0}, + {0, Inf(1)}, + {0, NaN()}, + {Pi, Inf(-1)}, + {Pi, 0}, + {Pi, Inf(1)}, + {Pi, NaN()}, + {Inf(1), Inf(-1)}, + {Inf(1), -Pi}, + {Inf(1), 0}, + {Inf(1), Pi}, + {Inf(1), Inf(1)}, + {Inf(1), NaN()}, + {NaN(), Inf(-1)}, + {NaN(), -Pi}, + {NaN(), 0}, + {NaN(), Pi}, + {NaN(), Inf(1)}, + {NaN(), NaN()}, } var fmodSC = []float64{ NaN(), // fmod(-Inf, -Inf) @@ -996,11 +1001,11 @@ var vffrexpSC = []float64{ NaN(), } var frexpSC = []fi{ - fi{Inf(-1), 0}, - fi{Copysign(0, -1), 0}, - fi{0, 0}, - fi{Inf(1), 0}, - fi{NaN(), 0}, + {Inf(-1), 0}, + {Copysign(0, -1), 0}, + {0, 0}, + {Inf(1), 0}, + {NaN(), 0}, } var vfgammaSC = []float64{ @@ -1021,25 +1026,25 @@ var gammaSC = []float64{ } var vfhypotSC = [][2]float64{ - [2]float64{Inf(-1), Inf(-1)}, - [2]float64{Inf(-1), 0}, - [2]float64{Inf(-1), Inf(1)}, - [2]float64{Inf(-1), NaN()}, - [2]float64{Copysign(0, -1), Copysign(0, -1)}, - [2]float64{Copysign(0, -1), 0}, - [2]float64{0, Copysign(0, -1)}, - [2]float64{0, 0}, // +0, +0 - [2]float64{0, Inf(-1)}, - [2]float64{0, Inf(1)}, - [2]float64{0, NaN()}, - [2]float64{Inf(1), Inf(-1)}, - [2]float64{Inf(1), 0}, - [2]float64{Inf(1), Inf(1)}, - [2]float64{Inf(1), NaN()}, - [2]float64{NaN(), Inf(-1)}, - [2]float64{NaN(), 0}, - [2]float64{NaN(), Inf(1)}, - [2]float64{NaN(), NaN()}, + {Inf(-1), Inf(-1)}, + {Inf(-1), 0}, + {Inf(-1), Inf(1)}, + {Inf(-1), NaN()}, + {Copysign(0, -1), Copysign(0, -1)}, + {Copysign(0, -1), 0}, + {0, Copysign(0, -1)}, + {0, 0}, // +0, +0 + {0, Inf(-1)}, + {0, Inf(1)}, + {0, NaN()}, + {Inf(1), Inf(-1)}, + {Inf(1), 0}, + {Inf(1), Inf(1)}, + {Inf(1), NaN()}, + {NaN(), Inf(-1)}, + {NaN(), 0}, + {NaN(), Inf(1)}, + {NaN(), NaN()}, } var hypotSC = []float64{ Inf(1), @@ -1117,13 +1122,13 @@ var vflgammaSC = []float64{ NaN(), } var lgammaSC = []fi{ - fi{Inf(-1), 1}, - fi{Inf(1), 1}, - fi{Inf(1), 1}, - fi{0, 1}, - fi{0, 1}, - fi{Inf(1), 1}, - fi{NaN(), 1}, + {Inf(-1), 1}, + {Inf(1), 1}, + {Inf(1), 1}, + {0, 1}, + {0, 1}, + {Inf(1), 1}, + {NaN(), 1}, } var vflogSC = []float64{ @@ -1183,15 +1188,15 @@ var vfmodfSC = []float64{ NaN(), } var modfSC = [][2]float64{ - [2]float64{Inf(-1), NaN()}, // [2]float64{Copysign(0, -1), Inf(-1)}, - [2]float64{Inf(1), NaN()}, // [2]float64{0, Inf(1)}, - [2]float64{NaN(), NaN()}, + {Inf(-1), NaN()}, // [2]float64{Copysign(0, -1), Inf(-1)}, + {Inf(1), NaN()}, // [2]float64{0, Inf(1)}, + {NaN(), NaN()}, } var vfnextafterSC = [][2]float64{ - [2]float64{0, NaN()}, - [2]float64{NaN(), 0}, - [2]float64{NaN(), NaN()}, + {0, NaN()}, + {NaN(), 0}, + {NaN(), NaN()}, } var nextafterSC = []float64{ NaN(), @@ -1200,70 +1205,70 @@ var nextafterSC = []float64{ } var vfpowSC = [][2]float64{ - [2]float64{Inf(-1), -Pi}, - [2]float64{Inf(-1), -3}, - [2]float64{Inf(-1), Copysign(0, -1)}, - [2]float64{Inf(-1), 0}, - [2]float64{Inf(-1), 1}, - [2]float64{Inf(-1), 3}, - [2]float64{Inf(-1), Pi}, - [2]float64{Inf(-1), NaN()}, - - [2]float64{-Pi, Inf(-1)}, - [2]float64{-Pi, -Pi}, - [2]float64{-Pi, Copysign(0, -1)}, - [2]float64{-Pi, 0}, - [2]float64{-Pi, 1}, - [2]float64{-Pi, Pi}, - [2]float64{-Pi, Inf(1)}, - [2]float64{-Pi, NaN()}, - - [2]float64{-1, Inf(-1)}, - [2]float64{-1, Inf(1)}, - [2]float64{-1, NaN()}, - [2]float64{-1 / 2, Inf(-1)}, - [2]float64{-1 / 2, Inf(1)}, - [2]float64{Copysign(0, -1), Inf(-1)}, - [2]float64{Copysign(0, -1), -Pi}, - [2]float64{Copysign(0, -1), -3}, - [2]float64{Copysign(0, -1), 3}, - [2]float64{Copysign(0, -1), Pi}, - [2]float64{Copysign(0, -1), Inf(1)}, - - [2]float64{0, Inf(-1)}, - [2]float64{0, -Pi}, - [2]float64{0, -3}, - [2]float64{0, Copysign(0, -1)}, - [2]float64{0, 0}, - [2]float64{0, 3}, - [2]float64{0, Pi}, - [2]float64{0, Inf(1)}, - [2]float64{0, NaN()}, - - [2]float64{1 / 2, Inf(-1)}, - [2]float64{1 / 2, Inf(1)}, - [2]float64{1, Inf(-1)}, - [2]float64{1, Inf(1)}, - [2]float64{1, NaN()}, - - [2]float64{Pi, Inf(-1)}, - [2]float64{Pi, Copysign(0, -1)}, - [2]float64{Pi, 0}, - [2]float64{Pi, 1}, - [2]float64{Pi, Inf(1)}, - [2]float64{Pi, NaN()}, - [2]float64{Inf(1), -Pi}, - [2]float64{Inf(1), Copysign(0, -1)}, - [2]float64{Inf(1), 0}, - [2]float64{Inf(1), 1}, - [2]float64{Inf(1), Pi}, - [2]float64{Inf(1), NaN()}, - [2]float64{NaN(), -Pi}, - [2]float64{NaN(), Copysign(0, -1)}, - [2]float64{NaN(), 0}, - [2]float64{NaN(), 1}, - [2]float64{NaN(), Pi}, - [2]float64{NaN(), NaN()}, + {Inf(-1), -Pi}, + {Inf(-1), -3}, + {Inf(-1), Copysign(0, -1)}, + {Inf(-1), 0}, + {Inf(-1), 1}, + {Inf(-1), 3}, + {Inf(-1), Pi}, + {Inf(-1), NaN()}, + + {-Pi, Inf(-1)}, + {-Pi, -Pi}, + {-Pi, Copysign(0, -1)}, + {-Pi, 0}, + {-Pi, 1}, + {-Pi, Pi}, + {-Pi, Inf(1)}, + {-Pi, NaN()}, + + {-1, Inf(-1)}, + {-1, Inf(1)}, + {-1, NaN()}, + {-1 / 2, Inf(-1)}, + {-1 / 2, Inf(1)}, + {Copysign(0, -1), Inf(-1)}, + {Copysign(0, -1), -Pi}, + {Copysign(0, -1), -3}, + {Copysign(0, -1), 3}, + {Copysign(0, -1), Pi}, + {Copysign(0, -1), Inf(1)}, + + {0, Inf(-1)}, + {0, -Pi}, + {0, -3}, + {0, Copysign(0, -1)}, + {0, 0}, + {0, 3}, + {0, Pi}, + {0, Inf(1)}, + {0, NaN()}, + + {1 / 2, Inf(-1)}, + {1 / 2, Inf(1)}, + {1, Inf(-1)}, + {1, Inf(1)}, + {1, NaN()}, + + {Pi, Inf(-1)}, + {Pi, Copysign(0, -1)}, + {Pi, 0}, + {Pi, 1}, + {Pi, Inf(1)}, + {Pi, NaN()}, + {Inf(1), -Pi}, + {Inf(1), Copysign(0, -1)}, + {Inf(1), 0}, + {Inf(1), 1}, + {Inf(1), Pi}, + {Inf(1), NaN()}, + {NaN(), -Pi}, + {NaN(), Copysign(0, -1)}, + {NaN(), 0}, + {NaN(), 1}, + {NaN(), Pi}, + {NaN(), NaN()}, } var powSC = []float64{ 0, // pow(-Inf, -Pi) @@ -1467,12 +1472,12 @@ func TestAcos(t *testing.T) { for i := 0; i < len(vf); i++ { a := vf[i] / 10 if f := Acos(a); !close(acos[i], f) { - t.Errorf("Acos(%g) = %g, want %g\n", a, f, acos[i]) + t.Errorf("Acos(%g) = %g, want %g", a, f, acos[i]) } } for i := 0; i < len(vfacosSC); i++ { if f := Acos(vfacosSC[i]); !alike(acosSC[i], f) { - t.Errorf("Acos(%g) = %g, want %g\n", vfacosSC[i], f, acosSC[i]) + t.Errorf("Acos(%g) = %g, want %g", vfacosSC[i], f, acosSC[i]) } } } @@ -1481,12 +1486,12 @@ func TestAcosh(t *testing.T) { for i := 0; i < len(vf); i++ { a := 1 + Fabs(vf[i]) if f := Acosh(a); !veryclose(acosh[i], f) { - t.Errorf("Acosh(%g) = %g, want %g\n", a, f, acosh[i]) + t.Errorf("Acosh(%g) = %g, want %g", a, f, acosh[i]) } } for i := 0; i < len(vfacoshSC); i++ { if f := Acosh(vfacoshSC[i]); !alike(acoshSC[i], f) { - t.Errorf("Acosh(%g) = %g, want %g\n", vfacoshSC[i], f, acoshSC[i]) + t.Errorf("Acosh(%g) = %g, want %g", vfacoshSC[i], f, acoshSC[i]) } } } @@ -1495,12 +1500,12 @@ func TestAsin(t *testing.T) { for i := 0; i < len(vf); i++ { a := vf[i] / 10 if f := Asin(a); !veryclose(asin[i], f) { - t.Errorf("Asin(%g) = %g, want %g\n", a, f, asin[i]) + t.Errorf("Asin(%g) = %g, want %g", a, f, asin[i]) } } for i := 0; i < len(vfasinSC); i++ { if f := Asin(vfasinSC[i]); !alike(asinSC[i], f) { - t.Errorf("Asin(%g) = %g, want %g\n", vfasinSC[i], f, asinSC[i]) + t.Errorf("Asin(%g) = %g, want %g", vfasinSC[i], f, asinSC[i]) } } } @@ -1508,12 +1513,12 @@ func TestAsin(t *testing.T) { func TestAsinh(t *testing.T) { for i := 0; i < len(vf); i++ { if f := Asinh(vf[i]); !veryclose(asinh[i], f) { - t.Errorf("Asinh(%g) = %g, want %g\n", vf[i], f, asinh[i]) + t.Errorf("Asinh(%g) = %g, want %g", vf[i], f, asinh[i]) } } for i := 0; i < len(vfasinhSC); i++ { if f := Asinh(vfasinhSC[i]); !alike(asinhSC[i], f) { - t.Errorf("Asinh(%g) = %g, want %g\n", vfasinhSC[i], f, asinhSC[i]) + t.Errorf("Asinh(%g) = %g, want %g", vfasinhSC[i], f, asinhSC[i]) } } } @@ -1521,12 +1526,12 @@ func TestAsinh(t *testing.T) { func TestAtan(t *testing.T) { for i := 0; i < len(vf); i++ { if f := Atan(vf[i]); !veryclose(atan[i], f) { - t.Errorf("Atan(%g) = %g, want %g\n", vf[i], f, atan[i]) + t.Errorf("Atan(%g) = %g, want %g", vf[i], f, atan[i]) } } for i := 0; i < len(vfatanSC); i++ { if f := Atan(vfatanSC[i]); !alike(atanSC[i], f) { - t.Errorf("Atan(%g) = %g, want %g\n", vfatanSC[i], f, atanSC[i]) + t.Errorf("Atan(%g) = %g, want %g", vfatanSC[i], f, atanSC[i]) } } } @@ -1535,12 +1540,12 @@ func TestAtanh(t *testing.T) { for i := 0; i < len(vf); i++ { a := vf[i] / 10 if f := Atanh(a); !veryclose(atanh[i], f) { - t.Errorf("Atanh(%g) = %g, want %g\n", a, f, atanh[i]) + t.Errorf("Atanh(%g) = %g, want %g", a, f, atanh[i]) } } for i := 0; i < len(vfatanhSC); i++ { if f := Atanh(vfatanhSC[i]); !alike(atanhSC[i], f) { - t.Errorf("Atanh(%g) = %g, want %g\n", vfatanhSC[i], f, atanhSC[i]) + t.Errorf("Atanh(%g) = %g, want %g", vfatanhSC[i], f, atanhSC[i]) } } } @@ -1548,12 +1553,12 @@ func TestAtanh(t *testing.T) { func TestAtan2(t *testing.T) { for i := 0; i < len(vf); i++ { if f := Atan2(10, vf[i]); !veryclose(atan2[i], f) { - t.Errorf("Atan2(10, %g) = %g, want %g\n", vf[i], f, atan2[i]) + t.Errorf("Atan2(10, %g) = %g, want %g", vf[i], f, atan2[i]) } } for i := 0; i < len(vfatan2SC); i++ { if f := Atan2(vfatan2SC[i][0], vfatan2SC[i][1]); !alike(atan2SC[i], f) { - t.Errorf("Atan2(%g, %g) = %g, want %g\n", vfatan2SC[i][0], vfatan2SC[i][1], f, atan2SC[i]) + t.Errorf("Atan2(%g, %g) = %g, want %g", vfatan2SC[i][0], vfatan2SC[i][1], f, atan2SC[i]) } } } @@ -1561,12 +1566,12 @@ func TestAtan2(t *testing.T) { func TestCbrt(t *testing.T) { for i := 0; i < len(vf); i++ { if f := Cbrt(vf[i]); !veryclose(cbrt[i], f) { - t.Errorf("Cbrt(%g) = %g, want %g\n", vf[i], f, cbrt[i]) + t.Errorf("Cbrt(%g) = %g, want %g", vf[i], f, cbrt[i]) } } for i := 0; i < len(vfcbrtSC); i++ { if f := Cbrt(vfcbrtSC[i]); !alike(cbrtSC[i], f) { - t.Errorf("Cbrt(%g) = %g, want %g\n", vfcbrtSC[i], f, cbrtSC[i]) + t.Errorf("Cbrt(%g) = %g, want %g", vfcbrtSC[i], f, cbrtSC[i]) } } } @@ -1574,12 +1579,12 @@ func TestCbrt(t *testing.T) { func TestCeil(t *testing.T) { for i := 0; i < len(vf); i++ { if f := Ceil(vf[i]); ceil[i] != f { - t.Errorf("Ceil(%g) = %g, want %g\n", vf[i], f, ceil[i]) + t.Errorf("Ceil(%g) = %g, want %g", vf[i], f, ceil[i]) } } for i := 0; i < len(vfceilSC); i++ { if f := Ceil(vfceilSC[i]); !alike(ceilSC[i], f) { - t.Errorf("Ceil(%g) = %g, want %g\n", vfceilSC[i], f, ceilSC[i]) + t.Errorf("Ceil(%g) = %g, want %g", vfceilSC[i], f, ceilSC[i]) } } } @@ -1587,12 +1592,17 @@ func TestCeil(t *testing.T) { func TestCopysign(t *testing.T) { for i := 0; i < len(vf); i++ { if f := Copysign(vf[i], -1); copysign[i] != f { - t.Errorf("Copysign(%g, -1) = %g, want %g\n", vf[i], f, copysign[i]) + t.Errorf("Copysign(%g, -1) = %g, want %g", vf[i], f, copysign[i]) + } + } + for i := 0; i < len(vf); i++ { + if f := Copysign(vf[i], 1); -copysign[i] != f { + t.Errorf("Copysign(%g, 1) = %g, want %g", vf[i], f, -copysign[i]) } } for i := 0; i < len(vfcopysignSC); i++ { if f := Copysign(vfcopysignSC[i], -1); !alike(copysignSC[i], f) { - t.Errorf("Copysign(%g, -1) = %g, want %g\n", vfcopysignSC[i], f, copysignSC[i]) + t.Errorf("Copysign(%g, -1) = %g, want %g", vfcopysignSC[i], f, copysignSC[i]) } } } @@ -1600,12 +1610,12 @@ func TestCopysign(t *testing.T) { func TestCos(t *testing.T) { for i := 0; i < len(vf); i++ { if f := Cos(vf[i]); !close(cos[i], f) { - t.Errorf("Cos(%g) = %g, want %g\n", vf[i], f, cos[i]) + t.Errorf("Cos(%g) = %g, want %g", vf[i], f, cos[i]) } } for i := 0; i < len(vfcosSC); i++ { if f := Cos(vfcosSC[i]); !alike(cosSC[i], f) { - t.Errorf("Cos(%g) = %g, want %g\n", vfcosSC[i], f, cosSC[i]) + t.Errorf("Cos(%g) = %g, want %g", vfcosSC[i], f, cosSC[i]) } } } @@ -1613,12 +1623,12 @@ func TestCos(t *testing.T) { func TestCosh(t *testing.T) { for i := 0; i < len(vf); i++ { if f := Cosh(vf[i]); !close(cosh[i], f) { - t.Errorf("Cosh(%g) = %g, want %g\n", vf[i], f, cosh[i]) + t.Errorf("Cosh(%g) = %g, want %g", vf[i], f, cosh[i]) } } for i := 0; i < len(vfcoshSC); i++ { if f := Cosh(vfcoshSC[i]); !alike(coshSC[i], f) { - t.Errorf("Cosh(%g) = %g, want %g\n", vfcoshSC[i], f, coshSC[i]) + t.Errorf("Cosh(%g) = %g, want %g", vfcoshSC[i], f, coshSC[i]) } } } @@ -1627,12 +1637,12 @@ func TestErf(t *testing.T) { for i := 0; i < len(vf); i++ { a := vf[i] / 10 if f := Erf(a); !veryclose(erf[i], f) { - t.Errorf("Erf(%g) = %g, want %g\n", a, f, erf[i]) + t.Errorf("Erf(%g) = %g, want %g", a, f, erf[i]) } } for i := 0; i < len(vferfSC); i++ { if f := Erf(vferfSC[i]); !alike(erfSC[i], f) { - t.Errorf("Erf(%g) = %g, want %g\n", vferfSC[i], f, erfSC[i]) + t.Errorf("Erf(%g) = %g, want %g", vferfSC[i], f, erfSC[i]) } } } @@ -1641,25 +1651,30 @@ func TestErfc(t *testing.T) { for i := 0; i < len(vf); i++ { a := vf[i] / 10 if f := Erfc(a); !veryclose(erfc[i], f) { - t.Errorf("Erfc(%g) = %g, want %g\n", a, f, erfc[i]) + t.Errorf("Erfc(%g) = %g, want %g", a, f, erfc[i]) } } for i := 0; i < len(vferfcSC); i++ { if f := Erfc(vferfcSC[i]); !alike(erfcSC[i], f) { - t.Errorf("Erfc(%g) = %g, want %g\n", vferfcSC[i], f, erfcSC[i]) + t.Errorf("Erfc(%g) = %g, want %g", vferfcSC[i], f, erfcSC[i]) } } } func TestExp(t *testing.T) { + testExp(t, Exp, "Exp") + testExp(t, ExpGo, "ExpGo") +} + +func testExp(t *testing.T, Exp func(float64) float64, name string) { for i := 0; i < len(vf); i++ { if f := Exp(vf[i]); !close(exp[i], f) { - t.Errorf("Exp(%g) = %g, want %g\n", vf[i], f, exp[i]) + t.Errorf("%s(%g) = %g, want %g", name, vf[i], f, exp[i]) } } for i := 0; i < len(vfexpSC); i++ { if f := Exp(vfexpSC[i]); !alike(expSC[i], f) { - t.Errorf("Exp(%g) = %g, want %g\n", vfexpSC[i], f, expSC[i]) + t.Errorf("%s(%g) = %g, want %g", name, vfexpSC[i], f, expSC[i]) } } } @@ -1668,25 +1683,37 @@ func TestExpm1(t *testing.T) { for i := 0; i < len(vf); i++ { a := vf[i] / 100 if f := Expm1(a); !veryclose(expm1[i], f) { - t.Errorf("Expm1(%g) = %g, want %g\n", a, f, expm1[i]) + t.Errorf("Expm1(%g) = %g, want %g", a, f, expm1[i]) } } for i := 0; i < len(vfexpm1SC); i++ { if f := Expm1(vfexpm1SC[i]); !alike(expm1SC[i], f) { - t.Errorf("Expm1(%g) = %g, want %g\n", vfexpm1SC[i], f, expm1SC[i]) + t.Errorf("Expm1(%g) = %g, want %g", vfexpm1SC[i], f, expm1SC[i]) } } } func TestExp2(t *testing.T) { + testExp2(t, Exp2, "Exp2") + testExp2(t, Exp2Go, "Exp2Go") +} + +func testExp2(t *testing.T, Exp2 func(float64) float64, name string) { 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]) + t.Errorf("%s(%g) = %g, want %g", name, 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]) + t.Errorf("%s(%g) = %g, want %g", name, vfexpSC[i], f, expSC[i]) + } + } + for n := -1074; n < 1024; n++ { + f := Exp2(float64(n)) + vf := Ldexp(1, n) + if f != vf { + t.Errorf("%s(%d) = %g, want %g", name, n, f, vf) } } } @@ -1694,12 +1721,12 @@ func TestExp2(t *testing.T) { func TestFabs(t *testing.T) { for i := 0; i < len(vf); i++ { if f := Fabs(vf[i]); fabs[i] != f { - t.Errorf("Fabs(%g) = %g, want %g\n", vf[i], f, fabs[i]) + t.Errorf("Fabs(%g) = %g, want %g", vf[i], f, fabs[i]) } } for i := 0; i < len(vffabsSC); i++ { if f := Fabs(vffabsSC[i]); !alike(fabsSC[i], f) { - t.Errorf("Fabs(%g) = %g, want %g\n", vffabsSC[i], f, fabsSC[i]) + t.Errorf("Fabs(%g) = %g, want %g", vffabsSC[i], f, fabsSC[i]) } } } @@ -1707,7 +1734,7 @@ func TestFabs(t *testing.T) { func TestFdim(t *testing.T) { for i := 0; i < len(vf); i++ { if f := Fdim(vf[i], 0); fdim[i] != f { - t.Errorf("Fdim(%g, %g) = %g, want %g\n", vf[i], 0.0, f, fdim[i]) + t.Errorf("Fdim(%g, %g) = %g, want %g", vf[i], 0.0, f, fdim[i]) } } } @@ -1715,12 +1742,12 @@ func TestFdim(t *testing.T) { func TestFloor(t *testing.T) { for i := 0; i < len(vf); i++ { if f := Floor(vf[i]); floor[i] != f { - t.Errorf("Floor(%g) = %g, want %g\n", vf[i], f, floor[i]) + t.Errorf("Floor(%g) = %g, want %g", vf[i], f, floor[i]) } } for i := 0; i < len(vfceilSC); i++ { if f := Floor(vfceilSC[i]); !alike(ceilSC[i], f) { - t.Errorf("Floor(%g) = %g, want %g\n", vfceilSC[i], f, ceilSC[i]) + t.Errorf("Floor(%g) = %g, want %g", vfceilSC[i], f, ceilSC[i]) } } } @@ -1728,7 +1755,7 @@ func TestFloor(t *testing.T) { func TestFmax(t *testing.T) { for i := 0; i < len(vf); i++ { if f := Fmax(vf[i], ceil[i]); ceil[i] != f { - t.Errorf("Fmax(%g, %g) = %g, want %g\n", vf[i], ceil[i], f, ceil[i]) + t.Errorf("Fmax(%g, %g) = %g, want %g", vf[i], ceil[i], f, ceil[i]) } } } @@ -1736,7 +1763,7 @@ func TestFmax(t *testing.T) { func TestFmin(t *testing.T) { for i := 0; i < len(vf); i++ { if f := Fmin(vf[i], floor[i]); floor[i] != f { - t.Errorf("Fmin(%g, %g) = %g, want %g\n", vf[i], floor[i], f, floor[i]) + t.Errorf("Fmin(%g, %g) = %g, want %g", vf[i], floor[i], f, floor[i]) } } } @@ -1744,12 +1771,12 @@ func TestFmin(t *testing.T) { func TestFmod(t *testing.T) { for i := 0; i < len(vf); i++ { if f := Fmod(10, vf[i]); fmod[i] != f { - t.Errorf("Fmod(10, %g) = %g, want %g\n", vf[i], f, fmod[i]) + t.Errorf("Fmod(10, %g) = %g, want %g", vf[i], f, fmod[i]) } } for i := 0; i < len(vffmodSC); i++ { if f := Fmod(vffmodSC[i][0], vffmodSC[i][1]); !alike(fmodSC[i], f) { - t.Errorf("Fmod(%g, %g) = %g, want %g\n", vffmodSC[i][0], vffmodSC[i][1], f, fmodSC[i]) + t.Errorf("Fmod(%g, %g) = %g, want %g", vffmodSC[i][0], vffmodSC[i][1], f, fmodSC[i]) } } } @@ -1757,12 +1784,12 @@ func TestFmod(t *testing.T) { func TestFrexp(t *testing.T) { for i := 0; i < len(vf); i++ { if f, j := Frexp(vf[i]); !veryclose(frexp[i].f, f) || frexp[i].i != j { - t.Errorf("Frexp(%g) = %g, %d, want %g, %d\n", vf[i], f, j, frexp[i].f, frexp[i].i) + t.Errorf("Frexp(%g) = %g, %d, want %g, %d", vf[i], f, j, frexp[i].f, frexp[i].i) } } for i := 0; i < len(vffrexpSC); i++ { if f, j := Frexp(vffrexpSC[i]); !alike(frexpSC[i].f, f) || frexpSC[i].i != j { - t.Errorf("Frexp(%g) = %g, %d, want %g, %d\n", vffrexpSC[i], f, j, frexpSC[i].f, frexpSC[i].i) + t.Errorf("Frexp(%g) = %g, %d, want %g, %d", vffrexpSC[i], f, j, frexpSC[i].f, frexpSC[i].i) } } } @@ -1770,12 +1797,12 @@ func TestFrexp(t *testing.T) { func TestGamma(t *testing.T) { for i := 0; i < len(vf); i++ { if f := Gamma(vf[i]); !close(gamma[i], f) { - t.Errorf("Gamma(%g) = %g, want %g\n", vf[i], f, gamma[i]) + t.Errorf("Gamma(%g) = %g, want %g", vf[i], f, gamma[i]) } } for i := 0; i < len(vfgammaSC); i++ { if f := Gamma(vfgammaSC[i]); !alike(gammaSC[i], f) { - t.Errorf("Gamma(%g) = %g, want %g\n", vfgammaSC[i], f, gammaSC[i]) + t.Errorf("Gamma(%g) = %g, want %g", vfgammaSC[i], f, gammaSC[i]) } } } @@ -1784,25 +1811,26 @@ func TestHypot(t *testing.T) { for i := 0; i < len(vf); i++ { a := Fabs(1e200 * tanh[i] * Sqrt(2)) if f := Hypot(1e200*tanh[i], 1e200*tanh[i]); !veryclose(a, f) { - t.Errorf("Hypot(%g, %g) = %g, want %g\n", 1e200*tanh[i], 1e200*tanh[i], f, a) + t.Errorf("Hypot(%g, %g) = %g, want %g", 1e200*tanh[i], 1e200*tanh[i], f, a) } } for i := 0; i < len(vfhypotSC); i++ { if f := Hypot(vfhypotSC[i][0], vfhypotSC[i][1]); !alike(hypotSC[i], f) { - t.Errorf("Hypot(%g, %g) = %g, want %g\n", vfhypotSC[i][0], vfhypotSC[i][1], f, hypotSC[i]) + t.Errorf("Hypot(%g, %g) = %g, want %g", vfhypotSC[i][0], vfhypotSC[i][1], f, hypotSC[i]) } } } func TestIlogb(t *testing.T) { for i := 0; i < len(vf); i++ { - if e := Ilogb(vf[i]); frexp[i].i != e { - t.Errorf("Ilogb(%g) = %d, want %d\n", vf[i], e, frexp[i].i) + a := frexp[i].i - 1 // adjust because fr in the interval [½, 1) + if e := Ilogb(vf[i]); a != e { + t.Errorf("Ilogb(%g) = %d, want %d", vf[i], e, a) } } for i := 0; i < len(vflogbSC); i++ { if e := Ilogb(vflogbSC[i]); ilogbSC[i] != e { - t.Errorf("Ilogb(%g) = %d, want %d\n", vflogbSC[i], e, ilogbSC[i]) + t.Errorf("Ilogb(%g) = %d, want %d", vflogbSC[i], e, ilogbSC[i]) } } } @@ -1810,12 +1838,12 @@ func TestIlogb(t *testing.T) { func TestJ0(t *testing.T) { for i := 0; i < len(vf); i++ { if f := J0(vf[i]); !soclose(j0[i], f, 4e-14) { - t.Errorf("J0(%g) = %g, want %g\n", vf[i], f, j0[i]) + t.Errorf("J0(%g) = %g, want %g", vf[i], f, j0[i]) } } for i := 0; i < len(vfj0SC); i++ { if f := J0(vfj0SC[i]); !alike(j0SC[i], f) { - t.Errorf("J0(%g) = %g, want %g\n", vfj0SC[i], f, j0SC[i]) + t.Errorf("J0(%g) = %g, want %g", vfj0SC[i], f, j0SC[i]) } } } @@ -1823,12 +1851,12 @@ func TestJ0(t *testing.T) { func TestJ1(t *testing.T) { for i := 0; i < len(vf); i++ { if f := J1(vf[i]); !close(j1[i], f) { - t.Errorf("J1(%g) = %g, want %g\n", vf[i], f, j1[i]) + t.Errorf("J1(%g) = %g, want %g", vf[i], f, j1[i]) } } for i := 0; i < len(vfj0SC); i++ { if f := J1(vfj0SC[i]); !alike(j1SC[i], f) { - t.Errorf("J1(%g) = %g, want %g\n", vfj0SC[i], f, j1SC[i]) + t.Errorf("J1(%g) = %g, want %g", vfj0SC[i], f, j1SC[i]) } } } @@ -1836,18 +1864,18 @@ func TestJ1(t *testing.T) { func TestJn(t *testing.T) { for i := 0; i < len(vf); i++ { if f := Jn(2, vf[i]); !close(j2[i], f) { - t.Errorf("Jn(2, %g) = %g, want %g\n", vf[i], f, j2[i]) + t.Errorf("Jn(2, %g) = %g, want %g", vf[i], f, j2[i]) } if f := Jn(-3, vf[i]); !close(jM3[i], f) { - t.Errorf("Jn(-3, %g) = %g, want %g\n", vf[i], f, jM3[i]) + t.Errorf("Jn(-3, %g) = %g, want %g", vf[i], f, jM3[i]) } } for i := 0; i < len(vfj0SC); i++ { if f := Jn(2, vfj0SC[i]); !alike(j2SC[i], f) { - t.Errorf("Jn(2, %g) = %g, want %g\n", vfj0SC[i], f, j2SC[i]) + t.Errorf("Jn(2, %g) = %g, want %g", vfj0SC[i], f, j2SC[i]) } if f := Jn(-3, vfj0SC[i]); !alike(jM3SC[i], f) { - t.Errorf("Jn(-3, %g) = %g, want %g\n", vfj0SC[i], f, jM3SC[i]) + t.Errorf("Jn(-3, %g) = %g, want %g", vfj0SC[i], f, jM3SC[i]) } } } @@ -1855,12 +1883,12 @@ func TestJn(t *testing.T) { func TestLdexp(t *testing.T) { for i := 0; i < len(vf); i++ { if f := Ldexp(frexp[i].f, frexp[i].i); !veryclose(vf[i], f) { - t.Errorf("Ldexp(%g, %d) = %g, want %g\n", frexp[i].f, frexp[i].i, f, vf[i]) + t.Errorf("Ldexp(%g, %d) = %g, want %g", frexp[i].f, frexp[i].i, f, vf[i]) } } for i := 0; i < len(vffrexpSC); i++ { if f := Ldexp(frexpSC[i].f, frexpSC[i].i); !alike(vffrexpSC[i], f) { - t.Errorf("Ldexp(%g, %d) = %g, want %g\n", frexpSC[i].f, frexpSC[i].i, f, vffrexpSC[i]) + t.Errorf("Ldexp(%g, %d) = %g, want %g", frexpSC[i].f, frexpSC[i].i, f, vffrexpSC[i]) } } } @@ -1868,12 +1896,12 @@ func TestLdexp(t *testing.T) { func TestLgamma(t *testing.T) { for i := 0; i < len(vf); i++ { if f, s := Lgamma(vf[i]); !close(lgamma[i].f, f) || lgamma[i].i != s { - t.Errorf("Lgamma(%g) = %g, %d, want %g, %d\n", vf[i], f, s, lgamma[i].f, lgamma[i].i) + t.Errorf("Lgamma(%g) = %g, %d, want %g, %d", vf[i], f, s, lgamma[i].f, lgamma[i].i) } } for i := 0; i < len(vflgammaSC); i++ { if f, s := Lgamma(vflgammaSC[i]); !alike(lgammaSC[i].f, f) || lgammaSC[i].i != s { - t.Errorf("Lgamma(%g) = %g, %d, want %g, %d\n", vflgammaSC[i], f, s, lgammaSC[i].f, lgammaSC[i].i) + t.Errorf("Lgamma(%g) = %g, %d, want %g, %d", vflgammaSC[i], f, s, lgammaSC[i].f, lgammaSC[i].i) } } } @@ -1882,15 +1910,15 @@ func TestLog(t *testing.T) { for i := 0; i < len(vf); i++ { a := Fabs(vf[i]) if f := Log(a); log[i] != f { - t.Errorf("Log(%g) = %g, want %g\n", a, f, log[i]) + t.Errorf("Log(%g) = %g, want %g", a, f, log[i]) } } if f := Log(10); f != Ln10 { - t.Errorf("Log(%g) = %g, want %g\n", 10.0, f, Ln10) + t.Errorf("Log(%g) = %g, want %g", 10.0, f, Ln10) } for i := 0; i < len(vflogSC); i++ { if f := Log(vflogSC[i]); !alike(logSC[i], f) { - t.Errorf("Log(%g) = %g, want %g\n", vflogSC[i], f, logSC[i]) + t.Errorf("Log(%g) = %g, want %g", vflogSC[i], f, logSC[i]) } } } @@ -1898,12 +1926,12 @@ func TestLog(t *testing.T) { func TestLogb(t *testing.T) { for i := 0; i < len(vf); i++ { if f := Logb(vf[i]); logb[i] != f { - t.Errorf("Logb(%g) = %g, want %g\n", vf[i], f, logb[i]) + t.Errorf("Logb(%g) = %g, want %g", vf[i], f, logb[i]) } } for i := 0; i < len(vflogbSC); i++ { if f := Logb(vflogbSC[i]); !alike(logbSC[i], f) { - t.Errorf("Logb(%g) = %g, want %g\n", vflogbSC[i], f, logbSC[i]) + t.Errorf("Logb(%g) = %g, want %g", vflogbSC[i], f, logbSC[i]) } } } @@ -1912,15 +1940,15 @@ func TestLog10(t *testing.T) { for i := 0; i < len(vf); i++ { a := Fabs(vf[i]) if f := Log10(a); !veryclose(log10[i], f) { - t.Errorf("Log10(%g) = %g, want %g\n", a, f, log10[i]) + t.Errorf("Log10(%g) = %g, want %g", a, f, log10[i]) } } if f := Log10(E); f != Log10E { - t.Errorf("Log10(%g) = %g, want %g\n", E, f, Log10E) + t.Errorf("Log10(%g) = %g, want %g", E, f, Log10E) } for i := 0; i < len(vflogSC); i++ { if f := Log10(vflogSC[i]); !alike(logSC[i], f) { - t.Errorf("Log10(%g) = %g, want %g\n", vflogSC[i], f, logSC[i]) + t.Errorf("Log10(%g) = %g, want %g", vflogSC[i], f, logSC[i]) } } } @@ -1929,16 +1957,16 @@ func TestLog1p(t *testing.T) { for i := 0; i < len(vf); i++ { a := vf[i] / 100 if f := Log1p(a); !veryclose(log1p[i], f) { - t.Errorf("Log1p(%g) = %g, want %g\n", a, f, log1p[i]) + t.Errorf("Log1p(%g) = %g, want %g", a, f, log1p[i]) } } a := float64(9) if f := Log1p(a); f != Ln10 { - t.Errorf("Log1p(%g) = %g, want %g\n", a, f, Ln10) + t.Errorf("Log1p(%g) = %g, want %g", a, f, Ln10) } for i := 0; i < len(vflogSC); i++ { if f := Log1p(vflog1pSC[i]); !alike(log1pSC[i], f) { - t.Errorf("Log1p(%g) = %g, want %g\n", vflog1pSC[i], f, log1pSC[i]) + t.Errorf("Log1p(%g) = %g, want %g", vflog1pSC[i], f, log1pSC[i]) } } } @@ -1947,15 +1975,15 @@ func TestLog2(t *testing.T) { for i := 0; i < len(vf); i++ { a := Fabs(vf[i]) if f := Log2(a); !veryclose(log2[i], f) { - t.Errorf("Log2(%g) = %g, want %g\n", a, f, log2[i]) + t.Errorf("Log2(%g) = %g, want %g", a, f, log2[i]) } } if f := Log2(E); f != Log2E { - t.Errorf("Log2(%g) = %g, want %g\n", E, f, Log2E) + t.Errorf("Log2(%g) = %g, want %g", E, f, Log2E) } for i := 0; i < len(vflogSC); i++ { if f := Log2(vflogSC[i]); !alike(logSC[i], f) { - t.Errorf("Log2(%g) = %g, want %g\n", vflogSC[i], f, logSC[i]) + t.Errorf("Log2(%g) = %g, want %g", vflogSC[i], f, logSC[i]) } } } @@ -1963,12 +1991,12 @@ func TestLog2(t *testing.T) { func TestModf(t *testing.T) { for i := 0; i < len(vf); i++ { if f, g := Modf(vf[i]); !veryclose(modf[i][0], f) || !veryclose(modf[i][1], g) { - t.Errorf("Modf(%g) = %g, %g, want %g, %g\n", vf[i], f, g, modf[i][0], modf[i][1]) + t.Errorf("Modf(%g) = %g, %g, want %g, %g", vf[i], f, g, modf[i][0], modf[i][1]) } } for i := 0; i < len(vfmodfSC); i++ { if f, g := Modf(vfmodfSC[i]); !alike(modfSC[i][0], f) || !alike(modfSC[i][1], g) { - t.Errorf("Modf(%g) = %g, %g, want %g, %g\n", vfmodfSC[i], f, g, modfSC[i][0], modfSC[i][1]) + t.Errorf("Modf(%g) = %g, %g, want %g, %g", vfmodfSC[i], f, g, modfSC[i][0], modfSC[i][1]) } } } @@ -1976,12 +2004,12 @@ func TestModf(t *testing.T) { func TestNextafter(t *testing.T) { for i := 0; i < len(vf); i++ { if f := Nextafter(vf[i], 10); nextafter[i] != f { - t.Errorf("Nextafter(%g, %g) = %g want %g\n", vf[i], 10.0, f, nextafter[i]) + t.Errorf("Nextafter(%g, %g) = %g want %g", vf[i], 10.0, f, nextafter[i]) } } for i := 0; i < len(vfmodfSC); i++ { if f := Nextafter(vfnextafterSC[i][0], vfnextafterSC[i][1]); !alike(nextafterSC[i], f) { - t.Errorf("Nextafter(%g, %g) = %g want %g\n", vfnextafterSC[i][0], vfnextafterSC[i][1], f, nextafterSC[i]) + t.Errorf("Nextafter(%g, %g) = %g want %g", vfnextafterSC[i][0], vfnextafterSC[i][1], f, nextafterSC[i]) } } } @@ -1989,12 +2017,12 @@ func TestNextafter(t *testing.T) { func TestPow(t *testing.T) { for i := 0; i < len(vf); i++ { if f := Pow(10, vf[i]); !close(pow[i], f) { - t.Errorf("Pow(10, %g) = %g, want %g\n", vf[i], f, pow[i]) + t.Errorf("Pow(10, %g) = %g, want %g", vf[i], f, pow[i]) } } for i := 0; i < len(vfpowSC); i++ { if f := Pow(vfpowSC[i][0], vfpowSC[i][1]); !alike(powSC[i], f) { - t.Errorf("Pow(%g, %g) = %g, want %g\n", vfpowSC[i][0], vfpowSC[i][1], f, powSC[i]) + t.Errorf("Pow(%g, %g) = %g, want %g", vfpowSC[i][0], vfpowSC[i][1], f, powSC[i]) } } } @@ -2002,12 +2030,12 @@ func TestPow(t *testing.T) { func TestRemainder(t *testing.T) { for i := 0; i < len(vf); i++ { if f := Remainder(10, vf[i]); remainder[i] != f { - t.Errorf("Remainder(10, %g) = %g, want %g\n", vf[i], f, remainder[i]) + t.Errorf("Remainder(10, %g) = %g, want %g", vf[i], f, remainder[i]) } } for i := 0; i < len(vffmodSC); i++ { if f := Remainder(vffmodSC[i][0], vffmodSC[i][1]); !alike(fmodSC[i], f) { - t.Errorf("Remainder(%g, %g) = %g, want %g\n", vffmodSC[i][0], vffmodSC[i][1], f, fmodSC[i]) + t.Errorf("Remainder(%g, %g) = %g, want %g", vffmodSC[i][0], vffmodSC[i][1], f, fmodSC[i]) } } } @@ -2015,24 +2043,24 @@ func TestRemainder(t *testing.T) { func TestSignbit(t *testing.T) { for i := 0; i < len(vf); i++ { if f := Signbit(vf[i]); signbit[i] != f { - t.Errorf("Signbit(%g) = %t, want %t\n", vf[i], f, signbit[i]) + t.Errorf("Signbit(%g) = %t, want %t", vf[i], f, signbit[i]) } } for i := 0; i < len(vfsignbitSC); i++ { if f := Signbit(vfsignbitSC[i]); signbitSC[i] != f { - t.Errorf("Signbit(%g) = %t, want %t\n", vfsignbitSC[i], f, signbitSC[i]) + t.Errorf("Signbit(%g) = %t, want %t", vfsignbitSC[i], f, signbitSC[i]) } } } func TestSin(t *testing.T) { for i := 0; i < len(vf); i++ { if f := Sin(vf[i]); !close(sin[i], f) { - t.Errorf("Sin(%g) = %g, want %g\n", vf[i], f, sin[i]) + t.Errorf("Sin(%g) = %g, want %g", vf[i], f, sin[i]) } } for i := 0; i < len(vfsinSC); i++ { if f := Sin(vfsinSC[i]); !alike(sinSC[i], f) { - t.Errorf("Sin(%g) = %g, want %g\n", vfsinSC[i], f, sinSC[i]) + t.Errorf("Sin(%g) = %g, want %g", vfsinSC[i], f, sinSC[i]) } } } @@ -2040,7 +2068,7 @@ func TestSin(t *testing.T) { func TestSincos(t *testing.T) { for i := 0; i < len(vf); i++ { if s, c := Sincos(vf[i]); !close(sin[i], s) || !close(cos[i], c) { - t.Errorf("Sincos(%g) = %g, %g want %g, %g\n", vf[i], s, c, sin[i], cos[i]) + t.Errorf("Sincos(%g) = %g, %g want %g, %g", vf[i], s, c, sin[i], cos[i]) } } } @@ -2048,12 +2076,12 @@ func TestSincos(t *testing.T) { func TestSinh(t *testing.T) { for i := 0; i < len(vf); i++ { if f := Sinh(vf[i]); !close(sinh[i], f) { - t.Errorf("Sinh(%g) = %g, want %g\n", vf[i], f, sinh[i]) + t.Errorf("Sinh(%g) = %g, want %g", vf[i], f, sinh[i]) } } for i := 0; i < len(vfsinhSC); i++ { if f := Sinh(vfsinhSC[i]); !alike(sinhSC[i], f) { - t.Errorf("Sinh(%g) = %g, want %g\n", vfsinhSC[i], f, sinhSC[i]) + t.Errorf("Sinh(%g) = %g, want %g", vfsinhSC[i], f, sinhSC[i]) } } } @@ -2062,19 +2090,19 @@ func TestSqrt(t *testing.T) { for i := 0; i < len(vf); i++ { a := Fabs(vf[i]) if f := SqrtGo(a); sqrt[i] != f { - t.Errorf("SqrtGo(%g) = %g, want %g\n", a, f, sqrt[i]) + t.Errorf("SqrtGo(%g) = %g, want %g", a, f, sqrt[i]) } a = Fabs(vf[i]) if f := Sqrt(a); sqrt[i] != f { - t.Errorf("Sqrt(%g) = %g, want %g\n", a, f, sqrt[i]) + t.Errorf("Sqrt(%g) = %g, want %g", a, f, sqrt[i]) } } for i := 0; i < len(vfsqrtSC); i++ { if f := SqrtGo(vfsqrtSC[i]); !alike(sqrtSC[i], f) { - t.Errorf("SqrtGo(%g) = %g, want %g\n", vfsqrtSC[i], f, sqrtSC[i]) + t.Errorf("SqrtGo(%g) = %g, want %g", vfsqrtSC[i], f, sqrtSC[i]) } if f := Sqrt(vfsqrtSC[i]); !alike(sqrtSC[i], f) { - t.Errorf("Sqrt(%g) = %g, want %g\n", vfsqrtSC[i], f, sqrtSC[i]) + t.Errorf("Sqrt(%g) = %g, want %g", vfsqrtSC[i], f, sqrtSC[i]) } } } @@ -2082,13 +2110,23 @@ func TestSqrt(t *testing.T) { func TestTan(t *testing.T) { for i := 0; i < len(vf); i++ { if f := Tan(vf[i]); !close(tan[i], f) { - t.Errorf("Tan(%g) = %g, want %g\n", vf[i], f, tan[i]) + t.Errorf("Tan(%g) = %g, want %g", vf[i], f, tan[i]) } } // same special cases as Sin for i := 0; i < len(vfsinSC); i++ { if f := Tan(vfsinSC[i]); !alike(sinSC[i], f) { - t.Errorf("Tan(%g) = %g, want %g\n", vfsinSC[i], f, sinSC[i]) + t.Errorf("Tan(%g) = %g, want %g", vfsinSC[i], f, sinSC[i]) + } + } + + // Make sure portable Tan(Pi/2) doesn't panic (it used to). + // The portable implementation returns NaN. + // Assembly implementations might not, + // because Pi/2 is not exactly representable. + if runtime.GOARCH != "386" { + if f := Tan(Pi / 2); !alike(f, NaN()) { + t.Errorf("Tan(%g) = %g, want %g", Pi/2, f, NaN()) } } } @@ -2096,12 +2134,12 @@ func TestTan(t *testing.T) { func TestTanh(t *testing.T) { for i := 0; i < len(vf); i++ { if f := Tanh(vf[i]); !veryclose(tanh[i], f) { - t.Errorf("Tanh(%g) = %g, want %g\n", vf[i], f, tanh[i]) + t.Errorf("Tanh(%g) = %g, want %g", vf[i], f, tanh[i]) } } for i := 0; i < len(vftanhSC); i++ { if f := Tanh(vftanhSC[i]); !alike(tanhSC[i], f) { - t.Errorf("Tanh(%g) = %g, want %g\n", vftanhSC[i], f, tanhSC[i]) + t.Errorf("Tanh(%g) = %g, want %g", vftanhSC[i], f, tanhSC[i]) } } } @@ -2109,12 +2147,12 @@ func TestTanh(t *testing.T) { func TestTrunc(t *testing.T) { for i := 0; i < len(vf); i++ { if f := Trunc(vf[i]); trunc[i] != f { - t.Errorf("Trunc(%g) = %g, want %g\n", vf[i], f, trunc[i]) + t.Errorf("Trunc(%g) = %g, want %g", vf[i], f, trunc[i]) } } for i := 0; i < len(vfceilSC); i++ { if f := Trunc(vfceilSC[i]); !alike(ceilSC[i], f) { - t.Errorf("Trunc(%g) = %g, want %g\n", vfceilSC[i], f, ceilSC[i]) + t.Errorf("Trunc(%g) = %g, want %g", vfceilSC[i], f, ceilSC[i]) } } } @@ -2123,12 +2161,12 @@ func TestY0(t *testing.T) { for i := 0; i < len(vf); i++ { a := Fabs(vf[i]) if f := Y0(a); !close(y0[i], f) { - t.Errorf("Y0(%g) = %g, want %g\n", a, f, y0[i]) + t.Errorf("Y0(%g) = %g, want %g", a, f, y0[i]) } } for i := 0; i < len(vfy0SC); i++ { if f := Y0(vfy0SC[i]); !alike(y0SC[i], f) { - t.Errorf("Y0(%g) = %g, want %g\n", vfy0SC[i], f, y0SC[i]) + t.Errorf("Y0(%g) = %g, want %g", vfy0SC[i], f, y0SC[i]) } } } @@ -2137,12 +2175,12 @@ func TestY1(t *testing.T) { for i := 0; i < len(vf); i++ { a := Fabs(vf[i]) if f := Y1(a); !soclose(y1[i], f, 2e-14) { - t.Errorf("Y1(%g) = %g, want %g\n", a, f, y1[i]) + t.Errorf("Y1(%g) = %g, want %g", a, f, y1[i]) } } for i := 0; i < len(vfy0SC); i++ { if f := Y1(vfy0SC[i]); !alike(y1SC[i], f) { - t.Errorf("Y1(%g) = %g, want %g\n", vfy0SC[i], f, y1SC[i]) + t.Errorf("Y1(%g) = %g, want %g", vfy0SC[i], f, y1SC[i]) } } } @@ -2151,18 +2189,18 @@ func TestYn(t *testing.T) { for i := 0; i < len(vf); i++ { a := Fabs(vf[i]) if f := Yn(2, a); !close(y2[i], f) { - t.Errorf("Yn(2, %g) = %g, want %g\n", a, f, y2[i]) + t.Errorf("Yn(2, %g) = %g, want %g", a, f, y2[i]) } if f := Yn(-3, a); !close(yM3[i], f) { - t.Errorf("Yn(-3, %g) = %g, want %g\n", a, f, yM3[i]) + t.Errorf("Yn(-3, %g) = %g, want %g", a, f, yM3[i]) } } for i := 0; i < len(vfy0SC); i++ { if f := Yn(2, vfy0SC[i]); !alike(y2SC[i], f) { - t.Errorf("Yn(2, %g) = %g, want %g\n", vfy0SC[i], f, y2SC[i]) + t.Errorf("Yn(2, %g) = %g, want %g", vfy0SC[i], f, y2SC[i]) } if f := Yn(-3, vfy0SC[i]); !alike(yM3SC[i], f) { - t.Errorf("Yn(-3, %g) = %g, want %g\n", vfy0SC[i], f, yM3SC[i]) + t.Errorf("Yn(-3, %g) = %g, want %g", vfy0SC[i], f, yM3SC[i]) } } } @@ -2175,7 +2213,7 @@ func TestLargeCos(t *testing.T) { f1 := Cos(vf[i]) f2 := Cos(vf[i] + large) if !kindaclose(f1, f2) { - t.Errorf("Cos(%g) = %g, want %g\n", vf[i]+large, f2, f1) + t.Errorf("Cos(%g) = %g, want %g", vf[i]+large, f2, f1) } } } @@ -2186,7 +2224,7 @@ func TestLargeSin(t *testing.T) { f1 := Sin(vf[i]) f2 := Sin(vf[i] + large) if !kindaclose(f1, f2) { - t.Errorf("Sin(%g) = %g, want %g\n", vf[i]+large, f2, f1) + t.Errorf("Sin(%g) = %g, want %g", vf[i]+large, f2, f1) } } } @@ -2197,7 +2235,7 @@ func TestLargeSincos(t *testing.T) { f1, g1 := Sincos(vf[i]) f2, g2 := Sincos(vf[i] + large) if !kindaclose(f1, f2) || !kindaclose(g1, g2) { - t.Errorf("Sincos(%g) = %g, %g, want %g, %g\n", vf[i]+large, f2, g2, f1, g1) + t.Errorf("Sincos(%g) = %g, %g, want %g, %g", vf[i]+large, f2, g2, f1, g1) } } } @@ -2208,7 +2246,7 @@ func TestLargeTan(t *testing.T) { f1 := Tan(vf[i]) f2 := Tan(vf[i] + large) if !kindaclose(f1, f2) { - t.Errorf("Tan(%g) = %g, want %g\n", vf[i]+large, f2, f1) + t.Errorf("Tan(%g) = %g, want %g", vf[i]+large, f2, f1) } } } @@ -2224,10 +2262,10 @@ type floatTest struct { } var floatTests = []floatTest{ - floatTest{float64(MaxFloat64), "MaxFloat64", "1.7976931348623157e+308"}, - floatTest{float64(MinFloat64), "MinFloat64", "5e-324"}, - floatTest{float32(MaxFloat32), "MaxFloat32", "3.4028235e+38"}, - floatTest{float32(MinFloat32), "MinFloat32", "1e-45"}, + {float64(MaxFloat64), "MaxFloat64", "1.7976931348623157e+308"}, + {float64(SmallestNonzeroFloat64), "SmallestNonzeroFloat64", "5e-324"}, + {float32(MaxFloat32), "MaxFloat32", "3.4028235e+38"}, + {float32(SmallestNonzeroFloat32), "SmallestNonzeroFloat32", "1e-45"}, } func TestFloatMinMax(t *testing.T) { @@ -2331,6 +2369,12 @@ func BenchmarkExp(b *testing.B) { } } +func BenchmarkExpGo(b *testing.B) { + for i := 0; i < b.N; i++ { + ExpGo(.5) + } +} + func BenchmarkExpm1(b *testing.B) { for i := 0; i < b.N; i++ { Expm1(.5) @@ -2343,6 +2387,12 @@ func BenchmarkExp2(b *testing.B) { } } +func BenchmarkExp2Go(b *testing.B) { + for i := 0; i < b.N; i++ { + Exp2Go(.5) + } +} + func BenchmarkFabs(b *testing.B) { for i := 0; i < b.N; i++ { Fabs(.5) diff --git a/src/pkg/math/bits.go b/src/pkg/math/bits.go index d36cd18d7..1a97e7679 100644 --- a/src/pkg/math/bits.go +++ b/src/pkg/math/bits.go @@ -10,7 +10,7 @@ const ( uvneginf = 0xFFF0000000000000 mask = 0x7FF shift = 64 - 11 - 1 - bias = 1022 + bias = 1023 ) // Inf returns positive infinity if sign >= 0, negative infinity if sign < 0. diff --git a/src/pkg/math/const.go b/src/pkg/math/const.go index 6a78d00a0..b53527a4f 100644 --- a/src/pkg/math/const.go +++ b/src/pkg/math/const.go @@ -25,13 +25,13 @@ const ( // Floating-point limit values. // Max is the largest finite value representable by the type. -// Min is the smallest nonzero value representable by the type. +// SmallestNonzero is the smallest positive, non-zero value representable by the type. const ( - MaxFloat32 = 3.40282346638528859811704183484516925440e+38 /* 2**127 * (2**24 - 1) / 2**23 */ - MinFloat32 = 1.401298464324817070923729583289916131280e-45 /* 1 / 2**(127 - 1 + 23) */ + MaxFloat32 = 3.40282346638528859811704183484516925440e+38 /* 2**127 * (2**24 - 1) / 2**23 */ + SmallestNonzeroFloat32 = 1.401298464324817070923729583289916131280e-45 /* 1 / 2**(127 - 1 + 23) */ - MaxFloat64 = 1.797693134862315708145274237317043567981e+308 /* 2**1023 * (2**53 - 1) / 2**52 */ - MinFloat64 = 4.940656458412465441765687928682213723651e-324 /* 1 / 2**(1023 - 1 + 52) */ + MaxFloat64 = 1.797693134862315708145274237317043567981e+308 /* 2**1023 * (2**53 - 1) / 2**52 */ + SmallestNonzeroFloat64 = 4.940656458412465441765687928682213723651e-324 /* 1 / 2**(1023 - 1 + 52) */ ) // Integer limit values. diff --git a/src/pkg/math/exp.go b/src/pkg/math/exp.go index 90409c341..c519c2cb6 100644 --- a/src/pkg/math/exp.go +++ b/src/pkg/math/exp.go @@ -4,83 +4,6 @@ package math - -// The original C code, the long comment, and the constants -// below are from FreeBSD's /usr/src/lib/msun/src/e_exp.c -// and came with this notice. The go code is a simplified -// version of the original C. -// -// ==================================================== -// Copyright (C) 2004 by Sun Microsystems, Inc. All rights reserved. -// -// Permission to use, copy, modify, and distribute this -// software is freely granted, provided that this notice -// is preserved. -// ==================================================== -// -// -// exp(x) -// Returns the exponential of x. -// -// Method -// 1. Argument reduction: -// Reduce x to an r so that |r| <= 0.5*ln2 ~ 0.34658. -// Given x, find r and integer k such that -// -// x = k*ln2 + r, |r| <= 0.5*ln2. -// -// Here r will be represented as r = hi-lo for better -// accuracy. -// -// 2. Approximation of exp(r) by a special rational function on -// the interval [0,0.34658]: -// Write -// R(r**2) = r*(exp(r)+1)/(exp(r)-1) = 2 + r*r/6 - r**4/360 + ... -// We use a special Remes algorithm on [0,0.34658] to generate -// a polynomial of degree 5 to approximate R. The maximum error -// of this polynomial approximation is bounded by 2**-59. In -// other words, -// R(z) ~ 2.0 + P1*z + P2*z**2 + P3*z**3 + P4*z**4 + P5*z**5 -// (where z=r*r, and the values of P1 to P5 are listed below) -// and -// | 5 | -59 -// | 2.0+P1*z+...+P5*z - R(z) | <= 2 -// | | -// The computation of exp(r) thus becomes -// 2*r -// exp(r) = 1 + ------- -// R - r -// r*R1(r) -// = 1 + r + ----------- (for better accuracy) -// 2 - R1(r) -// where -// 2 4 10 -// R1(r) = r - (P1*r + P2*r + ... + P5*r ). -// -// 3. Scale back to obtain exp(x): -// From step 1, we have -// exp(x) = 2**k * exp(r) -// -// Special cases: -// exp(INF) is INF, exp(NaN) is NaN; -// exp(-INF) is 0, and -// for finite argument, only exp(0)=1 is exact. -// -// Accuracy: -// according to an error analysis, the error is always less than -// 1 ulp (unit in the last place). -// -// Misc. info. -// For IEEE double -// if x > 7.09782712893383973096e+02 then exp(x) overflow -// if x < -7.45133219101941108420e+02 then exp(x) underflow -// -// Constants: -// The hexadecimal values are the intended ones for the following -// constants. The decimal values may be used, provided that the -// compiler will convert from decimal to binary accurately enough -// to produce the hexadecimal values shown. - // Exp returns e**x, the base-e exponential of x. // // Special cases are: @@ -88,54 +11,4 @@ package math // Exp(NaN) = NaN // Very large values overflow to 0 or +Inf. // Very small values underflow to 1. -func Exp(x float64) float64 { - const ( - Ln2Hi = 6.93147180369123816490e-01 - Ln2Lo = 1.90821492927058770002e-10 - Log2e = 1.44269504088896338700e+00 - P1 = 1.66666666666666019037e-01 /* 0x3FC55555; 0x5555553E */ - P2 = -2.77777777770155933842e-03 /* 0xBF66C16C; 0x16BEBD93 */ - P3 = 6.61375632143793436117e-05 /* 0x3F11566A; 0xAF25DE2C */ - P4 = -1.65339022054652515390e-06 /* 0xBEBBBD41; 0xC5D26BF1 */ - P5 = 4.13813679705723846039e-08 /* 0x3E663769; 0x72BEA4D0 */ - - Overflow = 7.09782712893383973096e+02 - Underflow = -7.45133219101941108420e+02 - NearZero = 1.0 / (1 << 28) // 2**-28 - ) - - // TODO(rsc): Remove manual inlining of IsNaN, IsInf - // when compiler does it for us - // special cases - switch { - case x != x || x > MaxFloat64: // IsNaN(x) || IsInf(x, 1): - return x - case x < -MaxFloat64: // IsInf(x, -1): - return 0 - case x > Overflow: - return Inf(1) - case x < Underflow: - return 0 - case -NearZero < x && x < NearZero: - return 1 - } - - // reduce; computed as r = hi - lo for extra precision. - var k int - switch { - case x < 0: - k = int(Log2e*x - 0.5) - case x > 0: - k = int(Log2e*x + 0.5) - } - hi := x - float64(k)*Ln2Hi - lo := float64(k) * Ln2Lo - r := hi - lo - - // compute - t := r * r - c := r - t*(P1+t*(P2+t*(P3+t*(P4+t*P5)))) - y := 1 - ((lo - (r*c)/(2-c)) - hi) - // TODO(rsc): make sure Ldexp can handle boundary k - return Ldexp(y, k) -} +func Exp(x float64) float64 { return expGo(x) } diff --git a/src/pkg/math/exp2.go b/src/pkg/math/exp2.go index 1e67f29eb..1cface9d3 100644 --- a/src/pkg/math/exp2.go +++ b/src/pkg/math/exp2.go @@ -7,4 +7,4 @@ package math // 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) } +func Exp2(x float64) float64 { return exp2Go(x) } diff --git a/src/pkg/math/exp_amd64.s b/src/pkg/math/exp_amd64.s index 844b5c923..74c9c876a 100644 --- a/src/pkg/math/exp_amd64.s +++ b/src/pkg/math/exp_amd64.s @@ -19,20 +19,32 @@ #define LOG2E 1.4426950408889634073599246810018920 // 1/LN2 #define LN2U 0.69314718055966295651160180568695068359375 // upper half LN2 #define LN2L 0.28235290563031577122588448175013436025525412068e-12 // lower half LN2 +#define T0 1.0 +#define T1 0.5 +#define T2 1.6666666666666666667e-1 +#define T3 4.1666666666666666667e-2 +#define T4 8.3333333333333333333e-3 +#define T5 1.3888888888888888889e-3 +#define T6 1.9841269841269841270e-4 +#define T7 2.4801587301587301587e-5 +#define PosInf 0x7FF0000000000000 +#define NegInf 0xFFF0000000000000 // func Exp(x float64) float64 TEXT ·Exp(SB),7,$0 // test bits for not-finite - MOVQ x+0(FP), AX - MOVQ $0x7ff0000000000000, BX - ANDQ BX, AX - CMPQ BX, AX - JEQ not_finite - MOVSD x+0(FP), X0 + MOVQ x+0(FP), BX + MOVQ $~(1<<63), AX // sign bit mask + MOVQ BX, DX + ANDQ AX, DX + MOVQ $PosInf, AX + CMPQ AX, DX + JLE notFinite + MOVQ BX, X0 MOVSD $LOG2E, X1 MULSD X0, X1 - CVTTSD2SQ X1, BX // BX = exponent - CVTSQ2SD BX, X1 + CVTSD2SL X1, BX // BX = exponent + CVTSL2SD BX, X1 MOVSD $LN2U, X2 MULSD X1, X2 SUBSD X2, X0 @@ -40,31 +52,23 @@ TEXT ·Exp(SB),7,$0 MULSD X1, X2 SUBSD X2, X0 // reduce argument - MOVSD $0.0625, X1 - MULSD X1, X0 + MULSD $0.0625, X0 // Taylor series evaluation - MOVSD $2.4801587301587301587e-5, X1 + MOVSD $T7, X1 MULSD X0, X1 - MOVSD $1.9841269841269841270e-4, X2 - ADDSD X2, X1 + ADDSD $T6, X1 MULSD X0, X1 - MOVSD $1.3888888888888888889e-3, X2 - ADDSD X2, X1 + ADDSD $T5, X1 MULSD X0, X1 - MOVSD $8.3333333333333333333e-3, X2 - ADDSD X2, X1 + ADDSD $T4, X1 MULSD X0, X1 - MOVSD $4.1666666666666666667e-2, X2 - ADDSD X2, X1 + ADDSD $T3, X1 MULSD X0, X1 - MOVSD $1.6666666666666666667e-1, X2 - ADDSD X2, X1 + ADDSD $T2, X1 MULSD X0, X1 - MOVSD $0.5, X2 - ADDSD X2, X1 + ADDSD $T1, X1 MULSD X0, X1 - MOVSD $1.0, X2 - ADDSD X2, X1 + ADDSD $T0, X1 MULSD X1, X0 MOVSD $2.0, X1 ADDSD X0, X1 @@ -78,27 +82,31 @@ TEXT ·Exp(SB),7,$0 MOVSD $2.0, X1 ADDSD X0, X1 MULSD X1, X0 - MOVSD $1.0, X1 - ADDSD X1, X0 - // return ldexp(fr, exp) - MOVQ $0x3ff, AX // bias + 1 - ADDQ AX, BX + ADDSD $1.0, X0 + // return fr * 2**exponent + MOVL $0x3FF, AX // bias + ADDL AX, BX + JLE underflow + CMPL BX, $0x7FF + JGE overflow + MOVL $52, CX + SHLQ CX, BX MOVQ BX, X1 - MOVQ $52, AX // shift - MOVQ AX, X2 - PSLLQ X2, X1 MULSD X1, X0 MOVSD X0, r+8(FP) RET -not_finite: -// test bits for -Inf - MOVQ x+0(FP), AX - MOVQ $0xfff0000000000000, BX - CMPQ BX, AX - JNE not_neginf - XORQ AX, AX +notFinite: + // test bits for -Inf + MOVQ $NegInf, AX + CMPQ AX, BX + JNE notNegInf + // -Inf, return 0 +underflow: // return 0 + MOVQ $0, AX MOVQ AX, r+8(FP) RET -not_neginf: - MOVQ AX, r+8(FP) +overflow: // return +Inf + MOVQ $PosInf, BX +notNegInf: // NaN or +Inf, return x + MOVQ BX, r+8(FP) RET diff --git a/src/pkg/math/exp_port.go b/src/pkg/math/exp_port.go new file mode 100644 index 000000000..071420c24 --- /dev/null +++ b/src/pkg/math/exp_port.go @@ -0,0 +1,192 @@ +// 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 math + + +// The original C code, the long comment, and the constants +// below are from FreeBSD's /usr/src/lib/msun/src/e_exp.c +// and came with this notice. The go code is a simplified +// version of the original C. +// +// ==================================================== +// Copyright (C) 2004 by Sun Microsystems, Inc. All rights reserved. +// +// Permission to use, copy, modify, and distribute this +// software is freely granted, provided that this notice +// is preserved. +// ==================================================== +// +// +// exp(x) +// Returns the exponential of x. +// +// Method +// 1. Argument reduction: +// Reduce x to an r so that |r| <= 0.5*ln2 ~ 0.34658. +// Given x, find r and integer k such that +// +// x = k*ln2 + r, |r| <= 0.5*ln2. +// +// Here r will be represented as r = hi-lo for better +// accuracy. +// +// 2. Approximation of exp(r) by a special rational function on +// the interval [0,0.34658]: +// Write +// R(r**2) = r*(exp(r)+1)/(exp(r)-1) = 2 + r*r/6 - r**4/360 + ... +// We use a special Remes algorithm on [0,0.34658] to generate +// a polynomial of degree 5 to approximate R. The maximum error +// of this polynomial approximation is bounded by 2**-59. In +// other words, +// R(z) ~ 2.0 + P1*z + P2*z**2 + P3*z**3 + P4*z**4 + P5*z**5 +// (where z=r*r, and the values of P1 to P5 are listed below) +// and +// | 5 | -59 +// | 2.0+P1*z+...+P5*z - R(z) | <= 2 +// | | +// The computation of exp(r) thus becomes +// 2*r +// exp(r) = 1 + ------- +// R - r +// r*R1(r) +// = 1 + r + ----------- (for better accuracy) +// 2 - R1(r) +// where +// 2 4 10 +// R1(r) = r - (P1*r + P2*r + ... + P5*r ). +// +// 3. Scale back to obtain exp(x): +// From step 1, we have +// exp(x) = 2**k * exp(r) +// +// Special cases: +// exp(INF) is INF, exp(NaN) is NaN; +// exp(-INF) is 0, and +// for finite argument, only exp(0)=1 is exact. +// +// Accuracy: +// according to an error analysis, the error is always less than +// 1 ulp (unit in the last place). +// +// Misc. info. +// For IEEE double +// if x > 7.09782712893383973096e+02 then exp(x) overflow +// if x < -7.45133219101941108420e+02 then exp(x) underflow +// +// Constants: +// The hexadecimal values are the intended ones for the following +// constants. The decimal values may be used, provided that the +// compiler will convert from decimal to binary accurately enough +// to produce the hexadecimal values shown. + +// Exp returns e**x, the base-e exponential of x. +// +// Special cases are: +// Exp(+Inf) = +Inf +// Exp(NaN) = NaN +// Very large values overflow to 0 or +Inf. +// Very small values underflow to 1. +func expGo(x float64) float64 { + const ( + Ln2Hi = 6.93147180369123816490e-01 + Ln2Lo = 1.90821492927058770002e-10 + Log2e = 1.44269504088896338700e+00 + + Overflow = 7.09782712893383973096e+02 + Underflow = -7.45133219101941108420e+02 + NearZero = 1.0 / (1 << 28) // 2**-28 + ) + + // TODO(rsc): Remove manual inlining of IsNaN, IsInf + // when compiler does it for us + // special cases + switch { + case x != x || x > MaxFloat64: // IsNaN(x) || IsInf(x, 1): + return x + case x < -MaxFloat64: // IsInf(x, -1): + return 0 + case x > Overflow: + return Inf(1) + case x < Underflow: + return 0 + case -NearZero < x && x < NearZero: + return 1 + x + } + + // reduce; computed as r = hi - lo for extra precision. + var k int + switch { + case x < 0: + k = int(Log2e*x - 0.5) + case x > 0: + k = int(Log2e*x + 0.5) + } + hi := x - float64(k)*Ln2Hi + lo := float64(k) * Ln2Lo + + // compute + return exp(hi, lo, k) +} + +// Exp2 returns 2**x, the base-2 exponential of x. +// +// Special cases are the same as Exp. +func exp2Go(x float64) float64 { + const ( + Ln2Hi = 6.93147180369123816490e-01 + Ln2Lo = 1.90821492927058770002e-10 + + Overflow = 1.0239999999999999e+03 + Underflow = -1.0740e+03 + ) + + // TODO: remove manual inlining of IsNaN and IsInf + // when compiler does it for us + // special cases + switch { + case x != x || x > MaxFloat64: // IsNaN(x) || IsInf(x, 1): + return x + case x < -MaxFloat64: // IsInf(x, -1): + return 0 + case x > Overflow: + return Inf(1) + case x < Underflow: + return 0 + } + + // argument reduction; x = r×lg(e) + k with |r| ≤ ln(2)/2. + // computed as r = hi - lo for extra precision. + var k int + switch { + case x > 0: + k = int(x + 0.5) + case x < 0: + k = int(x - 0.5) + } + t := x - float64(k) + hi := t * Ln2Hi + lo := -t * Ln2Lo + + // compute + return exp(hi, lo, k) +} + +// exp returns e**r × 2**k where r = hi - lo and |r| ≤ ln(2)/2. +func exp(hi, lo float64, k int) float64 { + const ( + P1 = 1.66666666666666019037e-01 /* 0x3FC55555; 0x5555553E */ + P2 = -2.77777777770155933842e-03 /* 0xBF66C16C; 0x16BEBD93 */ + P3 = 6.61375632143793436117e-05 /* 0x3F11566A; 0xAF25DE2C */ + P4 = -1.65339022054652515390e-06 /* 0xBEBBBD41; 0xC5D26BF1 */ + P5 = 4.13813679705723846039e-08 /* 0x3E663769; 0x72BEA4D0 */ + ) + + r := hi - lo + t := r * r + c := r - t*(P1+t*(P2+t*(P3+t*(P4+t*P5)))) + y := 1 - ((lo - (r*c)/(2-c)) - hi) + // TODO(rsc): make sure Ldexp can handle boundary k + return Ldexp(y, k) +} diff --git a/src/pkg/math/exp_test.go b/src/pkg/math/exp_test.go new file mode 100644 index 000000000..7381fd5ad --- /dev/null +++ b/src/pkg/math/exp_test.go @@ -0,0 +1,10 @@ +// 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 + +// Make expGo and exp2Go available for testing. + +func ExpGo(x float64) float64 { return expGo(x) } +func Exp2Go(x float64) float64 { return exp2Go(x) } diff --git a/src/pkg/math/frexp.go b/src/pkg/math/frexp.go index b63b508e6..203219c0d 100644 --- a/src/pkg/math/frexp.go +++ b/src/pkg/math/frexp.go @@ -19,9 +19,9 @@ func Frexp(f float64) (frac float64, exp int) { return f, 0 } x := Float64bits(f) - exp = int((x>>shift)&mask) - bias + exp = int((x>>shift)&mask) - bias + 1 x &^= mask << shift - x |= bias << shift + x |= (-1 + bias) << shift frac = Float64frombits(x) return } diff --git a/src/pkg/math/hypot_amd64.s b/src/pkg/math/hypot_amd64.s new file mode 100644 index 000000000..1f691e70e --- /dev/null +++ b/src/pkg/math/hypot_amd64.s @@ -0,0 +1,50 @@ +// 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. + +#define PosInf 0x7ff0000000000000 +#define NaN 0x7FF0000000000001 + +// func Hypot(x, y float64) float64 +TEXT ·Hypot(SB),7,$0 + // test bits for special cases + MOVQ x+0(FP), BX + MOVQ $~(1<<63), AX + ANDQ AX, BX // x = |x| + MOVQ y+8(FP), CX + ANDQ AX, CX // y = |y| + MOVQ $PosInf, AX + CMPQ AX, BX + JLE isInfOrNaN + CMPQ AX, CX + JLE isInfOrNaN + // hypot = max * sqrt(1 + (min/max)**2) + MOVQ BX, X0 + MOVQ CX, X1 + ORQ CX, BX + JEQ isZero + MOVAPD X0, X2 + MAXSD X1, X0 + MINSD X2, X1 + DIVSD X0, X1 + MULSD X1, X1 + ADDSD $1.0, X1 + SQRTSD X1, X1 + MULSD X1, X0 + MOVSD X0, r+16(FP) + RET +isInfOrNaN: + CMPQ AX, BX + JEQ isInf + CMPQ AX, CX + JEQ isInf + MOVQ $NaN, AX + MOVQ AX, r+16(FP) // return NaN + RET +isInf: + MOVQ AX, r+16(FP) // return +Inf + RET +isZero: + MOVQ $0, AX + MOVQ AX, r+16(FP) // return 0 + RET diff --git a/src/pkg/math/log.go b/src/pkg/math/log.go index 02e767b95..39d94512d 100644 --- a/src/pkg/math/log.go +++ b/src/pkg/math/log.go @@ -121,11 +121,3 @@ func Log(x float64) float64 { hfsq := 0.5 * f * f return k*Ln2Hi - ((hfsq - (s*(hfsq+R) + k*Ln2Lo)) - f) } - -// Log10 returns the decimal logarithm of x. -// The special cases are the same as for Log. -func Log10(x float64) float64 { return Log(x) * (1 / Ln10) } - -// Log2 returns the binary logarithm of x. -// The special cases are the same as for Log. -func Log2(x float64) float64 { return Log(x) * (1 / Ln2) } diff --git a/src/pkg/math/log10.go b/src/pkg/math/log10.go new file mode 100644 index 000000000..6d18baae2 --- /dev/null +++ b/src/pkg/math/log10.go @@ -0,0 +1,13 @@ +// 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 math + +// Log10 returns the decimal logarithm of x. +// The special cases are the same as for Log. +func Log10(x float64) float64 { return Log(x) * (1 / Ln10) } + +// Log2 returns the binary logarithm of x. +// The special cases are the same as for Log. +func Log2(x float64) float64 { return Log(x) * (1 / Ln2) } diff --git a/src/pkg/math/log10_386.s b/src/pkg/math/log10_386.s new file mode 100644 index 000000000..cc473b424 --- /dev/null +++ b/src/pkg/math/log10_386.s @@ -0,0 +1,19 @@ +// 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 Log10(x float64) float64 +TEXT ·Log10(SB),7,$0 + FLDLG2 // F0=log10(2) + FMOVD x+0(FP), F0 // F0=x, F1=log10(2) + FYL2X // F0=log10(x)=log2(x)*log10(2) + FMOVDP F0, r+8(FP) + RET + +// func Log2(x float64) float64 +TEXT ·Log2(SB),7,$0 + FLD1 // F0=1 + FMOVD x+0(FP), F0 // F0=x, F1=1 + FYL2X // F0=log2(x) + FMOVDP F0, r+8(FP) + RET diff --git a/src/pkg/math/log10_decl.go b/src/pkg/math/log10_decl.go new file mode 100644 index 000000000..5aec94e1c --- /dev/null +++ b/src/pkg/math/log10_decl.go @@ -0,0 +1,8 @@ +// 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 Log10(x float64) float64 +func Log2(x float64) float64 diff --git a/src/pkg/math/log_386.s b/src/pkg/math/log_386.s index ae5211e22..6cfbc7605 100644 --- a/src/pkg/math/log_386.s +++ b/src/pkg/math/log_386.s @@ -9,19 +9,3 @@ TEXT ·Log(SB),7,$0 FYL2X // F0=log(x)=log2(x)*log(2) FMOVDP F0, r+8(FP) RET - -// func Log10(x float64) float64 -TEXT ·Log10(SB),7,$0 - FLDLG2 // F0=log10(2) - FMOVD x+0(FP), F0 // F0=x, F1=log10(2) - FYL2X // F0=log10(x)=log2(x)*log10(2) - FMOVDP F0, r+8(FP) - RET - -// func Log2(x float64) float64 -TEXT ·Log2(SB),7,$0 - FLD1 // F0=1 - FMOVD x+0(FP), F0 // F0=x, F1=1 - FYL2X // F0=log2(x) - FMOVDP F0, r+8(FP) - RET diff --git a/src/pkg/math/log_amd64.s b/src/pkg/math/log_amd64.s new file mode 100644 index 000000000..79e35907c --- /dev/null +++ b/src/pkg/math/log_amd64.s @@ -0,0 +1,109 @@ +// 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. + +#define HSqrt2 7.07106781186547524401e-01 // sqrt(2)/2 +#define Ln2Hi 6.93147180369123816490e-01 // 0x3fe62e42fee00000 +#define Ln2Lo 1.90821492927058770002e-10 // 0x3dea39ef35793c76 +#define L1 6.666666666666735130e-01 // 0x3FE5555555555593 +#define L2 3.999999999940941908e-01 // 0x3FD999999997FA04 +#define L3 2.857142874366239149e-01 // 0x3FD2492494229359 +#define L4 2.222219843214978396e-01 // 0x3FCC71C51D8E78AF +#define L5 1.818357216161805012e-01 // 0x3FC7466496CB03DE +#define L6 1.531383769920937332e-01 // 0x3FC39A09D078C69F +#define L7 1.479819860511658591e-01 // 0x3FC2F112DF3E5244 +#define NaN 0x7FF0000000000001 +#define NegInf 0xFFF0000000000000 +#define PosInf 0x7FF0000000000000 + +// func Log(x float64) float64 +TEXT ·Log(SB),7,$0 + // test bits for special cases + MOVQ x+0(FP), BX + MOVQ $~(1<<63), AX // sign bit mask + ANDQ BX, AX + JEQ isZero + MOVQ $0, AX + CMPQ AX, BX + JGT isNegative + MOVQ $PosInf, AX + CMPQ AX, BX + JLE isInfOrNaN + // f1, ki := math.Frexp(x); k := float64(ki) + MOVQ BX, X0 + MOVQ $0x000FFFFFFFFFFFFF, AX + MOVQ AX, X2 + ANDPD X0, X2 + MOVSD $0.5, X0 // 0x3FE0000000000000 + ORPD X0, X2 // X2= f1 + SHRQ $52, BX + ANDL $0x7FF, BX + SUBL $0x3FE, BX + CVTSL2SD BX, X1 // x1= k, x2= f1 + // if f1 < math.Sqrt2/2 { k -= 1; f1 *= 2 } + MOVSD $HSqrt2, X0 // x0= 0.7071, x1= k, x2= f1 + CMPSD X2, X0, 5 // cmpnlt; x0= 0 or ^0, x1= k, x2 = f1 + MOVSD $1.0, X3 // x0= 0 or ^0, x1= k, x2 = f1, x3= 1 + ANDPD X0, X3 // x0= 0 or ^0, x1= k, x2 = f1, x3= 0 or 1 + SUBSD X3, X1 // x0= 0 or ^0, x1= k, x2 = f1, x3= 0 or 1 + MOVSD $1.0, X0 // x0= 1, x1= k, x2= f1, x3= 0 or 1 + ADDSD X0, X3 // x0= 1, x1= k, x2= f1, x3= 1 or 2 + MULSD X3, X2 // x0= 1, x1= k, x2= f1 + // f := f1 - 1 + SUBSD X0, X2 // x1= k, x2= f + // s := f / (2 + f) + MOVSD $2.0, X0 + ADDSD X2, X0 + MOVSD X2, X3 + DIVSD X0, X3 // x1=k, x2= f, x3= s + // s2 := s * s + MOVSD X3, X4 // x1= k, x2= f, x3= s + MULSD X4, X4 // x1= k, x2= f, x3= s, x4= s2 + // s4 := s2 * s2 + MOVSD X4, X5 // x1= k, x2= f, x3= s, x4= s2 + MULSD X5, X5 // x1= k, x2= f, x3= s, x4= s2, x5= s4 + // t1 := s2 * (L1 + s4*(L3+s4*(L5+s4*L7))) + MOVSD $L7, X6 + MULSD X5, X6 + ADDSD $L5, X6 + MULSD X5, X6 + ADDSD $L3, X6 + MULSD X5, X6 + ADDSD $L1, X6 + MULSD X6, X4 // x1= k, x2= f, x3= s, x4= t1, x5= s4 + // t2 := s4 * (L2 + s4*(L4+s4*L6)) + MOVSD $L6, X6 + MULSD X5, X6 + ADDSD $L4, X6 + MULSD X5, X6 + ADDSD $L2, X6 + MULSD X6, X5 // x1= k, x2= f, x3= s, x4= t1, x5= t2 + // R := t1 + t2 + ADDSD X5, X4 // x1= k, x2= f, x3= s, x4= R + // hfsq := 0.5 * f * f + MOVSD $0.5, X0 + MULSD X2, X0 + MULSD X2, X0 // x0= hfsq, x1= k, x2= f, x3= s, x4= R + // return k*Ln2Hi - ((hfsq - (s*(hfsq+R) + k*Ln2Lo)) - f) + ADDSD X0, X4 // x0= hfsq, x1= k, x2= f, x3= s, x4= hfsq+R + MULSD X4, X3 // x0= hfsq, x1= k, x2= f, x3= s*(hfsq+R) + MOVSD $Ln2Lo, X4 + MULSD X1, X4 // x4= k*Ln2Lo + ADDSD X4, X3 // x0= hfsq, x1= k, x2= f, x3= s*(hfsq+R)+k*Ln2Lo + SUBSD X3, X0 // x0= hfsq-(s*(hfsq+R)+k*Ln2Lo), x1= k, x2= f + SUBSD X2, X0 // x0= (hfsq-(s*(hfsq+R)+k*Ln2Lo))-f, x1= k + MULSD $Ln2Hi, X1 // x0= (hfsq-(s*(hfsq+R)+k*Ln2Lo))-f, x1= k*Ln2Hi + SUBSD X0, X1 // x1= k*Ln2Hi-((hfsq-(s*(hfsq+R)+k*Ln2Lo))-f) + MOVSD X1, r+8(FP) + RET +isInfOrNaN: + MOVQ BX, r+8(FP) // +Inf or NaN, return x + RET +isNegative: + MOVQ $NaN, AX + MOVQ AX, r+8(FP) // return NaN + RET +isZero: + MOVQ $NegInf, AX + MOVQ AX, r+8(FP) // return -Inf + RET diff --git a/src/pkg/math/log_decl.go b/src/pkg/math/log_decl.go index 074b0cdb6..deda305dd 100644 --- a/src/pkg/math/log_decl.go +++ b/src/pkg/math/log_decl.go @@ -5,5 +5,3 @@ package math func Log(x float64) float64 -func Log10(x float64) float64 -func Log2(x float64) float64 diff --git a/src/pkg/math/logb.go b/src/pkg/math/logb.go index acda15d22..9e4651517 100644 --- a/src/pkg/math/logb.go +++ b/src/pkg/math/logb.go @@ -4,7 +4,7 @@ package math -// Logb(x) returns the binary logarithm of non-zero x. +// Logb(x) returns the binary exponent of non-zero x. // // Special cases are: // Logb(±Inf) = +Inf @@ -25,7 +25,7 @@ func Logb(x float64) float64 { return float64(int((Float64bits(x)>>shift)&mask) - bias) } -// Ilogb(x) returns the binary logarithm of non-zero x as an integer. +// Ilogb(x) returns the binary exponent of non-zero x as an integer. // // Special cases are: // Ilogb(±Inf) = MaxInt32 diff --git a/src/pkg/math/modf.go b/src/pkg/math/modf.go index ae0c7c887..315174b70 100644 --- a/src/pkg/math/modf.go +++ b/src/pkg/math/modf.go @@ -23,9 +23,9 @@ func Modf(f float64) (int float64, frac float64) { x := Float64bits(f) e := uint(x>>shift)&mask - bias - // Keep the top 11+e bits, the integer part; clear the rest. - if e < 64-11 { - x &^= 1<<(64-11-e) - 1 + // Keep the top 12+e bits, the integer part; clear the rest. + if e < 64-12 { + x &^= 1<<(64-12-e) - 1 } int = Float64frombits(x) frac = f - int diff --git a/src/pkg/math/sincos_amd64.s b/src/pkg/math/sincos_amd64.s new file mode 100644 index 000000000..18c824e51 --- /dev/null +++ b/src/pkg/math/sincos_amd64.s @@ -0,0 +1,143 @@ +// 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. + +// The method is based on a paper by Naoki Shibata: "Efficient evaluation +// methods of elementary functions suitable for SIMD computation", Proc. +// of International Supercomputing Conference 2010 (ISC'10), pp. 25 -- 32 +// (May 2010). The paper is available at +// http://www.springerlink.com/content/340228x165742104/ +// +// The original code and the constants below are from the author's +// implementation available at http://freshmeat.net/projects/sleef. +// The README file says, "The software is in public domain. +// You can use the software without any obligation." +// +// This code is a simplified version of the original. The CMPSD +// instruction, not generated by the compiler, eliminates jumps in the +// body of the calculation. + +#define PosOne 0x3FF0000000000000 +#define PosInf 0x7FF0000000000000 +#define NaN 0x7FF0000000000001 +#define PI4A 0.7853981554508209228515625 // pi/4 split into three parts +#define PI4B 0.794662735614792836713604629039764404296875e-8 +#define PI4C 0.306161699786838294306516483068750264552437361480769e-16 +#define M4PI 1.273239544735162542821171882678754627704620361328125 // 4/pi +#define T0 1.0 +#define T1 -8.33333333333333333333333e-02 // (-1.0/12) +#define T2 2.77777777777777777777778e-03 // (+1.0/360) +#define T3 -4.96031746031746031746032e-05 // (-1.0/20160) +#define T4 5.51146384479717813051146e-07 // (+1.0/1814400) + +// func Sincos(d float64) (sin, cos float64) +TEXT ·Sincos(SB),7,$0 + // test for special cases + MOVQ $~(1<<63), DX // sign bit mask + MOVQ x+0(FP), BX + ANDQ BX, DX + JEQ isZero + MOVQ $PosInf, AX + CMPQ AX, DX + JLE isInfOrNaN + // Reduce argument + MOVQ BX, X7 // x7= d + MOVQ DX, X0 // x0= |d| + MOVSD $M4PI, X2 + MULSD X0, X2 + CVTTSD2SQ X2, BX // bx= q + MOVQ $1, AX + ANDQ BX, AX + ADDQ BX, AX + CVTSQ2SD AX, X2 + MOVSD $PI4A, X3 + MULSD X2, X3 + SUBSD X3, X0 + MOVSD $PI4B, X3 + MULSD X2, X3 + SUBSD X3, X0 + MOVSD $PI4C, X3 + MULSD X2, X3 + SUBSD X3, X0 + MULSD $0.125, X0 // x0= x, x7= d, bx= q + // Evaluate Taylor series + MULSD X0, X0 + MOVSD $T4, X2 + MULSD X0, X2 + ADDSD $T3, X2 + MULSD X0, X2 + ADDSD $T2, X2 + MULSD X0, X2 + ADDSD $T1, X2 + MULSD X0, X2 + ADDSD $T0, X2 + MULSD X2, X0 // x0= x, x7= d, bx= q + // Apply double angle formula + MOVSD $4.0, X2 + SUBSD X0, X2 + MULSD X2, X0 + MOVSD $4.0, X2 + SUBSD X0, X2 + MULSD X2, X0 + MOVSD $4.0, X2 + SUBSD X0, X2 + MULSD X2, X0 + MULSD $0.5, X0 // x0= x, x7= d, bx= q + // sin = sqrt((2 - x) * x) + MOVSD $2.0, X2 + SUBSD X0, X2 + MULSD X0, X2 + SQRTSD X2, X2 // x0= x, x2= z, x7= d, bx= q + // cos = 1 - x + MOVSD $1.0, X1 + SUBSD X0, X1 // x1= x, x2= z, x7= d, bx= q + // if ((q + 1) & 2) != 0 { sin, cos = cos, sin } + MOVQ $1, DX + ADDQ BX, DX + MOVQ $2, AX + ANDQ AX, DX + MOVQ DX, X0 + MOVSD $0.0, X3 + CMPSD X0, X3, 0 // cmpeq; x1= x, x2= z, x3 = y, x7= d, bx= q + // sin = (y & z) | (^y & x) + MOVAPD X2, X0 + ANDPD X3, X0 // x0= sin + MOVAPD X3, X4 + ANDNPD X1, X4 + ORPD X4, X0 // x0= sin, x1= x, x2= z, x3= y, x7= d, bx= q + // cos = (y & x) | (^y & z) + ANDPD X3, X1 // x1= cos + ANDNPD X2, X3 + ORPD X3, X1 // x0= sin, x1= cos, x7= d, bx= q + // if ((q & 4) != 0) != (d < 0) { sin = -sin } + MOVQ BX, AX + MOVQ $61, CX + SHLQ CX, AX + MOVQ AX, X3 + XORPD X7, X3 + MOVQ $(1<<63), AX + MOVQ AX, X2 // x2= -0.0 + ANDPD X2, X3 + ORPD X3, X0 // x0= sin, x1= cos, x2= -0.0, bx= q + // if ((q + 2) & 4) != 0 { cos = -cos } + MOVQ $2, AX + ADDQ AX, BX + MOVQ $61, CX + SHLQ CX, BX + MOVQ BX, X3 + ANDPD X2, X3 + ORPD X3, X1 // x0= sin, x1= cos + // return (sin, cos) + MOVSD X0, sin+8(FP) + MOVSD X1, cos+16(FP) + RET +isZero: // return (±0.0, 1.0) + MOVQ BX, sin+8(FP) + MOVQ $PosOne, AX + MOVQ AX, cos+16(FP) + RET +isInfOrNaN: // return (NaN, NaN) + MOVQ $NaN, AX + MOVQ AX, sin+8(FP) + MOVQ AX, cos+16(FP) + RET diff --git a/src/pkg/math/sqrt_port.go b/src/pkg/math/sqrt_port.go index 8d821b559..6f35a383d 100644 --- a/src/pkg/math/sqrt_port.go +++ b/src/pkg/math/sqrt_port.go @@ -113,7 +113,7 @@ func sqrtGo(x float64) float64 { } exp++ } - exp -= bias + 1 // unbias exponent + exp -= bias // unbias exponent ix &^= mask << shift ix |= 1 << shift if exp&1 == 1 { // odd exp, double x to make it even @@ -138,6 +138,6 @@ func sqrtGo(x float64) float64 { if ix != 0 { // remainder, result not exact q += q & 1 // round according to extra bit } - ix = q>>1 + uint64(exp+bias)<<shift // significand + biased exponent + ix = q>>1 + uint64(exp-1+bias)<<shift // significand + biased exponent return Float64frombits(ix) } diff --git a/src/pkg/math/tan.go b/src/pkg/math/tan.go index 842ac6438..a36ebbf44 100644 --- a/src/pkg/math/tan.go +++ b/src/pkg/math/tan.go @@ -54,7 +54,7 @@ func Tan(x float64) float64 { if flag { if temp == 0 { - panic(NaN()) + return NaN() } temp = 1 / temp } |