├── .github └── workflows │ └── go.yml ├── .gitignore ├── LICENSE ├── README.md ├── _exp_arm64.s ├── _stubs_risc64.s ├── abs.go ├── acos.go ├── acosh.go ├── all_test.go ├── asin.go ├── asinh.go ├── atan.go ├── atan2.go ├── atanh.go ├── bits.go ├── cbrt.go ├── const.go ├── copysign.go ├── cosh.go ├── dim.go ├── doc.go ├── erf.go ├── erfc.go ├── exp.go ├── exp2_asm.go ├── exp2_noasm.go ├── exp_amd64.s ├── exp_asm.go ├── exp_noasm.go ├── expm1f.go ├── export_test.go ├── floor.go ├── frexp.go ├── gamma.go ├── go.mod ├── hypot.go ├── j0.go ├── j1.go ├── jn.go ├── ldexp.go ├── lgamma.go ├── log.go ├── log10.go ├── log1p.go ├── log2.go ├── log_amd64.s ├── log_asm.go ├── log_noasm.go ├── logb.go ├── math32_test.go ├── mod.go ├── modf.go ├── nextafter.go ├── pow.go ├── remainder.go ├── remainder_amd64.s ├── remainder_asm.go ├── remainder_noasm.go ├── round.go ├── signbit.go ├── sincos.go ├── sinhf.go ├── sqrt.go ├── sqrt_amd64.s ├── sqrt_arm64.s ├── sqrt_asm.go ├── sqrt_noasm.go ├── stubs_386.s ├── stubs_arm.s ├── stubs_arm64.s ├── stubs_ppc64le.s ├── stubs_s390x.s ├── stubs_wasm.s ├── tan.go ├── tanh.go ├── unsafe.go ├── y0.go └── y1.go /.github/workflows/go.yml: -------------------------------------------------------------------------------- 1 | name: Go 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | branches: [ master ] 8 | 9 | jobs: 10 | 11 | build: 12 | runs-on: ubuntu-latest 13 | steps: 14 | - uses: actions/checkout@v3 15 | 16 | - name: Set up Go 17 | uses: actions/setup-go@v3 18 | with: 19 | go-version: 1.18 20 | 21 | - name: Test 22 | run: go test -v ./... 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files, Static and Dynamic libs (Shared Objects) 2 | *.o 3 | *.a 4 | *.so 5 | 6 | # Folders 7 | _obj 8 | _test 9 | 10 | # Architecture specific extensions/prefixes 11 | *.[568vq] 12 | [568vq].out 13 | 14 | *.cgo1.go 15 | *.cgo2.c 16 | _cgo_defun.c 17 | _cgo_gotypes.go 18 | _cgo_export.* 19 | 20 | _testmain.go 21 | 22 | *.exe 23 | *.test 24 | *.prof 25 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 2-Clause License 2 | 3 | Copyright (c) 2021, Xuanyi Chew and the Go Authors 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 20 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 23 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # math32 [![GoDoc](https://godoc.org/github.com/chewxy/math32?status.svg)](https://godoc.org/github.com/chewxy/math32) 2 | 3 | A `float32` version of Go's math package. The majority of code in this library is a thin `float32` wrapper over the results of the `math` package that comes in the standard lib. 4 | 5 | 6 | The original code is lifted from the Go standard library which is governed by 7 | a BSD-style licence which can be found here: https://golang.org/LICENSE. 8 | -------------------------------------------------------------------------------- /_exp_arm64.s: -------------------------------------------------------------------------------- 1 | //go:build !tinygo && !noasm 2 | // Copyright 2017 The Go Authors. All rights reserved. 3 | // Use of this source code is governed by a BSD-style 4 | // license that can be found in the LICENSE file. 5 | 6 | #define Ln2Hi 6.9313812256e-01 7 | #define Ln2Lo 9.0580006145e-06 8 | #define Log2e 1.4426950216e+00 9 | #define Overflow 7.097827e+02 10 | #define Underflow -7.451332e+02 11 | #define Overflow2 1.024000e+03 12 | #define Underflow2 -1.0740e+03 13 | #define NearZero 0x317fffff // 2**-28 14 | #define PosInf 0x7f800000 15 | #define FracMask 0x07fffff 16 | #define C1 0x34000000 // 2**-23 17 | #define P1 1.6666667163e-01 // 0x3FC55555; 0x55555555 18 | #define P2 -2.7777778450e-03 // 0xBF66C16C; 0x16BEBD93 19 | #define P3 6.6137559770e-05 // 0x3F11566A; 0xAF25DE2C 20 | #define P4 -1.6533901999e-06 // 0xBEBBBD41; 0xC5D26BF1 21 | #define P5 4.1381369442e-08 // 0x3E663769; 0x72BEA4D0 22 | 23 | // Exp returns e**x, the base-e exponential of x. 24 | // This is an assembly implementation of the method used for function Exp in file exp.go. 25 | // 26 | // func archExp(x float32) float32 27 | TEXT ·archExp(SB),$0-12 28 | FMOVS x+0(FP), F0 // F0 = x 29 | FCMPS F0, F0 30 | BNE isNaN // x = NaN, return NaN 31 | FMOVS $Overflow, F1 32 | FCMPS F1, F0 33 | BGT overflow // x > Overflow, return PosInf 34 | FMOVS $Underflow, F1 35 | FCMPS F1, F0 36 | BLT underflow // x < Underflow, return 0 37 | MOVW $NearZero, R0 38 | FMOVS R0, F2 39 | FABSS F0, F3 40 | FMOVS $1.0, F1 // F1 = 1.0 41 | FCMPS F2, F3 42 | BLT nearzero // fabs(x) < NearZero, return 1 + x 43 | // argument reduction, x = k*ln2 + r, |r| <= 0.5*ln2 44 | // computed as r = hi - lo for extra precision. 45 | FMOVS $Log2e, F2 46 | FMOVS $0.5, F3 47 | FNMSUBS F0, F3, F2, F4 // Log2e*x - 0.5 48 | FMADDS F0, F3, F2, F3 // Log2e*x + 0.5 49 | FCMPS $0.0, F0 50 | FCSELS LT, F4, F3, F3 // F3 = k 51 | FCVTZSS F3, R1 // R1 = int(k) 52 | SCVTFS R1, F3 // F3 = float32(int(k)) 53 | FMOVS $Ln2Hi, F4 // F4 = Ln2Hi 54 | FMOVS $Ln2Lo, F5 // F5 = Ln2Lo 55 | FMSUBS F3, F0, F4, F4 // F4 = hi = x - float32(int(k))*Ln2Hi 56 | FMULS F3, F5 // F5 = lo = float32(int(k)) * Ln2Lo 57 | FSUBS F5, F4, F6 // F6 = r = hi - lo 58 | FMULS F6, F6, F7 // F7 = t = r * r 59 | // compute y 60 | FMOVS $P5, F8 // F8 = P5 61 | FMOVS $P4, F9 // F9 = P4 62 | FMADDS F7, F9, F8, F13 // P4+t*P5 63 | FMOVS $P3, F10 // F10 = P3 64 | FMADDS F7, F10, F13, F13 // P3+t*(P4+t*P5) 65 | FMOVS $P2, F11 // F11 = P2 66 | FMADDS F7, F11, F13, F13 // P2+t*(P3+t*(P4+t*P5)) 67 | FMOVS $P1, F12 // F12 = P1 68 | FMADDS F7, F12, F13, F13 // P1+t*(P2+t*(P3+t*(P4+t*P5))) 69 | FMSUBS F7, F6, F13, F13 // F13 = c = r - t*(P1+t*(P2+t*(P3+t*(P4+t*P5)))) 70 | FMOVS $2.0, F14 71 | FSUBS F13, F14 72 | FMULS F6, F13, F15 73 | FDIVS F14, F15 // F15 = (r*c)/(2-c) 74 | FSUBS F15, F5, F15 // lo-(r*c)/(2-c) 75 | FSUBS F4, F15, F15 // (lo-(r*c)/(2-c))-hi 76 | FSUBS F15, F1, F16 // F16 = y = 1-((lo-(r*c)/(2-c))-hi) 77 | // inline Ldexp(y, k), benefit: 78 | // 1, no parameter pass overhead. 79 | // 2, skip unnecessary checks for Inf/NaN/Zero 80 | FMOVS F16, R0 81 | ANDS $FracMask, R0, R2 // fraction 82 | LSRW $23, R0, R5 // exponent 83 | ADDS R1, R5 // R1 = int(k) 84 | CMPW $1, R5 85 | BGE normal 86 | ADDS $23, R5 // denormal 87 | MOVW $C1, R8 88 | FMOVS R8, F1 // m = 2**-23 89 | normal: 90 | ORRW R5<<23, R2, R0 91 | FMOVS R0, F0 92 | FMULS F1, F0 // return m * x 93 | FMOVS F0, ret+8(FP) 94 | RET 95 | nearzero: 96 | FADDS F1, F0 97 | isNaN: 98 | FMOVS F0, ret+8(FP) 99 | RET 100 | underflow: 101 | MOVW ZR, ret+8(FP) 102 | RET 103 | overflow: 104 | MOVW $PosInf, R0 105 | MOVW R0, ret+8(FP) 106 | RET 107 | 108 | 109 | // Exp2 returns 2**x, the base-2 exponential of x. 110 | // This is an assembly implementation of the method used for function Exp2 in file exp.go. 111 | // 112 | // func archExp2(x float32) float32 113 | TEXT ·archExp2(SB),$0-12 // Is this correct? 114 | FMOVS x+0(FP), F0 // F0 = x 115 | FCMPS F0, F0 116 | BNE isNaN // x = NaN, return NaN 117 | FMOVS $Overflow2, F1 118 | FCMPS F1, F0 119 | BGT overflow // x > Overflow, return PosInf 120 | FMOVS $Underflow2, F1 121 | FCMPS F1, F0 122 | BLT underflow // x < Underflow, return 0 123 | // argument reduction; x = r*lg(e) + k with |r| <= ln(2)/2 124 | // computed as r = hi - lo for extra precision. 125 | FMOVS $0.5, F2 126 | FSUBS F2, F0, F3 // x + 0.5 127 | FADDS F2, F0, F4 // x - 0.5 128 | FCMPS $0.0, F0 129 | FCSELS LT, F3, F4, F3 // F3 = k 130 | FCVTZSS F3, R1 // R1 = int(k) 131 | SCVTFS R1, F3 // F3 = float32(int(k)) 132 | FSUBS F3, F0, F3 // t = x - float32(int(k)) 133 | FMOVS $Ln2Hi, F4 // F4 = Ln2Hi 134 | FMOVS $Ln2Lo, F5 // F5 = Ln2Lo 135 | FMULS F3, F4 // F4 = hi = t * Ln2Hi 136 | FNMULS F3, F5 // F5 = lo = -t * Ln2Lo 137 | FSUBS F5, F4, F6 // F6 = r = hi - lo 138 | FMULS F6, F6, F7 // F7 = t = r * r 139 | // compute y 140 | FMOVS $P5, F8 // F8 = P5 141 | FMOVS $P4, F9 // F9 = P4 142 | FMADDS F7, F9, F8, F13 // P4+t*P5 143 | FMOVS $P3, F10 // F10 = P3 144 | FMADDS F7, F10, F13, F13 // P3+t*(P4+t*P5) 145 | FMOVS $P2, F11 // F11 = P2 146 | FMADDS F7, F11, F13, F13 // P2+t*(P3+t*(P4+t*P5)) 147 | FMOVS $P1, F12 // F12 = P1 148 | FMADDS F7, F12, F13, F13 // P1+t*(P2+t*(P3+t*(P4+t*P5))) 149 | FMSUBS F7, F6, F13, F13 // F13 = c = r - t*(P1+t*(P2+t*(P3+t*(P4+t*P5)))) 150 | FMOVS $2.0, F14 151 | FSUBS F13, F14 152 | FMULS F6, F13, F15 153 | FDIVS F14, F15 // F15 = (r*c)/(2-c) 154 | FMOVS $1.0, F1 // F1 = 1.0 155 | FSUBS F15, F5, F15 // lo-(r*c)/(2-c) 156 | FSUBS F4, F15, F15 // (lo-(r*c)/(2-c))-hi 157 | FSUBS F15, F1, F16 // F16 = y = 1-((lo-(r*c)/(2-c))-hi) 158 | // inline Ldexp(y, k), benefit: 159 | // 1, no parameter pass overhead. 160 | // 2, skip unnecessary checks for Inf/NaN/Zero 161 | FMOVS F16, R0 162 | ANDS $FracMask, R0, R2 // fraction 163 | LSRW $23, R0, R5 // exponent 164 | ADDS R1, R5 // R1 = int(k) 165 | CMPW $1, R5 166 | BGE normal 167 | ADDS $23, R5 // denormal 168 | MOVW $C1, R8 169 | FMOVS R8, F1 // m = 2**-52 170 | normal: 171 | ORRW R5<<23, R2, R0 172 | FMOVS R0, F0 173 | FMULS F1, F0 // return m * x 174 | isNaN: 175 | FMOVS F0, ret+8(FP) 176 | RET 177 | underflow: 178 | MOVW ZR, ret+8(FP) 179 | RET 180 | overflow: 181 | MOVW $PosInf, R0 182 | MOVW R0, ret+8(FP) 183 | RET 184 | -------------------------------------------------------------------------------- /_stubs_risc64.s: -------------------------------------------------------------------------------- 1 | //go:build !tinygo && !noasm 2 | #include "textflag.h" 3 | 4 | // func archExp(x float32) float32 5 | TEXT ·archExp(SB),NOSPLIT,$0 6 | B ·exp(SB) 7 | 8 | // func archExp2(x float32) float32 9 | TEXT ·archExp2(SB),NOSPLIT,$0 10 | B ·exp2(SB) 11 | 12 | // func archLog(x float32) float32 13 | TEXT ·archLog(SB),NOSPLIT,$0 14 | B ·log(SB) 15 | 16 | // func archRemainder(x, y float32) float32 17 | TEXT ·archRemainder(SB),NOSPLIT,$0 18 | B ·remainder(SB) 19 | 20 | // func archSqrt(x float32) float32 21 | TEXT ·archSqrt(SB),NOSPLIT,$0 22 | B ·sqrt(SB) 23 | -------------------------------------------------------------------------------- /abs.go: -------------------------------------------------------------------------------- 1 | package math32 2 | 3 | // Abs returns the absolute value of x. 4 | // 5 | // Special cases are: 6 | // 7 | // Abs(±Inf) = +Inf 8 | // Abs(NaN) = NaN 9 | func Abs(x float32) float32 { 10 | return Float32frombits(Float32bits(x) &^ signMask) 11 | } 12 | -------------------------------------------------------------------------------- /acos.go: -------------------------------------------------------------------------------- 1 | package math32 2 | 3 | // Acos returns the arccosine, in radians, of x. 4 | // 5 | // Special case is: 6 | // 7 | // Acos(x) = NaN if x < -1 or x > 1 8 | func Acos(x float32) float32 { 9 | return Pi/2 - Asin(x) 10 | } 11 | -------------------------------------------------------------------------------- /acosh.go: -------------------------------------------------------------------------------- 1 | package math32 2 | 3 | // The original C code, the long comment, and the constants 4 | // below are from FreeBSD's /usr/src/lib/msun/src/e_acosh.c 5 | // and came with this notice. The go code is a simplified 6 | // version of the original C. 7 | // 8 | // ==================================================== 9 | // Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. 10 | // 11 | // Developed at SunPro, a Sun Microsystems, Inc. business. 12 | // Permission to use, copy, modify, and distribute this 13 | // software is freely granted, provided that this notice 14 | // is preserved. 15 | // ==================================================== 16 | // 17 | // 18 | // __ieee754_acosh(x) 19 | // Method : 20 | // Based on 21 | // acosh(x) = log [ x + sqrt(x*x-1) ] 22 | // we have 23 | // acosh(x) := log(x)+ln2, if x is large; else 24 | // acosh(x) := log(2x-1/(sqrt(x*x-1)+x)) if x>2; else 25 | // acosh(x) := log1p(t+sqrt(2.0*t+t*t)); where t=x-1. 26 | // 27 | // Special cases: 28 | // acosh(x) is NaN with signal if x<1. 29 | // acosh(NaN) is NaN without signal. 30 | // 31 | 32 | // Acosh returns the inverse hyperbolic cosine of x. 33 | // 34 | // Special cases are: 35 | // 36 | // Acosh(+Inf) = +Inf 37 | // Acosh(x) = NaN if x < 1 38 | // Acosh(NaN) = NaN 39 | func Acosh(x float32) float32 { 40 | const Large = 1 << 28 // 2**28 41 | // first case is special case 42 | switch { 43 | case x < 1 || IsNaN(x): 44 | return NaN() 45 | case x == 1: 46 | return 0 47 | case x >= Large: 48 | return Log(x) + Ln2 // x > 2**28 49 | case x > 2: 50 | return Log(2*x - 1./(x+Sqrt(x*x-1))) // 2**28 > x > 2 51 | } 52 | t := x - 1 53 | return Log1p(t + Sqrt(2*t+t*t)) // 2 >= x > 1 54 | } 55 | -------------------------------------------------------------------------------- /all_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2009 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package math32_test 6 | 7 | import ( 8 | "fmt" 9 | "testing" 10 | 11 | . "github.com/chewxy/math32" 12 | ) 13 | 14 | var vf = []float32{ 15 | 4.9790119248836735e+00, 16 | 7.7388724745781045e+00, 17 | -2.7688005719200159e-01, 18 | -5.0106036182710749e+00, 19 | 9.6362937071984173e+00, 20 | 2.9263772392439646e+00, 21 | 5.2290834314593066e+00, 22 | 2.7279399104360102e+00, 23 | 1.8253080916808550e+00, 24 | -8.6859247685756013e+00, 25 | } 26 | 27 | // The expected results below were computed by the high precision calculators 28 | // at http://keisan.casio.com/. More exact input values (array vf[], above) 29 | // were obtained by printing them with "%.26f". The answers were calculated 30 | // to 26 digits (by using the "Digit number" drop-down control of each 31 | // calculator). 32 | var acos = []float32{ 33 | 1.0496193546107222142571536e+00, 34 | 6.8584012813664425171660692e-01, 35 | 1.5984878714577160325521819e+00, 36 | 2.0956199361475859327461799e+00, 37 | 2.7053008467824138592616927e-01, 38 | 1.2738121680361776018155625e+00, 39 | 1.0205369421140629186287407e+00, 40 | 1.2945003481781246062157835e+00, 41 | 1.3872364345374451433846657e+00, 42 | 2.6231510803970463967294145e+00, 43 | } 44 | var acosh = []float32{ 45 | 2.4743347004159012494457618e+00, 46 | 2.8576385344292769649802701e+00, 47 | 7.2796961502981066190593175e-01, 48 | 2.4796794418831451156471977e+00, 49 | 3.0552020742306061857212962e+00, 50 | 2.044238592688586588942468e+00, 51 | 2.5158701513104513595766636e+00, 52 | 1.99050839282411638174299e+00, 53 | 1.6988625798424034227205445e+00, 54 | 2.9611454842470387925531875e+00, 55 | } 56 | var asin = []float32{ 57 | 5.2117697218417440497416805e-01, 58 | 8.8495619865825236751471477e-01, 59 | -02.769154466281941332086016e-02, 60 | -5.2482360935268931351485822e-01, 61 | 1.3002662421166552333051524e+00, 62 | 2.9698415875871901741575922e-01, 63 | 5.5025938468083370060258102e-01, 64 | 2.7629597861677201301553823e-01, 65 | 1.83559892257451475846656e-01, 66 | -1.0523547536021497774980928e+00, 67 | } 68 | var asinh = []float32{ 69 | 2.3083139124923523427628243e+00, 70 | 2.743551594301593620039021e+00, 71 | -2.7345908534880091229413487e-01, 72 | -2.3145157644718338650499085e+00, 73 | 2.9613652154015058521951083e+00, 74 | 1.7949041616585821933067568e+00, 75 | 2.3564032905983506405561554e+00, 76 | 1.7287118790768438878045346e+00, 77 | 1.3626658083714826013073193e+00, 78 | -2.8581483626513914445234004e+00, 79 | } 80 | var atan = []float32{ 81 | 1.372590262129621651920085e+00, 82 | 1.442290609645298083020664e+00, 83 | -2.7011324359471758245192595e-01, 84 | -1.3738077684543379452781531e+00, 85 | 1.4673921193587666049154681e+00, 86 | 1.2415173565870168649117764e+00, 87 | 1.3818396865615168979966498e+00, 88 | 1.2194305844639670701091426e+00, 89 | 1.0696031952318783760193244e+00, 90 | -1.4561721938838084990898679e+00, 91 | } 92 | var atanh = []float32{ 93 | 5.4651163712251938116878204e-01, 94 | 1.0299474112843111224914709e+00, 95 | -2.7695084420740135145234906e-02, 96 | -5.5072096119207195480202529e-01, 97 | 1.9943940993171843235906642e+00, 98 | 3.01448604578089708203017e-01, 99 | 5.8033427206942188834370595e-01, 100 | 2.7987997499441511013958297e-01, 101 | 1.8459947964298794318714228e-01, 102 | -1.3273186910532645867272502e+00, 103 | } 104 | var atan2 = []float32{ 105 | 1.1088291730037004444527075e+00, 106 | 9.1218183188715804018797795e-01, 107 | 1.5984772603216203736068915e+00, 108 | 2.0352918654092086637227327e+00, 109 | 8.0391819139044720267356014e-01, 110 | 1.2861075249894661588866752e+00, 111 | 1.0889904479131695712182587e+00, 112 | 1.3044821793397925293797357e+00, 113 | 1.3902530903455392306872261e+00, 114 | 2.2859857424479142655411058e+00, 115 | } 116 | var cbrt = []float32{ 117 | 1.7075799841925094446722675e+00, 118 | 1.9779982212970353936691498e+00, 119 | -6.5177429017779910853339447e-01, 120 | -1.7111838886544019873338113e+00, 121 | 2.1279920909827937423960472e+00, 122 | 1.4303536770460741452312367e+00, 123 | 1.7357021059106154902341052e+00, 124 | 1.3972633462554328350552916e+00, 125 | 1.2221149580905388454977636e+00, 126 | -2.0556003730500069110343596e+00, 127 | } 128 | var ceil = []float32{ 129 | 5.0000000000000000e+00, 130 | 8.0000000000000000e+00, 131 | 0.0000000000000000e+00, 132 | -5.0000000000000000e+00, 133 | 1.0000000000000000e+01, 134 | 3.0000000000000000e+00, 135 | 6.0000000000000000e+00, 136 | 3.0000000000000000e+00, 137 | 2.0000000000000000e+00, 138 | -8.0000000000000000e+00, 139 | } 140 | var copysign = []float32{ 141 | -4.9790119248836735e+00, 142 | -7.7388724745781045e+00, 143 | -2.7688005719200159e-01, 144 | -5.0106036182710749e+00, 145 | -9.6362937071984173e+00, 146 | -2.9263772392439646e+00, 147 | -5.2290834314593066e+00, 148 | -2.7279399104360102e+00, 149 | -1.8253080916808550e+00, 150 | -8.6859247685756013e+00, 151 | } 152 | var cos = []float32{ 153 | 2.634752140995199110787593e-01, 154 | 1.148551260848219865642039e-01, 155 | 9.6191297325640768154550453e-01, 156 | 2.938141150061714816890637e-01, 157 | -9.777138189897924126294461e-01, 158 | -9.7693041344303219127199518e-01, 159 | 4.940088096948647263961162e-01, 160 | -9.1565869021018925545016502e-01, 161 | -2.517729313893103197176091e-01, 162 | -7.39241351595676573201918e-01, 163 | } 164 | 165 | // Results for 100000 * Pi + vf[i] 166 | var cosLarge = []float32{ 167 | 2.634752141185559426744e-01, 168 | 1.14855126055543100712e-01, 169 | 9.61912973266488928113e-01, 170 | 2.9381411499556122552e-01, 171 | -9.777138189880161924641e-01, 172 | -9.76930413445147608049e-01, 173 | 4.940088097314976789841e-01, 174 | -9.15658690217517835002e-01, 175 | -2.51772931436786954751e-01, 176 | -7.3924135157173099849e-01, 177 | } 178 | var cosh = []float32{ 179 | 7.2668796942212842775517446e+01, 180 | 1.1479413465659254502011135e+03, 181 | 1.0385767908766418550935495e+00, 182 | 7.5000957789658051428857788e+01, 183 | 7.655246669605357888468613e+03, 184 | 9.3567491758321272072888257e+00, 185 | 9.331351599270605471131735e+01, 186 | 7.6833430994624643209296404e+00, 187 | 3.1829371625150718153881164e+00, 188 | 2.9595059261916188501640911e+03, 189 | } 190 | var erf = []float32{ 191 | 5.1865354817738701906913566e-01, 192 | 7.2623875834137295116929844e-01, 193 | -3.123458688281309990629839e-02, 194 | -5.2143121110253302920437013e-01, 195 | 8.2704742671312902508629582e-01, 196 | 3.2101767558376376743993945e-01, 197 | 5.403990312223245516066252e-01, 198 | 3.0034702916738588551174831e-01, 199 | 2.0369924417882241241559589e-01, 200 | -7.8069386968009226729944677e-01, 201 | } 202 | var erfc = []float32{ 203 | 4.8134645182261298093086434e-01, 204 | 2.7376124165862704883070156e-01, 205 | 1.0312345868828130999062984e+00, 206 | 1.5214312111025330292043701e+00, 207 | 1.7295257328687097491370418e-01, 208 | 6.7898232441623623256006055e-01, 209 | 4.596009687776754483933748e-01, 210 | 6.9965297083261411448825169e-01, 211 | 7.9630075582117758758440411e-01, 212 | 1.7806938696800922672994468e+00, 213 | } 214 | var exp = []float32{ 215 | 1.4533071302642137507696589e+02, 216 | 2.2958822575694449002537581e+03, 217 | 7.5814542574851666582042306e-01, 218 | 6.6668778421791005061482264e-03, 219 | 1.5310493273896033740861206e+04, 220 | 1.8659907517999328638667732e+01, 221 | 1.8662167355098714543942057e+02, 222 | 1.5301332413189378961665788e+01, 223 | 6.2047063430646876349125085e+00, 224 | 1.6894712385826521111610438e-04, 225 | } 226 | var expm1 = []float32{ 227 | 5.105047796122957327384770212e-02, 228 | 8.046199708567344080562675439e-02, 229 | -2.764970978891639815187418703e-03, 230 | -4.8871434888875355394330300273e-02, 231 | 1.0115864277221467777117227494e-01, 232 | 2.969616407795910726014621657e-02, 233 | 5.368214487944892300914037972e-02, 234 | 2.765488851131274068067445335e-02, 235 | 1.842068661871398836913874273e-02, 236 | -8.3193870863553801814961137573e-02, 237 | } 238 | var expm1Large = []float32{ 239 | 4.2031418113550844e+21, 240 | 4.0690789717473863e+33, 241 | -0.9372627915981363e+00, 242 | -1.0, 243 | Inf(1), // NOTE: this was changed to fit float32 244 | 5.117936223839153e+12, 245 | 5.124137759001189e+22, 246 | 7.03546003972584e+11, 247 | 8.456921800389698e+07, 248 | -1.0, 249 | } 250 | var exp2 = []float32{ 251 | 3.1537839463286288034313104e+01, 252 | 2.1361549283756232296144849e+02, 253 | 8.2537402562185562902577219e-01, 254 | 3.1021158628740294833424229e-02, 255 | 7.9581744110252191462569661e+02, 256 | 7.6019905892596359262696423e+00, 257 | 3.7506882048388096973183084e+01, 258 | 6.6250893439173561733216375e+00, 259 | 3.5438267900243941544605339e+00, 260 | 2.4281533133513300984289196e-03, 261 | } 262 | var fabs = []float32{ 263 | 4.9790119248836735e+00, 264 | 7.7388724745781045e+00, 265 | 2.7688005719200159e-01, 266 | 5.0106036182710749e+00, 267 | 9.6362937071984173e+00, 268 | 2.9263772392439646e+00, 269 | 5.2290834314593066e+00, 270 | 2.7279399104360102e+00, 271 | 1.8253080916808550e+00, 272 | 8.6859247685756013e+00, 273 | } 274 | var fdim = []float32{ 275 | 4.9790119248836735e+00, 276 | 7.7388724745781045e+00, 277 | 0.0000000000000000e+00, 278 | 0.0000000000000000e+00, 279 | 9.6362937071984173e+00, 280 | 2.9263772392439646e+00, 281 | 5.2290834314593066e+00, 282 | 2.7279399104360102e+00, 283 | 1.8253080916808550e+00, 284 | 0.0000000000000000e+00, 285 | } 286 | var floor = []float32{ 287 | 4.0000000000000000e+00, 288 | 7.0000000000000000e+00, 289 | -1.0000000000000000e+00, 290 | -6.0000000000000000e+00, 291 | 9.0000000000000000e+00, 292 | 2.0000000000000000e+00, 293 | 5.0000000000000000e+00, 294 | 2.0000000000000000e+00, 295 | 1.0000000000000000e+00, 296 | -9.0000000000000000e+00, 297 | } 298 | var fmod = []float32{ 299 | 4.197615023265299782906368e-02, 300 | 2.261127525421895434476482e+00, 301 | 3.231794108794261433104108e-02, 302 | 4.989396381728925078391512e+00, 303 | 3.637062928015826201999516e-01, 304 | 1.220868282268106064236690e+00, 305 | 4.770916568540693347699744e+00, 306 | 1.816180268691969246219742e+00, 307 | 8.734595415957246977711748e-01, 308 | 1.314075231424398637614104e+00, 309 | } 310 | 311 | type fi struct { 312 | f float32 313 | i int 314 | } 315 | 316 | var frexp = []fi{ 317 | {6.2237649061045918750e-01, 3}, 318 | {9.6735905932226306250e-01, 3}, 319 | {-5.5376011438400318000e-01, -1}, 320 | {-6.2632545228388436250e-01, 3}, 321 | {6.02268356699901081250e-01, 4}, 322 | {7.3159430981099115000e-01, 2}, 323 | {6.5363542893241332500e-01, 3}, 324 | {6.8198497760900255000e-01, 2}, 325 | {9.1265404584042750000e-01, 1}, 326 | {-5.4287029803597508250e-01, 4}, 327 | } 328 | var gamma = []float32{ 329 | 2.3254348370739963835386613898e+01, 330 | 2.991153837155317076427529816e+03, 331 | -4.561154336726758060575129109e+00, 332 | 7.719403468842639065959210984e-01, 333 | 1.6111876618855418534325755566e+05, 334 | 1.8706575145216421164173224946e+00, 335 | 3.4082787447257502836734201635e+01, 336 | 1.579733951448952054898583387e+00, 337 | 9.3834586598354592860187267089e-01, 338 | -2.093995902923148389186189429e-05, 339 | } 340 | var j0 = []float32{ 341 | -1.8444682230601672018219338e-01, 342 | 2.27353668906331975435892e-01, 343 | 9.809259936157051116270273e-01, 344 | -1.741170131426226587841181e-01, 345 | -2.1389448451144143352039069e-01, 346 | -2.340905848928038763337414e-01, 347 | -1.0029099691890912094586326e-01, 348 | -1.5466726714884328135358907e-01, 349 | 3.252650187653420388714693e-01, 350 | -8.72218484409407250005360235e-03, 351 | } 352 | var j1 = []float32{ 353 | -3.251526395295203422162967e-01, 354 | 1.893581711430515718062564e-01, 355 | -1.3711761352467242914491514e-01, 356 | 3.287486536269617297529617e-01, 357 | 1.3133899188830978473849215e-01, 358 | 3.660243417832986825301766e-01, 359 | -3.4436769271848174665420672e-01, 360 | 4.329481396640773768835036e-01, 361 | 5.8181350531954794639333955e-01, 362 | -2.7030574577733036112996607e-01, 363 | } 364 | var j2 = []float32{ 365 | 5.3837518920137802565192769e-02, 366 | -1.7841678003393207281244667e-01, 367 | 9.521746934916464142495821e-03, 368 | 4.28958355470987397983072e-02, 369 | 2.4115371837854494725492872e-01, 370 | 4.842458532394520316844449e-01, 371 | -3.142145220618633390125946e-02, 372 | 4.720849184745124761189957e-01, 373 | 3.122312022520957042957497e-01, 374 | 7.096213118930231185707277e-02, 375 | } 376 | var jM3 = []float32{ 377 | -3.684042080996403091021151e-01, 378 | 2.8157665936340887268092661e-01, 379 | 4.401005480841948348343589e-04, 380 | 3.629926999056814081597135e-01, 381 | 3.123672198825455192489266e-02, 382 | -2.958805510589623607540455e-01, 383 | -3.2033177696533233403289416e-01, 384 | -2.592737332129663376736604e-01, 385 | -1.0241334641061485092351251e-01, 386 | -2.3762660886100206491674503e-01, 387 | } 388 | var lgamma = []fi{ 389 | {3.146492141244545774319734e+00, 1}, 390 | {8.003414490659126375852113e+00, 1}, 391 | {1.517575735509779707488106e+00, -1}, 392 | {-2.588480028182145853558748e-01, 1}, 393 | {1.1989897050205555002007985e+01, 1}, 394 | {6.262899811091257519386906e-01, 1}, 395 | {3.5287924899091566764846037e+00, 1}, 396 | {4.5725644770161182299423372e-01, 1}, 397 | {-6.363667087767961257654854e-02, 1}, 398 | {-1.077385130910300066425564e+01, -1}, 399 | } 400 | var log = []float32{ 401 | 1.605231462693062999102599e+00, 402 | 2.0462560018708770653153909e+00, 403 | -1.2841708730962657801275038e+00, 404 | 1.6115563905281545116286206e+00, 405 | 2.2655365644872016636317461e+00, 406 | 1.0737652208918379856272735e+00, 407 | 1.6542360106073546632707956e+00, 408 | 1.0035467127723465801264487e+00, 409 | 6.0174879014578057187016475e-01, 410 | 2.161703872847352815363655e+00, 411 | } 412 | var logb = []float32{ 413 | 2.0000000000000000e+00, 414 | 2.0000000000000000e+00, 415 | -2.0000000000000000e+00, 416 | 2.0000000000000000e+00, 417 | 3.0000000000000000e+00, 418 | 1.0000000000000000e+00, 419 | 2.0000000000000000e+00, 420 | 1.0000000000000000e+00, 421 | 0.0000000000000000e+00, 422 | 3.0000000000000000e+00, 423 | } 424 | var log10 = []float32{ 425 | 6.9714316642508290997617083e-01, 426 | 8.886776901739320576279124e-01, 427 | -5.5770832400658929815908236e-01, 428 | 6.998900476822994346229723e-01, 429 | 9.8391002850684232013281033e-01, 430 | 4.6633031029295153334285302e-01, 431 | 7.1842557117242328821552533e-01, 432 | 4.3583479968917773161304553e-01, 433 | 2.6133617905227038228626834e-01, 434 | 9.3881606348649405716214241e-01, 435 | } 436 | var log1p = []float32{ 437 | 4.8590257759797794104158205e-02, 438 | 7.4540265965225865330849141e-02, 439 | -2.7726407903942672823234024e-03, 440 | -5.1404917651627649094953380e-02, 441 | 9.1998280672258624681335010e-02, 442 | 2.8843762576593352865894824e-02, 443 | 5.0969534581863707268992645e-02, 444 | 2.6913947602193238458458594e-02, 445 | 1.8088493239630770262045333e-02, 446 | -9.0865245631588989681559268e-02, 447 | } 448 | var log2 = []float32{ 449 | 2.3158594707062190618898251e+00, 450 | 2.9521233862883917703341018e+00, 451 | -1.8526669502700329984917062e+00, 452 | 2.3249844127278861543568029e+00, 453 | 3.268478366538305087466309e+00, 454 | 1.5491157592596970278166492e+00, 455 | 2.3865580889631732407886495e+00, 456 | 1.447811865817085365540347e+00, 457 | 8.6813999540425116282815557e-01, 458 | 3.118679457227342224364709e+00, 459 | } 460 | var modf = [][2]float32{ 461 | {4.0000000000000000e+00, 9.7901192488367350108546816e-01}, 462 | {7.0000000000000000e+00, 7.3887247457810456552351752e-01}, 463 | {Copysign(0, -1), -2.7688005719200159404635997e-01}, 464 | {-5.0000000000000000e+00, -1.060361827107492160848778e-02}, 465 | {9.0000000000000000e+00, 6.3629370719841737980004837e-01}, 466 | {2.0000000000000000e+00, 9.2637723924396464525443662e-01}, 467 | {5.0000000000000000e+00, 2.2908343145930665230025625e-01}, 468 | {2.0000000000000000e+00, 7.2793991043601025126008608e-01}, 469 | {1.0000000000000000e+00, 8.2530809168085506044576505e-01}, 470 | {-8.0000000000000000e+00, -6.8592476857560136238589621e-01}, 471 | } 472 | var nextafter32 = []float32{ 473 | 4.979012489318848e+00, 474 | 7.738873004913330e+00, 475 | -2.768800258636475e-01, 476 | -5.010602951049805e+00, 477 | 9.636294364929199e+00, 478 | 2.926377534866333e+00, 479 | 5.229084014892578e+00, 480 | 2.727940082550049e+00, 481 | 1.825308203697205e+00, 482 | -8.685923576354980e+00, 483 | } 484 | 485 | var pow = []float32{ 486 | 9.5282232631648411840742957e+04, 487 | 5.4811599352999901232411871e+07, 488 | 5.2859121715894396531132279e-01, 489 | 9.7587991957286474464259698e-06, 490 | 4.328064329346044846740467e+09, 491 | 8.4406761805034547437659092e+02, 492 | 1.6946633276191194947742146e+05, 493 | 5.3449040147551939075312879e+02, 494 | 6.688182138451414936380374e+01, 495 | 2.0609869004248742886827439e-09, 496 | } 497 | var remainder = []float32{ 498 | 4.197615023265299782906368e-02, 499 | 2.261127525421895434476482e+00, 500 | 3.231794108794261433104108e-02, 501 | -2.120723654214984321697556e-02, 502 | 3.637062928015826201999516e-01, 503 | 1.220868282268106064236690e+00, 504 | -4.581668629186133046005125e-01, 505 | -9.117596417440410050403443e-01, 506 | 8.734595415957246977711748e-01, 507 | 1.314075231424398637614104e+00, 508 | } 509 | var signbit = []bool{ 510 | false, 511 | false, 512 | true, 513 | true, 514 | false, 515 | false, 516 | false, 517 | false, 518 | false, 519 | true, 520 | } 521 | var sin = []float32{ 522 | -9.6466616586009283766724726e-01, 523 | 9.9338225271646545763467022e-01, 524 | -2.7335587039794393342449301e-01, 525 | 9.5586257685042792878173752e-01, 526 | -2.099421066779969164496634e-01, 527 | 2.135578780799860532750616e-01, 528 | -8.694568971167362743327708e-01, 529 | 4.019566681155577786649878e-01, 530 | 9.6778633541687993721617774e-01, 531 | -6.734405869050344734943028e-01, 532 | } 533 | 534 | // Results for 100000 * Pi + vf[i] 535 | var sinLarge = []float32{ 536 | -9.646661658548936063912e-01, 537 | 9.933822527198506903752e-01, 538 | -2.7335587036246899796e-01, 539 | 9.55862576853689321268e-01, 540 | -2.099421066862688873691e-01, 541 | 2.13557878070308981163e-01, 542 | -8.694568970959221300497e-01, 543 | 4.01956668098863248917e-01, 544 | 9.67786335404528727927e-01, 545 | -6.7344058693131973066e-01, 546 | } 547 | var sinh = []float32{ 548 | 7.2661916084208532301448439e+01, 549 | 1.1479409110035194500526446e+03, 550 | -2.8043136512812518927312641e-01, 551 | -7.499429091181587232835164e+01, 552 | 7.6552466042906758523925934e+03, 553 | 9.3031583421672014313789064e+00, 554 | 9.330815755828109072810322e+01, 555 | 7.6179893137269146407361477e+00, 556 | 3.021769180549615819524392e+00, 557 | -2.95950575724449499189888e+03, 558 | } 559 | var sqrt = []float32{ 560 | 2.2313699659365484748756904e+00, 561 | 2.7818829009464263511285458e+00, 562 | 5.2619393496314796848143251e-01, 563 | 2.2384377628763938724244104e+00, 564 | 3.1042380236055381099288487e+00, 565 | 1.7106657298385224403917771e+00, 566 | 2.286718922705479046148059e+00, 567 | 1.6516476350711159636222979e+00, 568 | 1.3510396336454586262419247e+00, 569 | 2.9471892997524949215723329e+00, 570 | } 571 | var tan = []float32{ 572 | -3.661316565040227801781974e+00, 573 | 8.64900232648597589369854e+00, 574 | -2.8417941955033612725238097e-01, 575 | 3.253290185974728640827156e+00, 576 | 2.147275640380293804770778e-01, 577 | -2.18600910711067004921551e-01, 578 | -1.760002817872367935518928e+00, 579 | -4.389808914752818126249079e-01, 580 | -3.843885560201130679995041e+00, 581 | 9.10988793377685105753416e-01, 582 | } 583 | 584 | // Results for 100000 * Pi + vf[i] 585 | var tanLarge = []float32{ 586 | -3.66131656475596512705e+00, 587 | 8.6490023287202547927e+00, 588 | -2.841794195104782406e-01, 589 | 3.2532901861033120983e+00, 590 | 2.14727564046880001365e-01, 591 | -2.18600910700688062874e-01, 592 | -1.760002817699722747043e+00, 593 | -4.38980891453536115952e-01, 594 | -3.84388555942723509071e+00, 595 | 9.1098879344275101051e-01, 596 | } 597 | var tanh = []float32{ 598 | 9.9990531206936338549262119e-01, 599 | 9.9999962057085294197613294e-01, 600 | -2.7001505097318677233756845e-01, 601 | -9.9991110943061718603541401e-01, 602 | 9.9999999146798465745022007e-01, 603 | 9.9427249436125236705001048e-01, 604 | 9.9994257600983138572705076e-01, 605 | 9.9149409509772875982054701e-01, 606 | 9.4936501296239685514466577e-01, 607 | -9.9999994291374030946055701e-01, 608 | } 609 | var trunc = []float32{ 610 | 4.0000000000000000e+00, 611 | 7.0000000000000000e+00, 612 | -0.0000000000000000e+00, 613 | -5.0000000000000000e+00, 614 | 9.0000000000000000e+00, 615 | 2.0000000000000000e+00, 616 | 5.0000000000000000e+00, 617 | 2.0000000000000000e+00, 618 | 1.0000000000000000e+00, 619 | -8.0000000000000000e+00, 620 | } 621 | var y0 = []float32{ 622 | -3.053399153780788357534855e-01, 623 | 1.7437227649515231515503649e-01, 624 | -8.6221781263678836910392572e-01, 625 | -3.100664880987498407872839e-01, 626 | 1.422200649300982280645377e-01, 627 | 4.000004067997901144239363e-01, 628 | -3.3340749753099352392332536e-01, 629 | 4.5399790746668954555205502e-01, 630 | 4.8290004112497761007536522e-01, 631 | 2.7036697826604756229601611e-01, 632 | } 633 | var y1 = []float32{ 634 | 0.15494213737457922210218611, 635 | -0.2165955142081145245075746, 636 | -2.4644949631241895201032829, 637 | 0.1442740489541836405154505, 638 | 0.2215379960518984777080163, 639 | 0.3038800915160754150565448, 640 | 0.0691107642452362383808547, 641 | 0.2380116417809914424860165, 642 | -0.20849492979459761009678934, 643 | 0.0242503179793232308250804, 644 | } 645 | var y2 = []float32{ 646 | 0.3675780219390303613394936, 647 | -0.23034826393250119879267257, 648 | -16.939677983817727205631397, 649 | 0.367653980523052152867791, 650 | -0.0962401471767804440353136, 651 | -0.1923169356184851105200523, 652 | 0.35984072054267882391843766, 653 | -0.2794987252299739821654982, 654 | -0.7113490692587462579757954, 655 | -0.2647831587821263302087457, 656 | } 657 | var yM3 = []float32{ 658 | -0.14035984421094849100895341, 659 | -0.097535139617792072703973, 660 | 242.25775994555580176377379, 661 | -0.1492267014802818619511046, 662 | 0.26148702629155918694500469, 663 | 0.56675383593895176530394248, 664 | -0.206150264009006981070575, 665 | 0.64784284687568332737963658, 666 | 1.3503631555901938037008443, 667 | 0.1461869756579956803341844, 668 | } 669 | 670 | // arguments and expected results for special cases 671 | var vfacosSC = []float32{ 672 | -Pi, 673 | 1, 674 | Pi, 675 | NaN(), 676 | } 677 | var acosSC = []float32{ 678 | NaN(), 679 | 0, 680 | NaN(), 681 | NaN(), 682 | } 683 | 684 | var vfacoshSC = []float32{ 685 | Inf(-1), 686 | 0.5, 687 | 1, 688 | Inf(1), 689 | NaN(), 690 | } 691 | var acoshSC = []float32{ 692 | NaN(), 693 | NaN(), 694 | 0, 695 | Inf(1), 696 | NaN(), 697 | } 698 | 699 | var vfasinSC = []float32{ 700 | -Pi, 701 | Copysign(0, -1), 702 | 0, 703 | Pi, 704 | NaN(), 705 | } 706 | var asinSC = []float32{ 707 | NaN(), 708 | Copysign(0, -1), 709 | 0, 710 | NaN(), 711 | NaN(), 712 | } 713 | 714 | var vfasinhSC = []float32{ 715 | Inf(-1), 716 | Copysign(0, -1), 717 | 0, 718 | Inf(1), 719 | NaN(), 720 | } 721 | var asinhSC = []float32{ 722 | Inf(-1), 723 | Copysign(0, -1), 724 | 0, 725 | Inf(1), 726 | NaN(), 727 | } 728 | 729 | var vfatanSC = []float32{ 730 | Inf(-1), 731 | Copysign(0, -1), 732 | 0, 733 | Inf(1), 734 | NaN(), 735 | } 736 | var atanSC = []float32{ 737 | -Pi / 2, 738 | Copysign(0, -1), 739 | 0, 740 | Pi / 2, 741 | NaN(), 742 | } 743 | 744 | var vfatanhSC = []float32{ 745 | Inf(-1), 746 | -Pi, 747 | -1, 748 | Copysign(0, -1), 749 | 0, 750 | 1, 751 | Pi, 752 | Inf(1), 753 | NaN(), 754 | } 755 | var atanhSC = []float32{ 756 | NaN(), 757 | NaN(), 758 | Inf(-1), 759 | Copysign(0, -1), 760 | 0, 761 | Inf(1), 762 | NaN(), 763 | NaN(), 764 | NaN(), 765 | } 766 | var vfatan2SC = [][2]float32{ 767 | {Inf(-1), Inf(-1)}, 768 | {Inf(-1), -Pi}, 769 | {Inf(-1), 0}, 770 | {Inf(-1), +Pi}, 771 | {Inf(-1), Inf(1)}, 772 | {Inf(-1), NaN()}, 773 | {-Pi, Inf(-1)}, 774 | {-Pi, 0}, 775 | {-Pi, Inf(1)}, 776 | {-Pi, NaN()}, 777 | {Copysign(0, -1), Inf(-1)}, 778 | {Copysign(0, -1), -Pi}, 779 | {Copysign(0, -1), Copysign(0, -1)}, 780 | {Copysign(0, -1), 0}, 781 | {Copysign(0, -1), +Pi}, 782 | {Copysign(0, -1), Inf(1)}, 783 | {Copysign(0, -1), NaN()}, 784 | {0, Inf(-1)}, 785 | {0, -Pi}, 786 | {0, Copysign(0, -1)}, 787 | {0, 0}, 788 | {0, +Pi}, 789 | {0, Inf(1)}, 790 | {0, NaN()}, 791 | {+Pi, Inf(-1)}, 792 | {+Pi, 0}, 793 | {+Pi, Inf(1)}, 794 | {+Pi, NaN()}, 795 | {Inf(1), Inf(-1)}, 796 | {Inf(1), -Pi}, 797 | {Inf(1), 0}, 798 | {Inf(1), +Pi}, 799 | {Inf(1), Inf(1)}, 800 | {Inf(1), NaN()}, 801 | {NaN(), NaN()}, 802 | } 803 | var atan2SC = []float32{ 804 | -3 * Pi / 4, // atan2(-Inf, -Inf) 805 | -Pi / 2, // atan2(-Inf, -Pi) 806 | -Pi / 2, // atan2(-Inf, +0) 807 | -Pi / 2, // atan2(-Inf, +Pi) 808 | -Pi / 4, // atan2(-Inf, +Inf) 809 | NaN(), // atan2(-Inf, NaN) 810 | -Pi, // atan2(-Pi, -Inf) 811 | -Pi / 2, // atan2(-Pi, +0) 812 | Copysign(0, -1), // atan2(-Pi, Inf) 813 | NaN(), // atan2(-Pi, NaN) 814 | -Pi, // atan2(-0, -Inf) 815 | -Pi, // atan2(-0, -Pi) 816 | -Pi, // atan2(-0, -0) 817 | Copysign(0, -1), // atan2(-0, +0) 818 | Copysign(0, -1), // atan2(-0, +Pi) 819 | Copysign(0, -1), // atan2(-0, +Inf) 820 | NaN(), // atan2(-0, NaN) 821 | Pi, // atan2(+0, -Inf) 822 | Pi, // atan2(+0, -Pi) 823 | Pi, // atan2(+0, -0) 824 | 0, // atan2(+0, +0) 825 | 0, // atan2(+0, +Pi) 826 | 0, // atan2(+0, +Inf) 827 | NaN(), // atan2(+0, NaN) 828 | Pi, // atan2(+Pi, -Inf) 829 | Pi / 2, // atan2(+Pi, +0) 830 | 0, // atan2(+Pi, +Inf) 831 | NaN(), // atan2(+Pi, NaN) 832 | 3 * Pi / 4, // atan2(+Inf, -Inf) 833 | Pi / 2, // atan2(+Inf, -Pi) 834 | Pi / 2, // atan2(+Inf, +0) 835 | Pi / 2, // atan2(+Inf, +Pi) 836 | Pi / 4, // atan2(+Inf, +Inf) 837 | NaN(), // atan2(+Inf, NaN) 838 | NaN(), // atan2(NaN, NaN) 839 | } 840 | 841 | var vfcbrtSC = []float32{ 842 | Inf(-1), 843 | Copysign(0, -1), 844 | 0, 845 | Inf(1), 846 | NaN(), 847 | } 848 | var cbrtSC = []float32{ 849 | Inf(-1), 850 | Copysign(0, -1), 851 | 0, 852 | Inf(1), 853 | NaN(), 854 | } 855 | 856 | var vfceilSC = []float32{ 857 | Inf(-1), 858 | Copysign(0, -1), 859 | 0, 860 | Inf(1), 861 | NaN(), 862 | } 863 | var ceilSC = []float32{ 864 | Inf(-1), 865 | Copysign(0, -1), 866 | 0, 867 | Inf(1), 868 | NaN(), 869 | } 870 | 871 | var vfcopysignSC = []float32{ 872 | Inf(-1), 873 | Inf(1), 874 | NaN(), 875 | } 876 | var copysignSC = []float32{ 877 | Inf(-1), 878 | Inf(-1), 879 | NaN(), 880 | } 881 | 882 | var vfcosSC = []float32{ 883 | Inf(-1), 884 | Inf(1), 885 | NaN(), 886 | } 887 | var cosSC = []float32{ 888 | NaN(), 889 | NaN(), 890 | NaN(), 891 | } 892 | 893 | var vfcoshSC = []float32{ 894 | Inf(-1), 895 | Copysign(0, -1), 896 | 0, 897 | Inf(1), 898 | NaN(), 899 | } 900 | var coshSC = []float32{ 901 | Inf(1), 902 | 1, 903 | 1, 904 | Inf(1), 905 | NaN(), 906 | } 907 | 908 | var vferfSC = []float32{ 909 | Inf(-1), 910 | Copysign(0, -1), 911 | 0, 912 | Inf(1), 913 | NaN(), 914 | } 915 | var erfSC = []float32{ 916 | -1, 917 | Copysign(0, -1), 918 | 0, 919 | 1, 920 | NaN(), 921 | } 922 | 923 | var vferfcSC = []float32{ 924 | Inf(-1), 925 | Inf(1), 926 | NaN(), 927 | } 928 | var erfcSC = []float32{ 929 | 2, 930 | 0, 931 | NaN(), 932 | } 933 | 934 | var vfexpSC = []float32{ 935 | Inf(-1), 936 | -2000, 937 | 2000, 938 | Inf(1), 939 | NaN(), 940 | } 941 | var expSC = []float32{ 942 | 0, 943 | 0, 944 | Inf(1), 945 | Inf(1), 946 | NaN(), 947 | } 948 | 949 | var vfexpm1SC = []float32{ 950 | Inf(-1), 951 | -710, 952 | Copysign(0, -1), 953 | 0, 954 | 710, 955 | Inf(1), 956 | NaN(), 957 | } 958 | var expm1SC = []float32{ 959 | -1, 960 | -1, 961 | Copysign(0, -1), 962 | 0, 963 | Inf(1), 964 | Inf(1), 965 | NaN(), 966 | } 967 | 968 | var vffabsSC = []float32{ 969 | Inf(-1), 970 | Copysign(0, -1), 971 | 0, 972 | Inf(1), 973 | NaN(), 974 | } 975 | var fabsSC = []float32{ 976 | Inf(1), 977 | 0, 978 | 0, 979 | Inf(1), 980 | NaN(), 981 | } 982 | 983 | var vffdimSC = [][2]float32{ 984 | {Inf(-1), Inf(-1)}, 985 | {Inf(-1), Inf(1)}, 986 | {Inf(-1), NaN()}, 987 | {Copysign(0, -1), Copysign(0, -1)}, 988 | {Copysign(0, -1), 0}, 989 | {0, Copysign(0, -1)}, 990 | {0, 0}, 991 | {Inf(1), Inf(-1)}, 992 | {Inf(1), Inf(1)}, 993 | {Inf(1), NaN()}, 994 | {NaN(), Inf(-1)}, 995 | {NaN(), Copysign(0, -1)}, 996 | {NaN(), 0}, 997 | {NaN(), Inf(1)}, 998 | {NaN(), NaN()}, 999 | } 1000 | var nan = Float32frombits(0x7FF80001) // SSE2 DIVSD 0/0 1001 | var vffdim2SC = [][2]float32{ 1002 | {Inf(-1), Inf(-1)}, 1003 | {Inf(-1), Inf(1)}, 1004 | {Inf(-1), nan}, 1005 | {Copysign(0, -1), Copysign(0, -1)}, 1006 | {Copysign(0, -1), 0}, 1007 | {0, Copysign(0, -1)}, 1008 | {0, 0}, 1009 | {Inf(1), Inf(-1)}, 1010 | {Inf(1), Inf(1)}, 1011 | {Inf(1), nan}, 1012 | {nan, Inf(-1)}, 1013 | {nan, Copysign(0, -1)}, 1014 | {nan, 0}, 1015 | {nan, Inf(1)}, 1016 | {nan, nan}, 1017 | } 1018 | var fdimSC = []float32{ 1019 | NaN(), 1020 | 0, 1021 | NaN(), 1022 | 0, 1023 | 0, 1024 | 0, 1025 | 0, 1026 | Inf(1), 1027 | NaN(), 1028 | NaN(), 1029 | NaN(), 1030 | NaN(), 1031 | NaN(), 1032 | NaN(), 1033 | NaN(), 1034 | } 1035 | var fmaxSC = []float32{ 1036 | Inf(-1), 1037 | Inf(1), 1038 | NaN(), 1039 | Copysign(0, -1), 1040 | 0, 1041 | 0, 1042 | 0, 1043 | Inf(1), 1044 | Inf(1), 1045 | Inf(1), 1046 | NaN(), 1047 | NaN(), 1048 | NaN(), 1049 | Inf(1), 1050 | NaN(), 1051 | } 1052 | var fminSC = []float32{ 1053 | Inf(-1), 1054 | Inf(-1), 1055 | Inf(-1), 1056 | Copysign(0, -1), 1057 | Copysign(0, -1), 1058 | Copysign(0, -1), 1059 | 0, 1060 | Inf(-1), 1061 | Inf(1), 1062 | NaN(), 1063 | Inf(-1), 1064 | NaN(), 1065 | NaN(), 1066 | NaN(), 1067 | NaN(), 1068 | } 1069 | 1070 | var vffmodSC = [][2]float32{ 1071 | {Inf(-1), Inf(-1)}, 1072 | {Inf(-1), -Pi}, 1073 | {Inf(-1), 0}, 1074 | {Inf(-1), Pi}, 1075 | {Inf(-1), Inf(1)}, 1076 | {Inf(-1), NaN()}, 1077 | {-Pi, Inf(-1)}, 1078 | {-Pi, 0}, 1079 | {-Pi, Inf(1)}, 1080 | {-Pi, NaN()}, 1081 | {Copysign(0, -1), Inf(-1)}, 1082 | {Copysign(0, -1), 0}, 1083 | {Copysign(0, -1), Inf(1)}, 1084 | {Copysign(0, -1), NaN()}, 1085 | {0, Inf(-1)}, 1086 | {0, 0}, 1087 | {0, Inf(1)}, 1088 | {0, NaN()}, 1089 | {Pi, Inf(-1)}, 1090 | {Pi, 0}, 1091 | {Pi, Inf(1)}, 1092 | {Pi, NaN()}, 1093 | {Inf(1), Inf(-1)}, 1094 | {Inf(1), -Pi}, 1095 | {Inf(1), 0}, 1096 | {Inf(1), Pi}, 1097 | {Inf(1), Inf(1)}, 1098 | {Inf(1), NaN()}, 1099 | {NaN(), Inf(-1)}, 1100 | {NaN(), -Pi}, 1101 | {NaN(), 0}, 1102 | {NaN(), Pi}, 1103 | {NaN(), Inf(1)}, 1104 | {NaN(), NaN()}, 1105 | } 1106 | var fmodSC = []float32{ 1107 | NaN(), // fmod(-Inf, -Inf) 1108 | NaN(), // fmod(-Inf, -Pi) 1109 | NaN(), // fmod(-Inf, 0) 1110 | NaN(), // fmod(-Inf, Pi) 1111 | NaN(), // fmod(-Inf, +Inf) 1112 | NaN(), // fmod(-Inf, NaN) 1113 | -Pi, // fmod(-Pi, -Inf) 1114 | NaN(), // fmod(-Pi, 0) 1115 | -Pi, // fmod(-Pi, +Inf) 1116 | NaN(), // fmod(-Pi, NaN) 1117 | Copysign(0, -1), // fmod(-0, -Inf) 1118 | NaN(), // fmod(-0, 0) 1119 | Copysign(0, -1), // fmod(-0, Inf) 1120 | NaN(), // fmod(-0, NaN) 1121 | 0, // fmod(0, -Inf) 1122 | NaN(), // fmod(0, 0) 1123 | 0, // fmod(0, +Inf) 1124 | NaN(), // fmod(0, NaN) 1125 | Pi, // fmod(Pi, -Inf) 1126 | NaN(), // fmod(Pi, 0) 1127 | Pi, // fmod(Pi, +Inf) 1128 | NaN(), // fmod(Pi, NaN) 1129 | NaN(), // fmod(+Inf, -Inf) 1130 | NaN(), // fmod(+Inf, -Pi) 1131 | NaN(), // fmod(+Inf, 0) 1132 | NaN(), // fmod(+Inf, Pi) 1133 | NaN(), // fmod(+Inf, +Inf) 1134 | NaN(), // fmod(+Inf, NaN) 1135 | NaN(), // fmod(NaN, -Inf) 1136 | NaN(), // fmod(NaN, -Pi) 1137 | NaN(), // fmod(NaN, 0) 1138 | NaN(), // fmod(NaN, Pi) 1139 | NaN(), // fmod(NaN, +Inf) 1140 | NaN(), // fmod(NaN, NaN) 1141 | } 1142 | 1143 | var vffrexpSC = []float32{ 1144 | Inf(-1), 1145 | Copysign(0, -1), 1146 | 0, 1147 | Inf(1), 1148 | NaN(), 1149 | } 1150 | var frexpSC = []fi{ 1151 | {Inf(-1), 0}, 1152 | {Copysign(0, -1), 0}, 1153 | {0, 0}, 1154 | {Inf(1), 0}, 1155 | {NaN(), 0}, 1156 | } 1157 | 1158 | var vfgammaSC = []float32{ 1159 | Inf(-1), 1160 | -3, 1161 | Copysign(0, -1), 1162 | 0, 1163 | Inf(1), 1164 | NaN(), 1165 | } 1166 | var gammaSC = []float32{ 1167 | NaN(), 1168 | NaN(), 1169 | Inf(-1), 1170 | Inf(1), 1171 | Inf(1), 1172 | NaN(), 1173 | } 1174 | 1175 | var vfhypotSC = [][2]float32{ 1176 | {Inf(-1), Inf(-1)}, 1177 | {Inf(-1), 0}, 1178 | {Inf(-1), Inf(1)}, 1179 | {Inf(-1), NaN()}, 1180 | {Copysign(0, -1), Copysign(0, -1)}, 1181 | {Copysign(0, -1), 0}, 1182 | {0, Copysign(0, -1)}, 1183 | {0, 0}, // +0, +0 1184 | {0, Inf(-1)}, 1185 | {0, Inf(1)}, 1186 | {0, NaN()}, 1187 | {Inf(1), Inf(-1)}, 1188 | {Inf(1), 0}, 1189 | {Inf(1), Inf(1)}, 1190 | {Inf(1), NaN()}, 1191 | {NaN(), Inf(-1)}, 1192 | {NaN(), 0}, 1193 | {NaN(), Inf(1)}, 1194 | {NaN(), NaN()}, 1195 | } 1196 | var hypotSC = []float32{ 1197 | Inf(1), 1198 | Inf(1), 1199 | Inf(1), 1200 | Inf(1), 1201 | 0, 1202 | 0, 1203 | 0, 1204 | 0, 1205 | Inf(1), 1206 | Inf(1), 1207 | NaN(), 1208 | Inf(1), 1209 | Inf(1), 1210 | Inf(1), 1211 | Inf(1), 1212 | Inf(1), 1213 | NaN(), 1214 | Inf(1), 1215 | NaN(), 1216 | } 1217 | 1218 | var ilogbSC = []int{ 1219 | MaxInt32, 1220 | MinInt32, 1221 | MaxInt32, 1222 | MaxInt32, 1223 | } 1224 | 1225 | var vfj0SC = []float32{ 1226 | Inf(-1), 1227 | 0, 1228 | Inf(1), 1229 | NaN(), 1230 | } 1231 | var j0SC = []float32{ 1232 | 0, 1233 | 1, 1234 | 0, 1235 | NaN(), 1236 | } 1237 | var j1SC = []float32{ 1238 | 0, 1239 | 0, 1240 | 0, 1241 | NaN(), 1242 | } 1243 | var j2SC = []float32{ 1244 | 0, 1245 | 0, 1246 | 0, 1247 | NaN(), 1248 | } 1249 | var jM3SC = []float32{ 1250 | 0, 1251 | 0, 1252 | 0, 1253 | NaN(), 1254 | } 1255 | 1256 | var vfldexpSC = []fi{ 1257 | {0, 0}, 1258 | {0, -1075}, 1259 | {0, 1024}, 1260 | {Copysign(0, -1), 0}, 1261 | {Copysign(0, -1), -1075}, 1262 | {Copysign(0, -1), 1024}, 1263 | {Inf(1), 0}, 1264 | {Inf(1), -1024}, 1265 | {Inf(-1), 0}, 1266 | {Inf(-1), -1024}, 1267 | {NaN(), -1024}, 1268 | } 1269 | var ldexpSC = []float32{ 1270 | 0, 1271 | 0, 1272 | 0, 1273 | Copysign(0, -1), 1274 | Copysign(0, -1), 1275 | Copysign(0, -1), 1276 | Inf(1), 1277 | Inf(1), 1278 | Inf(-1), 1279 | Inf(-1), 1280 | NaN(), 1281 | } 1282 | 1283 | var vflgammaSC = []float32{ 1284 | Inf(-1), 1285 | -3, 1286 | 0, 1287 | 1, 1288 | 2, 1289 | Inf(1), 1290 | NaN(), 1291 | } 1292 | var lgammaSC = []fi{ 1293 | {Inf(-1), 1}, 1294 | {Inf(1), 1}, 1295 | {Inf(1), 1}, 1296 | {0, 1}, 1297 | {0, 1}, 1298 | {Inf(1), 1}, 1299 | {NaN(), 1}, 1300 | } 1301 | 1302 | var vflogSC = []float32{ 1303 | Inf(-1), 1304 | -Pi, 1305 | Copysign(0, -1), 1306 | 0, 1307 | 1, 1308 | Inf(1), 1309 | NaN(), 1310 | } 1311 | var logSC = []float32{ 1312 | NaN(), 1313 | NaN(), 1314 | Inf(-1), 1315 | Inf(-1), 1316 | 0, 1317 | Inf(1), 1318 | NaN(), 1319 | } 1320 | 1321 | var vflogbSC = []float32{ 1322 | Inf(-1), 1323 | 0, 1324 | Inf(1), 1325 | NaN(), 1326 | } 1327 | var logbSC = []float32{ 1328 | Inf(1), 1329 | Inf(-1), 1330 | Inf(1), 1331 | NaN(), 1332 | } 1333 | 1334 | var vflog1pSC = []float32{ 1335 | Inf(-1), 1336 | -Pi, 1337 | -1, 1338 | Copysign(0, -1), 1339 | 0, 1340 | Inf(1), 1341 | NaN(), 1342 | } 1343 | var log1pSC = []float32{ 1344 | NaN(), 1345 | NaN(), 1346 | Inf(-1), 1347 | Copysign(0, -1), 1348 | 0, 1349 | Inf(1), 1350 | NaN(), 1351 | } 1352 | 1353 | var vfmodfSC = []float32{ 1354 | Inf(-1), 1355 | Copysign(0, -1), 1356 | Inf(1), 1357 | NaN(), 1358 | } 1359 | var modfSC = [][2]float32{ 1360 | {Inf(-1), NaN()}, // [2]float32{Copysign(0, -1), Inf(-1)}, 1361 | {Copysign(0, -1), Copysign(0, -1)}, 1362 | {Inf(1), NaN()}, // [2]float32{0, Inf(1)}, 1363 | {NaN(), NaN()}, 1364 | } 1365 | 1366 | var vfnextafter32SC = [][2]float32{ 1367 | {0, 0}, 1368 | {0, float32(Copysign(0, -1))}, 1369 | {0, -1}, 1370 | {0, float32(NaN())}, 1371 | {float32(Copysign(0, -1)), 1}, 1372 | {float32(Copysign(0, -1)), 0}, 1373 | {float32(Copysign(0, -1)), float32(Copysign(0, -1))}, 1374 | {float32(Copysign(0, -1)), -1}, 1375 | {float32(NaN()), 0}, 1376 | {float32(NaN()), float32(NaN())}, 1377 | } 1378 | var nextafter32SC = []float32{ 1379 | 0, 1380 | 0, 1381 | -1.401298464e-45, // Float32frombits(0x80000001) 1382 | float32(NaN()), 1383 | 1.401298464e-45, // Float32frombits(0x00000001) 1384 | float32(Copysign(0, -1)), 1385 | float32(Copysign(0, -1)), 1386 | -1.401298464e-45, // Float32frombits(0x80000001) 1387 | float32(NaN()), 1388 | float32(NaN()), 1389 | } 1390 | 1391 | var vfpowSC = [][2]float32{ 1392 | {Inf(-1), -Pi}, 1393 | {Inf(-1), -3}, 1394 | {Inf(-1), Copysign(0, -1)}, 1395 | {Inf(-1), 0}, 1396 | {Inf(-1), 1}, 1397 | {Inf(-1), 3}, 1398 | {Inf(-1), Pi}, 1399 | {Inf(-1), NaN()}, 1400 | 1401 | {-Pi, Inf(-1)}, 1402 | {-Pi, -Pi}, 1403 | {-Pi, Copysign(0, -1)}, 1404 | {-Pi, 0}, 1405 | {-Pi, 1}, 1406 | {-Pi, Pi}, 1407 | {-Pi, Inf(1)}, 1408 | {-Pi, NaN()}, 1409 | 1410 | {-1, Inf(-1)}, 1411 | {-1, Inf(1)}, 1412 | {-1, NaN()}, 1413 | {-1. / 2, Inf(-1)}, 1414 | {-1. / 2, Inf(1)}, 1415 | {Copysign(0, -1), Inf(-1)}, 1416 | {Copysign(0, -1), -Pi}, 1417 | {Copysign(0, -1), -3}, 1418 | {Copysign(0, -1), 3}, 1419 | {Copysign(0, -1), Pi}, 1420 | {Copysign(0, -1), Inf(1)}, 1421 | 1422 | {0, Inf(-1)}, 1423 | {0, -Pi}, 1424 | {0, -3}, 1425 | {0, Copysign(0, -1)}, 1426 | {0, 0}, 1427 | {0, 3}, 1428 | {0, Pi}, 1429 | {0, Inf(1)}, 1430 | {0, NaN()}, 1431 | 1432 | {1. / 2, Inf(-1)}, 1433 | {1. / 2, Inf(1)}, 1434 | {1, Inf(-1)}, 1435 | {1, Inf(1)}, 1436 | {1, NaN()}, 1437 | 1438 | {Pi, Inf(-1)}, 1439 | {Pi, Copysign(0, -1)}, 1440 | {Pi, 0}, 1441 | {Pi, 1}, 1442 | {Pi, Inf(1)}, 1443 | {Pi, NaN()}, 1444 | {Inf(1), -Pi}, 1445 | {Inf(1), Copysign(0, -1)}, 1446 | {Inf(1), 0}, 1447 | {Inf(1), 1}, 1448 | {Inf(1), Pi}, 1449 | {Inf(1), NaN()}, 1450 | {NaN(), -Pi}, 1451 | {NaN(), Copysign(0, -1)}, 1452 | {NaN(), 0}, 1453 | {NaN(), 1}, 1454 | {NaN(), Pi}, 1455 | {NaN(), NaN()}, 1456 | } 1457 | var powSC = []float32{ 1458 | 0, // pow(-Inf, -Pi) 1459 | Copysign(0, -1), // pow(-Inf, -3) 1460 | 1, // pow(-Inf, -0) 1461 | 1, // pow(-Inf, +0) 1462 | Inf(-1), // pow(-Inf, 1) 1463 | Inf(-1), // pow(-Inf, 3) 1464 | Inf(1), // pow(-Inf, Pi) 1465 | NaN(), // pow(-Inf, NaN) 1466 | 0, // pow(-Pi, -Inf) 1467 | NaN(), // pow(-Pi, -Pi) 1468 | 1, // pow(-Pi, -0) 1469 | 1, // pow(-Pi, +0) 1470 | -Pi, // pow(-Pi, 1) 1471 | NaN(), // pow(-Pi, Pi) 1472 | Inf(1), // pow(-Pi, +Inf) 1473 | NaN(), // pow(-Pi, NaN) 1474 | 1, // pow(-1, -Inf) IEEE 754-2008 1475 | 1, // pow(-1, +Inf) IEEE 754-2008 1476 | NaN(), // pow(-1, NaN) 1477 | Inf(1), // pow(-1/2, -Inf) 1478 | 0, // pow(-1/2, +Inf) 1479 | Inf(1), // pow(-0, -Inf) 1480 | Inf(1), // pow(-0, -Pi) 1481 | Inf(-1), // pow(-0, -3) IEEE 754-2008 1482 | Copysign(0, -1), // pow(-0, 3) IEEE 754-2008 1483 | 0, // pow(-0, +Pi) 1484 | 0, // pow(-0, +Inf) 1485 | Inf(1), // pow(+0, -Inf) 1486 | Inf(1), // pow(+0, -Pi) 1487 | Inf(1), // pow(+0, -3) 1488 | 1, // pow(+0, -0) 1489 | 1, // pow(+0, +0) 1490 | 0, // pow(+0, 3) 1491 | 0, // pow(+0, +Pi) 1492 | 0, // pow(+0, +Inf) 1493 | NaN(), // pow(+0, NaN) 1494 | Inf(1), // pow(1/2, -Inf) 1495 | 0, // pow(1/2, +Inf) 1496 | 1, // pow(1, -Inf) IEEE 754-2008 1497 | 1, // pow(1, +Inf) IEEE 754-2008 1498 | 1, // pow(1, NaN) IEEE 754-2008 1499 | 0, // pow(+Pi, -Inf) 1500 | 1, // pow(+Pi, -0) 1501 | 1, // pow(+Pi, +0) 1502 | Pi, // pow(+Pi, 1) 1503 | Inf(1), // pow(+Pi, +Inf) 1504 | NaN(), // pow(+Pi, NaN) 1505 | 0, // pow(+Inf, -Pi) 1506 | 1, // pow(+Inf, -0) 1507 | 1, // pow(+Inf, +0) 1508 | Inf(1), // pow(+Inf, 1) 1509 | Inf(1), // pow(+Inf, Pi) 1510 | NaN(), // pow(+Inf, NaN) 1511 | NaN(), // pow(NaN, -Pi) 1512 | 1, // pow(NaN, -0) 1513 | 1, // pow(NaN, +0) 1514 | NaN(), // pow(NaN, 1) 1515 | NaN(), // pow(NaN, +Pi) 1516 | NaN(), // pow(NaN, NaN) 1517 | } 1518 | 1519 | var vfpow10SC = []int{ 1520 | MinInt32, 1521 | MaxInt32, 1522 | -325, 1523 | 309, 1524 | } 1525 | 1526 | var pow10SC = []float32{ 1527 | 0, // pow10(MinInt32) 1528 | Inf(1), // pow10(MaxInt32) 1529 | 0, // pow10(-325) 1530 | Inf(1), // pow10(309) 1531 | } 1532 | 1533 | var vfsignbitSC = []float32{ 1534 | Inf(-1), 1535 | Copysign(0, -1), 1536 | 0, 1537 | Inf(1), 1538 | NaN(), 1539 | } 1540 | var signbitSC = []bool{ 1541 | true, 1542 | true, 1543 | false, 1544 | false, 1545 | false, 1546 | } 1547 | 1548 | var vfsinSC = []float32{ 1549 | Inf(-1), 1550 | Copysign(0, -1), 1551 | 0, 1552 | Inf(1), 1553 | NaN(), 1554 | } 1555 | var sinSC = []float32{ 1556 | NaN(), 1557 | Copysign(0, -1), 1558 | 0, 1559 | NaN(), 1560 | NaN(), 1561 | } 1562 | 1563 | var vfsinhSC = []float32{ 1564 | Inf(-1), 1565 | Copysign(0, -1), 1566 | 0, 1567 | Inf(1), 1568 | NaN(), 1569 | } 1570 | var sinhSC = []float32{ 1571 | Inf(-1), 1572 | Copysign(0, -1), 1573 | 0, 1574 | Inf(1), 1575 | NaN(), 1576 | } 1577 | 1578 | var vfsqrtSC = []float32{ 1579 | Inf(-1), 1580 | -Pi, 1581 | Copysign(0, -1), 1582 | 0, 1583 | Inf(1), 1584 | NaN(), 1585 | Float32frombits(2), // subnormal; see https://golang.org/issue/13013 1586 | } 1587 | var sqrtSC = []float32{ 1588 | NaN(), 1589 | NaN(), 1590 | Copysign(0, -1), 1591 | 0, 1592 | Inf(1), 1593 | NaN(), 1594 | 5.293955920339377e-23, // Sqrt(float64(Float32frombits(2))) result 1595 | } 1596 | 1597 | var vftanhSC = []float32{ 1598 | Inf(-1), 1599 | Copysign(0, -1), 1600 | 0, 1601 | Inf(1), 1602 | NaN(), 1603 | } 1604 | var tanhSC = []float32{ 1605 | -1, 1606 | Copysign(0, -1), 1607 | 0, 1608 | 1, 1609 | NaN(), 1610 | } 1611 | 1612 | var vfy0SC = []float32{ 1613 | Inf(-1), 1614 | 0, 1615 | Inf(1), 1616 | NaN(), 1617 | } 1618 | var y0SC = []float32{ 1619 | NaN(), 1620 | Inf(-1), 1621 | 0, 1622 | NaN(), 1623 | } 1624 | var y1SC = []float32{ 1625 | NaN(), 1626 | Inf(-1), 1627 | 0, 1628 | NaN(), 1629 | } 1630 | var y2SC = []float32{ 1631 | NaN(), 1632 | Inf(-1), 1633 | 0, 1634 | NaN(), 1635 | } 1636 | var yM3SC = []float32{ 1637 | NaN(), 1638 | Inf(1), 1639 | 0, 1640 | NaN(), 1641 | } 1642 | 1643 | // arguments and expected results for boundary cases 1644 | const ( 1645 | SmallestNormalFloat32 = 1.1754943508222875079687365e-38 // 1/(2**(127-1)) 1646 | LargestSubnormalFloat32 = SmallestNormalFloat32 - SmallestNonzeroFloat32 1647 | ) 1648 | 1649 | var vffrexpBC = []float32{ 1650 | SmallestNormalFloat32, 1651 | LargestSubnormalFloat32, 1652 | SmallestNonzeroFloat32, 1653 | MaxFloat32, 1654 | -SmallestNormalFloat32, 1655 | -LargestSubnormalFloat32, 1656 | -SmallestNonzeroFloat32, 1657 | -MaxFloat32, 1658 | } 1659 | var frexpBC = []fi{ 1660 | {0.5, -125}, 1661 | {0.9999999, -126}, 1662 | {0.5, -148}, 1663 | {0.99999994, 128}, 1664 | {-0.5, -125}, 1665 | {-0.9999999, -126}, 1666 | {-0.5, -148}, 1667 | {-0.99999994, 128}, 1668 | } 1669 | 1670 | var vfldexpBC = []fi{ 1671 | {SmallestNormalFloat32, -23}, 1672 | {LargestSubnormalFloat32, -22}, 1673 | {SmallestNonzeroFloat32, 256}, 1674 | {MaxFloat32, -(127 + 149)}, 1675 | {1, -150}, 1676 | {-1, -150}, 1677 | {1, 128}, 1678 | {-1, 128}, 1679 | } 1680 | var ldexpBC = []float32{ 1681 | SmallestNonzeroFloat32, 1682 | 3e-45, // 2**-148 1683 | 1.6225928e32, // 2**130 1684 | 3e-45, // 2**-127 1685 | 0, 1686 | Copysign(0, -1), 1687 | Inf(1), 1688 | Inf(-1), 1689 | } 1690 | 1691 | var logbBC = []float32{ 1692 | -126, 1693 | -127, 1694 | -149, 1695 | 127, 1696 | -126, 1697 | -127, 1698 | -149, 1699 | 127, 1700 | } 1701 | 1702 | func tolerance(a, b, e float32) bool { 1703 | d := a - b 1704 | if d < 0 { 1705 | d = -d 1706 | } 1707 | 1708 | // note: b is correct (expected) value, a is actual value. 1709 | // make error tolerance a fraction of b, not a. 1710 | if b != 0 { 1711 | e = e * b 1712 | if e < 0 { 1713 | e = -e 1714 | } 1715 | } 1716 | return d < e 1717 | } 1718 | 1719 | // 5e-1 tolerance 1720 | func nearby(a, b float32) bool { return tolerance(a, b, 5e-1) } // for large trig inputs results may be far apart. 1721 | 1722 | // 1e-5 tolerance 1723 | func close(a, b float32) bool { return tolerance(a, b, 1e-5) } // the number gotten from the cfloat standard. Haskell's Linear package uses 1e-6 for floats 1724 | 1725 | // 1e-6 tolerance 1726 | func veryclose(a, b float32) bool { return tolerance(a, b, 1e-6) } // from wiki 1727 | func thisclose(a, b, e float32) bool { return tolerance(a, b, e) } 1728 | func alike(a, b float32) bool { 1729 | switch { 1730 | case IsNaN(a) && IsNaN(b): 1731 | return true 1732 | case a == b: 1733 | return Signbit(a) == Signbit(b) 1734 | } 1735 | return false 1736 | } 1737 | 1738 | func TestNaN(t *testing.T) { 1739 | f64 := NaN() 1740 | if f64 == f64 { 1741 | t.Fatalf("NaN() returns %g, expected NaN", f64) 1742 | } 1743 | f32 := float32(f64) 1744 | if f32 == f32 { 1745 | t.Fatalf("float32(NaN()) is %g, expected NaN", f32) 1746 | } 1747 | } 1748 | 1749 | func TestAcos(t *testing.T) { 1750 | for i := 0; i < len(vf); i++ { 1751 | a := vf[i] / 10 1752 | if f := Acos(a); !close(acos[i], f) { 1753 | t.Errorf("Acos(%g) = %g, want %g", a, f, acos[i]) 1754 | } 1755 | } 1756 | for i := 0; i < len(vfacosSC); i++ { 1757 | if f := Acos(vfacosSC[i]); !alike(acosSC[i], f) { 1758 | t.Errorf("Acos(%g) = %g, want %g", vfacosSC[i], f, acosSC[i]) 1759 | } 1760 | } 1761 | } 1762 | 1763 | func TestAcosh(t *testing.T) { 1764 | for i := 0; i < len(vf); i++ { 1765 | a := 1 + Abs(vf[i]) 1766 | if f := Acosh(a); !veryclose(acosh[i], f) { 1767 | t.Errorf("Acosh(%g) = %g, want %g", a, f, acosh[i]) 1768 | } 1769 | } 1770 | for i := 0; i < len(vfacoshSC); i++ { 1771 | if f := Acosh(vfacoshSC[i]); !alike(acoshSC[i], f) { 1772 | t.Errorf("Acosh(%g) = %g, want %g", vfacoshSC[i], f, acoshSC[i]) 1773 | } 1774 | } 1775 | } 1776 | 1777 | func TestAsin(t *testing.T) { 1778 | for i := 0; i < len(vf); i++ { 1779 | a := vf[i] / 10 1780 | if f := Asin(a); !veryclose(asin[i], f) { 1781 | t.Errorf("Asin(%g) = %g, want %g", a, f, asin[i]) 1782 | } 1783 | } 1784 | for i := 0; i < len(vfasinSC); i++ { 1785 | if f := Asin(vfasinSC[i]); !alike(asinSC[i], f) { 1786 | t.Errorf("Asin(%g) = %g, want %g", vfasinSC[i], f, asinSC[i]) 1787 | } 1788 | } 1789 | } 1790 | 1791 | func TestAsinh(t *testing.T) { 1792 | for i := 0; i < len(vf); i++ { 1793 | if f := Asinh(vf[i]); !veryclose(asinh[i], f) { 1794 | t.Errorf("Asinh(%g) = %g, want %g", vf[i], f, asinh[i]) 1795 | } 1796 | } 1797 | for i := 0; i < len(vfasinhSC); i++ { 1798 | if f := Asinh(vfasinhSC[i]); !alike(asinhSC[i], f) { 1799 | t.Errorf("Asinh(%g) = %g, want %g", vfasinhSC[i], f, asinhSC[i]) 1800 | } 1801 | } 1802 | } 1803 | 1804 | func TestAtan(t *testing.T) { 1805 | for i := 0; i < len(vf); i++ { 1806 | if f := Atan(vf[i]); !veryclose(atan[i], f) { 1807 | t.Errorf("Atan(%g) = %g, want %g", vf[i], f, atan[i]) 1808 | } 1809 | } 1810 | for i := 0; i < len(vfatanSC); i++ { 1811 | if f := Atan(vfatanSC[i]); !alike(atanSC[i], f) { 1812 | t.Errorf("Atan(%g) = %g, want %g", vfatanSC[i], f, atanSC[i]) 1813 | } 1814 | } 1815 | } 1816 | 1817 | func TestAtanh(t *testing.T) { 1818 | for i := 0; i < len(vf); i++ { 1819 | a := vf[i] / 10 1820 | if f := Atanh(a); !veryclose(atanh[i], f) { 1821 | t.Errorf("Atanh(%g) = %g, want %g", a, f, atanh[i]) 1822 | } 1823 | } 1824 | for i := 0; i < len(vfatanhSC); i++ { 1825 | if f := Atanh(vfatanhSC[i]); !alike(atanhSC[i], f) { 1826 | t.Errorf("Atanh(%g) = %g, want %g", vfatanhSC[i], f, atanhSC[i]) 1827 | } 1828 | } 1829 | } 1830 | 1831 | func TestAtan2(t *testing.T) { 1832 | for i := 0; i < len(vf); i++ { 1833 | if f := Atan2(10, vf[i]); !veryclose(atan2[i], f) { 1834 | t.Errorf("Atan2(10, %g) = %g, want %g", vf[i], f, atan2[i]) 1835 | } 1836 | } 1837 | for i := 0; i < len(vfatan2SC); i++ { 1838 | if f := Atan2(vfatan2SC[i][0], vfatan2SC[i][1]); !alike(atan2SC[i], f) { 1839 | t.Errorf("Atan2(%g, %g) = %g, want %g", vfatan2SC[i][0], vfatan2SC[i][1], f, atan2SC[i]) 1840 | } 1841 | } 1842 | } 1843 | 1844 | func TestCbrt(t *testing.T) { 1845 | for i := 0; i < len(vf); i++ { 1846 | if f := Cbrt(vf[i]); !veryclose(cbrt[i], f) { 1847 | t.Errorf("Cbrt(%g) = %g, want %g", vf[i], f, cbrt[i]) 1848 | } 1849 | } 1850 | for i := 0; i < len(vfcbrtSC); i++ { 1851 | if f := Cbrt(vfcbrtSC[i]); !alike(cbrtSC[i], f) { 1852 | t.Errorf("Cbrt(%g) = %g, want %g", vfcbrtSC[i], f, cbrtSC[i]) 1853 | } 1854 | } 1855 | } 1856 | 1857 | func TestCeil(t *testing.T) { 1858 | for i := 0; i < len(vf); i++ { 1859 | if f := Ceil(vf[i]); ceil[i] != f { 1860 | t.Errorf("Ceil(%g) = %g, want %g", vf[i], f, ceil[i]) 1861 | } 1862 | } 1863 | for i := 0; i < len(vfceilSC); i++ { 1864 | if f := Ceil(vfceilSC[i]); !alike(ceilSC[i], f) { 1865 | t.Errorf("Ceil(%g) = %g, want %g", vfceilSC[i], f, ceilSC[i]) 1866 | } 1867 | } 1868 | } 1869 | 1870 | func TestCopysign(t *testing.T) { 1871 | for i := 0; i < len(vf); i++ { 1872 | if f := Copysign(vf[i], -1); copysign[i] != f { 1873 | t.Errorf("Copysign(%g, -1) = %g, want %g", vf[i], f, copysign[i]) 1874 | } 1875 | } 1876 | for i := 0; i < len(vf); i++ { 1877 | if f := Copysign(vf[i], 1); -copysign[i] != f { 1878 | t.Errorf("Copysign(%g, 1) = %g, want %g", vf[i], f, -copysign[i]) 1879 | } 1880 | } 1881 | for i := 0; i < len(vfcopysignSC); i++ { 1882 | if f := Copysign(vfcopysignSC[i], -1); !alike(copysignSC[i], f) { 1883 | t.Errorf("Copysign(%g, -1) = %g, want %g", vfcopysignSC[i], f, copysignSC[i]) 1884 | } 1885 | } 1886 | } 1887 | 1888 | func TestCos(t *testing.T) { 1889 | for i := 0; i < len(vf); i++ { 1890 | if f := Cos(vf[i]); !close(cos[i], f) { 1891 | t.Errorf("Cos(%g) = %g, want %g", vf[i], f, cos[i]) 1892 | } 1893 | } 1894 | for i := 0; i < len(vfcosSC); i++ { 1895 | if f := Cos(vfcosSC[i]); !alike(cosSC[i], f) { 1896 | t.Errorf("Cos(%g) = %g, want %g", vfcosSC[i], f, cosSC[i]) 1897 | } 1898 | } 1899 | } 1900 | 1901 | func TestCosh(t *testing.T) { 1902 | for i := 0; i < len(vf); i++ { 1903 | if f := Cosh(vf[i]); !close(cosh[i], f) { 1904 | t.Errorf("Cosh(%g) = %g, want %g", vf[i], f, cosh[i]) 1905 | } 1906 | } 1907 | for i := 0; i < len(vfcoshSC); i++ { 1908 | if f := Cosh(vfcoshSC[i]); !alike(coshSC[i], f) { 1909 | t.Errorf("Cosh(%g) = %g, want %g", vfcoshSC[i], f, coshSC[i]) 1910 | } 1911 | } 1912 | } 1913 | 1914 | func TestErf(t *testing.T) { 1915 | for i := 0; i < len(vf); i++ { 1916 | a := vf[i] / 10 1917 | if f := Erf(a); !veryclose(erf[i], f) { 1918 | t.Errorf("Erf(%g) = %g, want %g", a, f, erf[i]) 1919 | } 1920 | } 1921 | for i := 0; i < len(vferfSC); i++ { 1922 | if f := Erf(vferfSC[i]); !alike(erfSC[i], f) { 1923 | t.Errorf("Erf(%g) = %g, want %g", vferfSC[i], f, erfSC[i]) 1924 | } 1925 | } 1926 | } 1927 | 1928 | func TestErfc(t *testing.T) { 1929 | for i := 0; i < len(vf); i++ { 1930 | a := vf[i] / 10 1931 | if f := Erfc(a); !veryclose(erfc[i], f) { 1932 | t.Errorf("Erfc(%g) = %g, want %g", a, f, erfc[i]) 1933 | } 1934 | } 1935 | for i := 0; i < len(vferfcSC); i++ { 1936 | if f := Erfc(vferfcSC[i]); !alike(erfcSC[i], f) { 1937 | t.Errorf("Erfc(%g) = %g, want %g", vferfcSC[i], f, erfcSC[i]) 1938 | } 1939 | } 1940 | } 1941 | 1942 | func TestExp(t *testing.T) { 1943 | testExp(t, Exp, "Exp") 1944 | // testExp(t, ExpGo, "ExpGo") 1945 | } 1946 | 1947 | func testExp(t *testing.T, Exp func(float32) float32, name string) { 1948 | for i := 0; i < len(vf); i++ { 1949 | if f := Exp(vf[i]); !close(exp[i], f) { 1950 | t.Errorf("%s(%g) = %g, want %g", name, vf[i], f, exp[i]) 1951 | } 1952 | } 1953 | for i := 0; i < len(vfexpSC); i++ { 1954 | if f := Exp(vfexpSC[i]); !alike(expSC[i], f) { 1955 | t.Errorf("%s(%g) = %g, want %g", name, vfexpSC[i], f, expSC[i]) 1956 | } 1957 | } 1958 | } 1959 | 1960 | func TestExpm1(t *testing.T) { 1961 | for i := 0; i < len(vf); i++ { 1962 | a := vf[i] / 100 1963 | if f := Expm1(a); !veryclose(expm1[i], f) { 1964 | t.Errorf("Expm1(%g) = %g, want %g", a, f, expm1[i]) 1965 | } 1966 | } 1967 | for i := 0; i < len(vf); i++ { 1968 | a := vf[i] * 10 1969 | if f := Expm1(a); !close(expm1Large[i], f) && (i == 4 && !IsInf(f, 1)) { 1970 | t.Errorf("Expm1(%g) = %g, want %g", a, f, expm1Large[i]) 1971 | } 1972 | } 1973 | for i := 0; i < len(vfexpm1SC); i++ { 1974 | if f := Expm1(vfexpm1SC[i]); !alike(expm1SC[i], f) { 1975 | t.Errorf("Expm1(%g) = %g, want %g", vfexpm1SC[i], f, expm1SC[i]) 1976 | } 1977 | } 1978 | } 1979 | 1980 | // func TestExp2(t *testing.T) { 1981 | // testExp2(t, Exp2, "Exp2") 1982 | // testExp2(t, Exp2Go, "Exp2Go") 1983 | // } 1984 | 1985 | func testExp2(t *testing.T, Exp2 func(float32) float32, name string) { 1986 | for i := 0; i < len(vf); i++ { 1987 | if f := Exp2(vf[i]); !close(exp2[i], f) { 1988 | t.Errorf("%s(%g) = %g, want %g", name, vf[i], f, exp2[i]) 1989 | } 1990 | } 1991 | for i := 0; i < len(vfexpSC); i++ { 1992 | if f := Exp2(vfexpSC[i]); !alike(expSC[i], f) { 1993 | t.Errorf("%s(%g) = %g, want %g", name, vfexpSC[i], f, expSC[i]) 1994 | } 1995 | } 1996 | for n := -1074; n < 1024; n++ { 1997 | f := Exp2(float32(n)) 1998 | vf := Ldexp(1, n) 1999 | if f != vf { 2000 | t.Errorf("%s(%d) = %g, want %g", name, n, f, vf) 2001 | } 2002 | } 2003 | } 2004 | 2005 | func TestAbs(t *testing.T) { 2006 | for i := 0; i < len(vf); i++ { 2007 | if f := Abs(vf[i]); fabs[i] != f { 2008 | t.Errorf("Abs(%g) = %g, want %g", vf[i], f, fabs[i]) 2009 | } 2010 | } 2011 | for i := 0; i < len(vffabsSC); i++ { 2012 | if f := Abs(vffabsSC[i]); !alike(fabsSC[i], f) { 2013 | t.Errorf("Abs(%g) = %g, want %g", vffabsSC[i], f, fabsSC[i]) 2014 | } 2015 | } 2016 | } 2017 | 2018 | func TestDim(t *testing.T) { 2019 | for i := 0; i < len(vf); i++ { 2020 | if f := Dim(vf[i], 0); fdim[i] != f { 2021 | t.Errorf("Dim(%g, %g) = %g, want %g", vf[i], 0.0, f, fdim[i]) 2022 | } 2023 | } 2024 | for i := 0; i < len(vffdimSC); i++ { 2025 | if f := Dim(vffdimSC[i][0], vffdimSC[i][1]); !alike(fdimSC[i], f) { 2026 | t.Errorf("Dim(%g, %g) = %g, want %g", vffdimSC[i][0], vffdimSC[i][1], f, fdimSC[i]) 2027 | } 2028 | } 2029 | for i := 0; i < len(vffdim2SC); i++ { 2030 | if f := Dim(vffdim2SC[i][0], vffdim2SC[i][1]); !alike(fdimSC[i], f) { 2031 | t.Errorf("Dim(%g, %g) = %g, want %g", vffdim2SC[i][0], vffdim2SC[i][1], f, fdimSC[i]) 2032 | } 2033 | } 2034 | } 2035 | 2036 | func TestFloor(t *testing.T) { 2037 | for i := 0; i < len(vf); i++ { 2038 | if f := Floor(vf[i]); floor[i] != f { 2039 | t.Errorf("Floor(%g) = %g, want %g", vf[i], f, floor[i]) 2040 | } 2041 | } 2042 | for i := 0; i < len(vfceilSC); i++ { 2043 | if f := Floor(vfceilSC[i]); !alike(ceilSC[i], f) { 2044 | t.Errorf("Floor(%g) = %g, want %g", vfceilSC[i], f, ceilSC[i]) 2045 | } 2046 | } 2047 | } 2048 | 2049 | func TestMax(t *testing.T) { 2050 | for i := 0; i < len(vf); i++ { 2051 | if f := Max(vf[i], ceil[i]); ceil[i] != f { 2052 | t.Errorf("Max(%g, %g) = %g, want %g", vf[i], ceil[i], f, ceil[i]) 2053 | } 2054 | } 2055 | for i := 0; i < len(vffdimSC); i++ { 2056 | if f := Max(vffdimSC[i][0], vffdimSC[i][1]); !alike(fmaxSC[i], f) { 2057 | t.Errorf("Max(%g, %g) = %g, want %g", vffdimSC[i][0], vffdimSC[i][1], f, fmaxSC[i]) 2058 | } 2059 | } 2060 | for i := 0; i < len(vffdim2SC); i++ { 2061 | if f := Max(vffdim2SC[i][0], vffdim2SC[i][1]); !alike(fmaxSC[i], f) { 2062 | t.Errorf("Max(%g, %g) = %g, want %g", vffdim2SC[i][0], vffdim2SC[i][1], f, fmaxSC[i]) 2063 | } 2064 | } 2065 | } 2066 | 2067 | func TestMin(t *testing.T) { 2068 | for i := 0; i < len(vf); i++ { 2069 | if f := Min(vf[i], floor[i]); floor[i] != f { 2070 | t.Errorf("Min(%g, %g) = %g, want %g", vf[i], floor[i], f, floor[i]) 2071 | } 2072 | } 2073 | for i := 0; i < len(vffdimSC); i++ { 2074 | if f := Min(vffdimSC[i][0], vffdimSC[i][1]); !alike(fminSC[i], f) { 2075 | t.Errorf("Min(%g, %g) = %g, want %g", vffdimSC[i][0], vffdimSC[i][1], f, fminSC[i]) 2076 | } 2077 | } 2078 | for i := 0; i < len(vffdim2SC); i++ { 2079 | if f := Min(vffdim2SC[i][0], vffdim2SC[i][1]); !alike(fminSC[i], f) { 2080 | t.Errorf("Min(%g, %g) = %g, want %g", vffdim2SC[i][0], vffdim2SC[i][1], f, fminSC[i]) 2081 | } 2082 | } 2083 | } 2084 | 2085 | func TestMod(t *testing.T) { 2086 | for i := 0; i < len(vf); i++ { 2087 | if f := Mod(10, vf[i]); !close(fmod[i], f) { 2088 | t.Errorf("Mod(10, %g) = %g, want %g", vf[i], f, fmod[i]) 2089 | } 2090 | } 2091 | for i := 0; i < len(vffmodSC); i++ { 2092 | if f := Mod(vffmodSC[i][0], vffmodSC[i][1]); !alike(fmodSC[i], f) { 2093 | t.Errorf("Mod(%g, %g) = %g, want %g", vffmodSC[i][0], vffmodSC[i][1], f, fmodSC[i]) 2094 | } 2095 | } 2096 | } 2097 | 2098 | func TestFrexp(t *testing.T) { 2099 | for i := 0; i < len(vf); i++ { 2100 | if f, j := Frexp(vf[i]); !veryclose(frexp[i].f, f) || frexp[i].i != j { 2101 | t.Errorf("Frexp(%g) = %g, %d, want %g, %d", vf[i], f, j, frexp[i].f, frexp[i].i) 2102 | } 2103 | } 2104 | for i := 0; i < len(vffrexpSC); i++ { 2105 | if f, j := Frexp(vffrexpSC[i]); !alike(frexpSC[i].f, f) || frexpSC[i].i != j { 2106 | t.Errorf("Frexp(%g) = %g, %d, want %g, %d", vffrexpSC[i], f, j, frexpSC[i].f, frexpSC[i].i) 2107 | } 2108 | } 2109 | for i := 0; i < len(vffrexpBC); i++ { 2110 | if f, j := Frexp(vffrexpBC[i]); !alike(frexpBC[i].f, f) || frexpBC[i].i != j { 2111 | t.Errorf("Frexp(%g) = %g, %d, want %g, %d", vffrexpBC[i], f, j, frexpBC[i].f, frexpBC[i].i) 2112 | } 2113 | } 2114 | } 2115 | 2116 | func TestGamma(t *testing.T) { 2117 | for i := 0; i < len(vf); i++ { 2118 | if f := Gamma(vf[i]); !thisclose(gamma[i], f, 1e-4) { 2119 | t.Errorf("Gamma(%g) = %g, want %g", vf[i], f, gamma[i]) 2120 | } 2121 | } 2122 | for i := 0; i < len(vfgammaSC); i++ { 2123 | if f := Gamma(vfgammaSC[i]); !alike(gammaSC[i], f) { 2124 | t.Errorf("Gamma(%g) = %g, want %g", vfgammaSC[i], f, gammaSC[i]) 2125 | } 2126 | } 2127 | } 2128 | 2129 | func TestHypot(t *testing.T) { 2130 | for i := 0; i < len(vf); i++ { 2131 | a := Abs(1e20 * tanh[i] * Sqrt(2)) 2132 | if f := Hypot(1e20*tanh[i], 1e20*tanh[i]); !veryclose(a, f) { 2133 | t.Errorf("Hypot(%g, %g) = %g, want %g", 1e20*tanh[i], 1e20*tanh[i], f, a) 2134 | } 2135 | } 2136 | for i := 0; i < len(vfhypotSC); i++ { 2137 | if f := Hypot(vfhypotSC[i][0], vfhypotSC[i][1]); !alike(hypotSC[i], f) { 2138 | t.Errorf("Hypot(%g, %g) = %g, want %g", vfhypotSC[i][0], vfhypotSC[i][1], f, hypotSC[i]) 2139 | } 2140 | } 2141 | } 2142 | 2143 | func TestIlogb(t *testing.T) { 2144 | for i := 0; i < len(vf); i++ { 2145 | a := frexp[i].i - 1 // adjust because fr in the interval [½, 1) 2146 | if e := Ilogb(vf[i]); a != e { 2147 | t.Errorf("Ilogb(%g) = %d, want %d", vf[i], e, a) 2148 | } 2149 | } 2150 | for i := 0; i < len(vflogbSC); i++ { 2151 | if e := Ilogb(vflogbSC[i]); ilogbSC[i] != e { 2152 | t.Errorf("Ilogb(%g) = %d, want %d", vflogbSC[i], e, ilogbSC[i]) 2153 | } 2154 | } 2155 | for i := 0; i < len(vffrexpBC); i++ { 2156 | if e := Ilogb(vffrexpBC[i]); int(logbBC[i]) != e { 2157 | t.Errorf("Ilogb(%g) = %d, want %d", vffrexpBC[i], e, int(logbBC[i])) 2158 | } 2159 | } 2160 | } 2161 | 2162 | func TestJ0(t *testing.T) { 2163 | for i := 0; i < len(vf); i++ { 2164 | if f := J0(vf[i]); !thisclose(j0[i], f, 4e-5) { 2165 | t.Errorf("J0(%g) = %g, want %g", vf[i], f, j0[i]) 2166 | } 2167 | } 2168 | for i := 0; i < len(vfj0SC); i++ { 2169 | if f := J0(vfj0SC[i]); !alike(j0SC[i], f) { 2170 | t.Errorf("J0(%g) = %g, want %g", vfj0SC[i], f, j0SC[i]) 2171 | } 2172 | } 2173 | } 2174 | 2175 | func TestJ1(t *testing.T) { 2176 | for i := 0; i < len(vf); i++ { 2177 | if f := J1(vf[i]); !close(j1[i], f) { 2178 | t.Errorf("J1(%g) = %g, want %g", vf[i], f, j1[i]) 2179 | } 2180 | } 2181 | for i := 0; i < len(vfj0SC); i++ { 2182 | if f := J1(vfj0SC[i]); !alike(j1SC[i], f) { 2183 | t.Errorf("J1(%g) = %g, want %g", vfj0SC[i], f, j1SC[i]) 2184 | } 2185 | } 2186 | } 2187 | 2188 | func TestJn(t *testing.T) { 2189 | for i := 0; i < len(vf); i++ { 2190 | if f := Jn(2, vf[i]); !close(j2[i], f) { 2191 | t.Errorf("Jn(2, %g) = %g, want %g", vf[i], f, j2[i]) 2192 | } 2193 | if f := Jn(-3, vf[i]); !close(jM3[i], f) { 2194 | t.Errorf("Jn(-3, %g) = %g, want %g", vf[i], f, jM3[i]) 2195 | } 2196 | } 2197 | for i := 0; i < len(vfj0SC); i++ { 2198 | if f := Jn(2, vfj0SC[i]); !alike(j2SC[i], f) { 2199 | t.Errorf("Jn(2, %g) = %g, want %g", vfj0SC[i], f, j2SC[i]) 2200 | } 2201 | if f := Jn(-3, vfj0SC[i]); !alike(jM3SC[i], f) { 2202 | t.Errorf("Jn(-3, %g) = %g, want %g", vfj0SC[i], f, jM3SC[i]) 2203 | } 2204 | } 2205 | } 2206 | 2207 | func TestLdexp(t *testing.T) { 2208 | for i := 0; i < len(vf); i++ { 2209 | if f := Ldexp(frexp[i].f, frexp[i].i); !veryclose(vf[i], f) { 2210 | t.Errorf("Ldexp(%g, %d) = %g, want %g", frexp[i].f, frexp[i].i, f, vf[i]) 2211 | } 2212 | } 2213 | for i := 0; i < len(vffrexpSC); i++ { 2214 | if f := Ldexp(frexpSC[i].f, frexpSC[i].i); !alike(vffrexpSC[i], f) { 2215 | t.Errorf("Ldexp(%g, %d) = %g, want %g", frexpSC[i].f, frexpSC[i].i, f, vffrexpSC[i]) 2216 | } 2217 | } 2218 | for i := 0; i < len(vfldexpSC); i++ { 2219 | if f := Ldexp(vfldexpSC[i].f, vfldexpSC[i].i); !alike(ldexpSC[i], f) { 2220 | t.Errorf("Ldexp(%g, %d) = %g, want %g", vfldexpSC[i].f, vfldexpSC[i].i, f, ldexpSC[i]) 2221 | } 2222 | } 2223 | for i := 0; i < len(vffrexpBC); i++ { 2224 | if f := Ldexp(frexpBC[i].f, frexpBC[i].i); !alike(vffrexpBC[i], f) { 2225 | t.Errorf("Ldexp(%g, %d) = %g, want %g", frexpBC[i].f, frexpBC[i].i, f, vffrexpBC[i]) 2226 | } 2227 | } 2228 | for i := 0; i < len(vfldexpBC); i++ { 2229 | if f := Ldexp(vfldexpBC[i].f, vfldexpBC[i].i); !alike(ldexpBC[i], f) { 2230 | t.Errorf("Ldexp(%g, %d) = %g, want %g", vfldexpBC[i].f, vfldexpBC[i].i, f, ldexpBC[i]) 2231 | } 2232 | } 2233 | } 2234 | 2235 | func TestLgamma(t *testing.T) { 2236 | for i := 0; i < len(vf); i++ { 2237 | if f, s := Lgamma(vf[i]); !thisclose(lgamma[i].f, f, 1e-4) || lgamma[i].i != s { 2238 | t.Errorf("Lgamma(%g) = %g, %d, want %g, %d", vf[i], f, s, lgamma[i].f, lgamma[i].i) 2239 | } 2240 | } 2241 | for i := 0; i < len(vflgammaSC); i++ { 2242 | if f, s := Lgamma(vflgammaSC[i]); !alike(lgammaSC[i].f, f) || lgammaSC[i].i != s { 2243 | t.Errorf("Lgamma(%g) = %g, %d, want %g, %d", vflgammaSC[i], f, s, lgammaSC[i].f, lgammaSC[i].i) 2244 | } 2245 | } 2246 | } 2247 | 2248 | func TestLog(t *testing.T) { 2249 | for i := 0; i < len(vf); i++ { 2250 | a := Abs(vf[i]) 2251 | if f := Log(a); !close(log[i], f) { 2252 | t.Errorf("Log(%g) = %g, want %g", a, f, log[i]) 2253 | } 2254 | } 2255 | if f := Log(10); f != Ln10 { 2256 | t.Errorf("Log(%g) = %g, want %g", 10.0, f, Ln10) 2257 | } 2258 | for i := 0; i < len(vflogSC); i++ { 2259 | if f := Log(vflogSC[i]); !alike(logSC[i], f) { 2260 | t.Errorf("Log(%g) = %g, want %g", vflogSC[i], f, logSC[i]) 2261 | } 2262 | } 2263 | } 2264 | 2265 | func TestLogb(t *testing.T) { 2266 | for i := 0; i < len(vf); i++ { 2267 | if f := Logb(vf[i]); logb[i] != f { 2268 | t.Errorf("Logb(%g) = %g, want %g", vf[i], f, logb[i]) 2269 | } 2270 | } 2271 | for i := 0; i < len(vflogbSC); i++ { 2272 | if f := Logb(vflogbSC[i]); !alike(logbSC[i], f) { 2273 | t.Errorf("Logb(%g) = %g, want %g", vflogbSC[i], f, logbSC[i]) 2274 | } 2275 | } 2276 | for i := 0; i < len(vffrexpBC); i++ { 2277 | if f := Logb(vffrexpBC[i]); !alike(logbBC[i], f) { 2278 | t.Errorf("Logb(%g) = %g, want %g", vffrexpBC[i], f, logbBC[i]) 2279 | } 2280 | } 2281 | } 2282 | 2283 | func TestLog10(t *testing.T) { 2284 | for i := 0; i < len(vf); i++ { 2285 | a := Abs(vf[i]) 2286 | if f := Log10(a); !veryclose(log10[i], f) { 2287 | t.Errorf("Log10(%g) = %g, want %g", a, f, log10[i]) 2288 | } 2289 | } 2290 | if f := Log10(E); f != Log10E { 2291 | t.Errorf("Log10(%g) = %g, want %g", E, f, Log10E) 2292 | } 2293 | for i := 0; i < len(vflogSC); i++ { 2294 | if f := Log10(vflogSC[i]); !alike(logSC[i], f) { 2295 | t.Errorf("Log10(%g) = %g, want %g", vflogSC[i], f, logSC[i]) 2296 | } 2297 | } 2298 | } 2299 | 2300 | func TestLog1p(t *testing.T) { 2301 | for i := 0; i < len(vf); i++ { 2302 | a := vf[i] / 100 2303 | if f := Log1p(a); !veryclose(log1p[i], f) { 2304 | t.Errorf("Log1p(%g) = %g, want %g", a, f, log1p[i]) 2305 | } 2306 | } 2307 | a := float32(9.0) 2308 | if f := Log1p(a); f != Ln10 { 2309 | t.Errorf("Log1p(%g) = %g, want %g", a, f, Ln10) 2310 | } 2311 | for i := 0; i < len(vflogSC); i++ { 2312 | if f := Log1p(vflog1pSC[i]); !alike(log1pSC[i], f) { 2313 | t.Errorf("Log1p(%g) = %g, want %g", vflog1pSC[i], f, log1pSC[i]) 2314 | } 2315 | } 2316 | } 2317 | 2318 | func TestLog2(t *testing.T) { 2319 | for i := 0; i < len(vf); i++ { 2320 | a := Abs(vf[i]) 2321 | if f := Log2(a); !veryclose(log2[i], f) { 2322 | t.Errorf("Log2(%g) = %g, want %g", a, f, log2[i]) 2323 | } 2324 | } 2325 | if f := Log2(E); f != Log2E { 2326 | t.Errorf("Log2(%g) = %g, want %g", E, f, Log2E) 2327 | } 2328 | for i := 0; i < len(vflogSC); i++ { 2329 | if f := Log2(vflogSC[i]); !alike(logSC[i], f) { 2330 | t.Errorf("Log2(%g) = %g, want %g", vflogSC[i], f, logSC[i]) 2331 | } 2332 | } 2333 | for i := -149; i <= 127; i++ { 2334 | f := Ldexp(1, i) 2335 | l := Log2(f) 2336 | if l != float32(i) { 2337 | t.Errorf("Log2(2**%d) = %g, want %d", i, l, i) 2338 | } 2339 | } 2340 | } 2341 | 2342 | func TestModf(t *testing.T) { 2343 | for i := 0; i < len(vf); i++ { 2344 | if f, g := Modf(vf[i]); !veryclose(modf[i][0], f) || !thisclose(modf[i][1], g, 1e-4) { 2345 | t.Errorf("Modf(%g) = %g, %g, want %g, %g", vf[i], f, g, modf[i][0], modf[i][1]) 2346 | } 2347 | } 2348 | for i := 0; i < len(vfmodfSC); i++ { 2349 | if f, g := Modf(vfmodfSC[i]); !alike(modfSC[i][0], f) || !alike(modfSC[i][1], g) { 2350 | t.Errorf("Modf(%g) = %g, %g, want %g, %g", vfmodfSC[i], f, g, modfSC[i][0], modfSC[i][1]) 2351 | } 2352 | } 2353 | } 2354 | 2355 | func TestNextafter(t *testing.T) { 2356 | for i := 0; i < len(vf); i++ { 2357 | vfi := vf[i] 2358 | if f := Nextafter(vfi, 10); nextafter32[i] != f { 2359 | t.Errorf("Nextafter32(%g, %g) = %g want %g", vfi, 10.0, f, nextafter32[i]) 2360 | } 2361 | } 2362 | for i := 0; i < len(vfnextafter32SC); i++ { 2363 | if f := Nextafter(vfnextafter32SC[i][0], vfnextafter32SC[i][1]); !alike(nextafter32SC[i], f) { 2364 | t.Errorf("Nextafter32(%g, %g) = %g want %g", vfnextafter32SC[i][0], vfnextafter32SC[i][1], f, nextafter32SC[i]) 2365 | } 2366 | } 2367 | } 2368 | 2369 | func TestPow(t *testing.T) { 2370 | for i := 0; i < len(vf); i++ { 2371 | if f := Pow(10, vf[i]); !close(pow[i], f) { 2372 | t.Errorf("Pow(10, %g) = %g, want %g", vf[i], f, pow[i]) 2373 | } 2374 | } 2375 | for i := 0; i < len(vfpowSC); i++ { 2376 | if f := Pow(vfpowSC[i][0], vfpowSC[i][1]); !alike(powSC[i], f) { 2377 | t.Errorf("Pow(%g, %g) = %g, want %g", vfpowSC[i][0], vfpowSC[i][1], f, powSC[i]) 2378 | } 2379 | } 2380 | } 2381 | 2382 | func TestPow10(t *testing.T) { 2383 | for i := 0; i < len(vfpow10SC); i++ { 2384 | if f := Pow10(vfpow10SC[i]); !alike(pow10SC[i], f) { 2385 | t.Errorf("Pow10(%d) = %g, want %g", vfpow10SC[i], f, pow10SC[i]) 2386 | } 2387 | } 2388 | } 2389 | 2390 | func TestRemainder(t *testing.T) { 2391 | for i := 0; i < len(vf); i++ { 2392 | if f := Remainder(10, vf[i]); !thisclose(remainder[i], f, 1e-4) { 2393 | t.Errorf("Remainder(10, %g) = %g, want %g", vf[i], f, remainder[i]) 2394 | } 2395 | } 2396 | for i := 0; i < len(vffmodSC); i++ { 2397 | if f := Remainder(vffmodSC[i][0], vffmodSC[i][1]); !alike(fmodSC[i], f) { 2398 | t.Errorf("Remainder(%g, %g) = %g, want %g", vffmodSC[i][0], vffmodSC[i][1], f, fmodSC[i]) 2399 | } 2400 | } 2401 | } 2402 | 2403 | func TestSignbit(t *testing.T) { 2404 | for i := 0; i < len(vf); i++ { 2405 | if f := Signbit(vf[i]); signbit[i] != f { 2406 | t.Errorf("Signbit(%g) = %t, want %t", vf[i], f, signbit[i]) 2407 | } 2408 | } 2409 | for i := 0; i < len(vfsignbitSC); i++ { 2410 | if f := Signbit(vfsignbitSC[i]); signbitSC[i] != f { 2411 | t.Errorf("Signbit(%g) = %t, want %t", vfsignbitSC[i], f, signbitSC[i]) 2412 | } 2413 | } 2414 | } 2415 | func TestSin(t *testing.T) { 2416 | for i := 0; i < len(vf); i++ { 2417 | if f := Sin(vf[i]); !close(sin[i], f) { 2418 | t.Errorf("Sin(%g) = %g, want %g", vf[i], f, sin[i]) 2419 | } 2420 | } 2421 | for i := 0; i < len(vfsinSC); i++ { 2422 | if f := Sin(vfsinSC[i]); !alike(sinSC[i], f) { 2423 | t.Errorf("Sin(%g) = %g, want %g", vfsinSC[i], f, sinSC[i]) 2424 | } 2425 | } 2426 | } 2427 | 2428 | func TestSincos(t *testing.T) { 2429 | for i := 0; i < len(vf); i++ { 2430 | if s, c := Sincos(vf[i]); !close(sin[i], s) || !close(cos[i], c) { 2431 | t.Errorf("Sincos(%g) = %g, %g want %g, %g", vf[i], s, c, sin[i], cos[i]) 2432 | } 2433 | } 2434 | } 2435 | 2436 | func TestSinh(t *testing.T) { 2437 | for i := 0; i < len(vf); i++ { 2438 | if f := Sinh(vf[i]); !close(sinh[i], f) { 2439 | t.Errorf("Sinh(%g) = %g, want %g", vf[i], f, sinh[i]) 2440 | } 2441 | } 2442 | for i := 0; i < len(vfsinhSC); i++ { 2443 | if f := Sinh(vfsinhSC[i]); !alike(sinhSC[i], f) { 2444 | t.Errorf("Sinh(%g) = %g, want %g", vfsinhSC[i], f, sinhSC[i]) 2445 | } 2446 | } 2447 | } 2448 | 2449 | func TestSqrt(t *testing.T) { 2450 | const tol = 1e-7 2451 | for i := 0; i < len(vf); i++ { 2452 | a := Abs(vf[i]) 2453 | if f := SqrtGo(a); !thisclose(f, sqrt[i], tol) { 2454 | t.Errorf("SqrtGo(%g) = %g, want %g", a, f, sqrt[i]) 2455 | } 2456 | if f := Sqrt(a); !thisclose(f, sqrt[i], tol) { 2457 | t.Errorf("Sqrt(%g) = %g, want %g", a, f, sqrt[i]) 2458 | } 2459 | } 2460 | for i := 0; i < len(vfsqrtSC); i++ { 2461 | if f := SqrtGo(vfsqrtSC[i]); !alike(sqrtSC[i], f) { 2462 | t.Errorf("SqrtGo(%g) = %g, want %g", vfsqrtSC[i], f, sqrtSC[i]) 2463 | } 2464 | if f := Sqrt(vfsqrtSC[i]); !alike(sqrtSC[i], f) { 2465 | t.Errorf("Sqrt(%g) = %g, want %g", vfsqrtSC[i], f, sqrtSC[i]) 2466 | } 2467 | } 2468 | } 2469 | 2470 | func TestTan(t *testing.T) { 2471 | for i := 0; i < len(vf); i++ { 2472 | if f := Tan(vf[i]); !close(tan[i], f) { 2473 | t.Errorf("Tan(%g) = %g, want %g", vf[i], f, tan[i]) 2474 | } 2475 | } 2476 | // same special cases as Sin 2477 | for i := 0; i < len(vfsinSC); i++ { 2478 | if f := Tan(vfsinSC[i]); !alike(sinSC[i], f) { 2479 | t.Errorf("Tan(%g) = %g, want %g", vfsinSC[i], f, sinSC[i]) 2480 | } 2481 | } 2482 | } 2483 | 2484 | func TestTanh(t *testing.T) { 2485 | for i := 0; i < len(vf); i++ { 2486 | if f := Tanh(vf[i]); !veryclose(tanh[i], f) { 2487 | t.Errorf("Tanh(%g) = %g, want %g", vf[i], f, tanh[i]) 2488 | } 2489 | } 2490 | for i := 0; i < len(vftanhSC); i++ { 2491 | if f := Tanh(vftanhSC[i]); !alike(tanhSC[i], f) { 2492 | t.Errorf("Tanh(%g) = %g, want %g", vftanhSC[i], f, tanhSC[i]) 2493 | } 2494 | } 2495 | } 2496 | 2497 | func TestTrunc(t *testing.T) { 2498 | for i := 0; i < len(vf); i++ { 2499 | if f := Trunc(vf[i]); trunc[i] != f { 2500 | t.Errorf("Trunc(%g) = %g, want %g", vf[i], f, trunc[i]) 2501 | } 2502 | } 2503 | for i := 0; i < len(vfceilSC); i++ { 2504 | if f := Trunc(vfceilSC[i]); !alike(ceilSC[i], f) { 2505 | t.Errorf("Trunc(%g) = %g, want %g", vfceilSC[i], f, ceilSC[i]) 2506 | } 2507 | } 2508 | } 2509 | 2510 | func TestY0(t *testing.T) { 2511 | for i := 0; i < len(vf); i++ { 2512 | a := Abs(vf[i]) 2513 | if f := Y0(a); !close(y0[i], f) { 2514 | t.Errorf("Y0(%g) = %g, want %g", a, f, y0[i]) 2515 | } 2516 | } 2517 | for i := 0; i < len(vfy0SC); i++ { 2518 | if f := Y0(vfy0SC[i]); !alike(y0SC[i], f) { 2519 | t.Errorf("Y0(%g) = %g, want %g", vfy0SC[i], f, y0SC[i]) 2520 | } 2521 | } 2522 | } 2523 | 2524 | func TestY1(t *testing.T) { 2525 | for i := 0; i < len(vf); i++ { 2526 | a := Abs(vf[i]) 2527 | if f := Y1(a); !close(y1[i], f) { 2528 | t.Errorf("Y1(%g) = %g, want %g", a, f, y1[i]) 2529 | } 2530 | } 2531 | for i := 0; i < len(vfy0SC); i++ { 2532 | if f := Y1(vfy0SC[i]); !alike(y1SC[i], f) { 2533 | t.Errorf("Y1(%g) = %g, want %g", vfy0SC[i], f, y1SC[i]) 2534 | } 2535 | } 2536 | } 2537 | 2538 | func TestYn(t *testing.T) { 2539 | for i := 0; i < len(vf); i++ { 2540 | a := Abs(vf[i]) 2541 | if f := Yn(2, a); !close(y2[i], f) { 2542 | t.Errorf("Yn(2, %g) = %g, want %g", a, f, y2[i]) 2543 | } 2544 | if f := Yn(-3, a); !close(yM3[i], f) { 2545 | t.Errorf("Yn(-3, %g) = %g, want %g", a, f, yM3[i]) 2546 | } 2547 | } 2548 | for i := 0; i < len(vfy0SC); i++ { 2549 | if f := Yn(2, vfy0SC[i]); !alike(y2SC[i], f) { 2550 | t.Errorf("Yn(2, %g) = %g, want %g", vfy0SC[i], f, y2SC[i]) 2551 | } 2552 | if f := Yn(-3, vfy0SC[i]); !alike(yM3SC[i], f) { 2553 | t.Errorf("Yn(-3, %g) = %g, want %g", vfy0SC[i], f, yM3SC[i]) 2554 | } 2555 | } 2556 | } 2557 | 2558 | // Check that math functions of high angle values 2559 | // return accurate results. [Since (vf[i] + large) - large != vf[i], 2560 | // testing for Trig(vf[i] + large) == Trig(vf[i]), where large is 2561 | // a multiple of 2*Pi, is misleading.] 2562 | func TestLargeCos(t *testing.T) { 2563 | large := float32(100000 * Pi) 2564 | for i := 0; i < len(vf); i++ { 2565 | f1 := cosLarge[i] 2566 | f2 := Cos(vf[i] + large) 2567 | if !nearby(f1, f2) { 2568 | t.Errorf("Cos(%g) = %g, want %g", vf[i]+large, f2, f1) 2569 | } 2570 | } 2571 | } 2572 | 2573 | func TestLargeSin(t *testing.T) { 2574 | large := float32(100000 * Pi) 2575 | for i := 0; i < len(vf); i++ { 2576 | f1 := sinLarge[i] 2577 | f2 := Sin(vf[i] + large) 2578 | if !nearby(f1, f2) { 2579 | t.Errorf("Sin(%g) = %g, want %g", vf[i]+large, f2, f1) 2580 | } 2581 | } 2582 | } 2583 | 2584 | func TestLargeSincos(t *testing.T) { 2585 | large := float32(100000 * Pi) 2586 | for i := 0; i < len(vf); i++ { 2587 | f1, g1 := sinLarge[i], cosLarge[i] 2588 | f2, g2 := Sincos(vf[i] + large) 2589 | if !nearby(f1, f2) || !nearby(g1, g2) { 2590 | t.Errorf("Sincos(%g) = %g, %g, want %g, %g", vf[i]+large, f2, g2, f1, g1) 2591 | } 2592 | } 2593 | } 2594 | 2595 | func TestLargeTan(t *testing.T) { 2596 | large := float32(100000 * Pi) 2597 | for i := 0; i < len(vf); i++ { 2598 | f1 := tanLarge[i] 2599 | f2 := Tan(vf[i] + large) 2600 | if !nearby(f1, f2) { 2601 | t.Errorf("Tan(%g) = %g, want %g", vf[i]+large, f2, f1) 2602 | } 2603 | } 2604 | } 2605 | 2606 | // Check that math constants are accepted by compiler 2607 | // and have right value (assumes strconv.ParseFloat works). 2608 | // https://golang.org/issue/201 2609 | 2610 | type floatTest struct { 2611 | val interface{} 2612 | name string 2613 | str string 2614 | } 2615 | 2616 | var floatTests = []floatTest{ 2617 | {float32(MaxFloat32), "MaxFloat32", "3.4028235e+38"}, 2618 | {float32(SmallestNonzeroFloat32), "SmallestNonzeroFloat32", "1e-45"}, 2619 | } 2620 | 2621 | func TestFloatMinMax(t *testing.T) { 2622 | for _, tt := range floatTests { 2623 | s := fmt.Sprint(tt.val) 2624 | if s != tt.str { 2625 | t.Errorf("Sprint(%v) = %s, want %s", tt.name, s, tt.str) 2626 | } 2627 | } 2628 | } 2629 | 2630 | // Benchmarks 2631 | 2632 | func BenchmarkAcos(b *testing.B) { 2633 | for i := 0; i < b.N; i++ { 2634 | Acos(.5) 2635 | } 2636 | } 2637 | 2638 | func BenchmarkAcosh(b *testing.B) { 2639 | for i := 0; i < b.N; i++ { 2640 | Acosh(1.5) 2641 | } 2642 | } 2643 | 2644 | func BenchmarkAsin(b *testing.B) { 2645 | for i := 0; i < b.N; i++ { 2646 | Asin(.5) 2647 | } 2648 | } 2649 | 2650 | func BenchmarkAsinh(b *testing.B) { 2651 | for i := 0; i < b.N; i++ { 2652 | Asinh(.5) 2653 | } 2654 | } 2655 | 2656 | func BenchmarkAtan(b *testing.B) { 2657 | for i := 0; i < b.N; i++ { 2658 | Atan(.5) 2659 | } 2660 | } 2661 | 2662 | func BenchmarkAtanh(b *testing.B) { 2663 | for i := 0; i < b.N; i++ { 2664 | Atanh(.5) 2665 | } 2666 | } 2667 | 2668 | func BenchmarkAtan2(b *testing.B) { 2669 | for i := 0; i < b.N; i++ { 2670 | Atan2(.5, 1) 2671 | } 2672 | } 2673 | 2674 | func BenchmarkCbrt(b *testing.B) { 2675 | for i := 0; i < b.N; i++ { 2676 | Cbrt(10) 2677 | } 2678 | } 2679 | 2680 | func BenchmarkCeil(b *testing.B) { 2681 | for i := 0; i < b.N; i++ { 2682 | Ceil(.5) 2683 | } 2684 | } 2685 | 2686 | func BenchmarkCopysign(b *testing.B) { 2687 | for i := 0; i < b.N; i++ { 2688 | Copysign(.5, -1) 2689 | } 2690 | } 2691 | 2692 | func BenchmarkCos(b *testing.B) { 2693 | for i := 0; i < b.N; i++ { 2694 | Cos(.5) 2695 | } 2696 | } 2697 | 2698 | func BenchmarkCosh(b *testing.B) { 2699 | for i := 0; i < b.N; i++ { 2700 | Cosh(2.5) 2701 | } 2702 | } 2703 | 2704 | func BenchmarkErf(b *testing.B) { 2705 | for i := 0; i < b.N; i++ { 2706 | Erf(.5) 2707 | } 2708 | } 2709 | 2710 | func BenchmarkErfc(b *testing.B) { 2711 | for i := 0; i < b.N; i++ { 2712 | Erfc(.5) 2713 | } 2714 | } 2715 | 2716 | func BenchmarkExp(b *testing.B) { 2717 | for i := 0; i < b.N; i++ { 2718 | Exp(.5) 2719 | } 2720 | } 2721 | 2722 | // func BenchmarkExpGo(b *testing.B) { 2723 | // for i := 0; i < b.N; i++ { 2724 | // ExpGo(.5) 2725 | // } 2726 | // } 2727 | 2728 | func BenchmarkExpm1(b *testing.B) { 2729 | for i := 0; i < b.N; i++ { 2730 | Expm1(.5) 2731 | } 2732 | } 2733 | 2734 | func BenchmarkExp2(b *testing.B) { 2735 | for i := 0; i < b.N; i++ { 2736 | Exp2(.5) 2737 | } 2738 | } 2739 | 2740 | // func BenchmarkExp2Go(b *testing.B) { 2741 | // for i := 0; i < b.N; i++ { 2742 | // Exp2Go(.5) 2743 | // } 2744 | // } 2745 | 2746 | func BenchmarkAbs(b *testing.B) { 2747 | for i := 0; i < b.N; i++ { 2748 | Abs(.5) 2749 | } 2750 | } 2751 | 2752 | func BenchmarkDim(b *testing.B) { 2753 | for i := 0; i < b.N; i++ { 2754 | Dim(10, 3) 2755 | } 2756 | } 2757 | 2758 | func BenchmarkFloor(b *testing.B) { 2759 | for i := 0; i < b.N; i++ { 2760 | Floor(.5) 2761 | } 2762 | } 2763 | 2764 | func BenchmarkMax(b *testing.B) { 2765 | for i := 0; i < b.N; i++ { 2766 | Max(10, 3) 2767 | } 2768 | } 2769 | 2770 | func BenchmarkMin(b *testing.B) { 2771 | for i := 0; i < b.N; i++ { 2772 | Min(10, 3) 2773 | } 2774 | } 2775 | 2776 | func BenchmarkMod(b *testing.B) { 2777 | for i := 0; i < b.N; i++ { 2778 | Mod(10, 3) 2779 | } 2780 | } 2781 | 2782 | func BenchmarkFrexp(b *testing.B) { 2783 | for i := 0; i < b.N; i++ { 2784 | Frexp(8) 2785 | } 2786 | } 2787 | 2788 | func BenchmarkGamma(b *testing.B) { 2789 | for i := 0; i < b.N; i++ { 2790 | Gamma(2.5) 2791 | } 2792 | } 2793 | 2794 | func BenchmarkHypot(b *testing.B) { 2795 | for i := 0; i < b.N; i++ { 2796 | Hypot(3, 4) 2797 | } 2798 | } 2799 | 2800 | func BenchmarkIlogb(b *testing.B) { 2801 | for i := 0; i < b.N; i++ { 2802 | Ilogb(.5) 2803 | } 2804 | } 2805 | 2806 | func BenchmarkJ0(b *testing.B) { 2807 | for i := 0; i < b.N; i++ { 2808 | J0(2.5) 2809 | } 2810 | } 2811 | 2812 | func BenchmarkJ1(b *testing.B) { 2813 | for i := 0; i < b.N; i++ { 2814 | J1(2.5) 2815 | } 2816 | } 2817 | 2818 | func BenchmarkJn(b *testing.B) { 2819 | for i := 0; i < b.N; i++ { 2820 | Jn(2, 2.5) 2821 | } 2822 | } 2823 | 2824 | func BenchmarkLdexp(b *testing.B) { 2825 | for i := 0; i < b.N; i++ { 2826 | Ldexp(.5, 2) 2827 | } 2828 | } 2829 | 2830 | func BenchmarkLgamma(b *testing.B) { 2831 | for i := 0; i < b.N; i++ { 2832 | Lgamma(2.5) 2833 | } 2834 | } 2835 | 2836 | func BenchmarkLog(b *testing.B) { 2837 | for i := 0; i < b.N; i++ { 2838 | Log(.5) 2839 | } 2840 | } 2841 | 2842 | func BenchmarkLogb(b *testing.B) { 2843 | for i := 0; i < b.N; i++ { 2844 | Logb(.5) 2845 | } 2846 | } 2847 | 2848 | func BenchmarkLog1p(b *testing.B) { 2849 | for i := 0; i < b.N; i++ { 2850 | Log1p(.5) 2851 | } 2852 | } 2853 | 2854 | func BenchmarkLog10(b *testing.B) { 2855 | for i := 0; i < b.N; i++ { 2856 | Log10(.5) 2857 | } 2858 | } 2859 | 2860 | func BenchmarkLog2(b *testing.B) { 2861 | for i := 0; i < b.N; i++ { 2862 | Log2(.5) 2863 | } 2864 | } 2865 | 2866 | func BenchmarkModf(b *testing.B) { 2867 | for i := 0; i < b.N; i++ { 2868 | Modf(1.5) 2869 | } 2870 | } 2871 | 2872 | func BenchmarkNextafter(b *testing.B) { 2873 | for i := 0; i < b.N; i++ { 2874 | Nextafter(.5, 1) 2875 | } 2876 | } 2877 | 2878 | func BenchmarkPowInt(b *testing.B) { 2879 | for i := 0; i < b.N; i++ { 2880 | Pow(2, 2) 2881 | } 2882 | } 2883 | 2884 | func BenchmarkPowFrac(b *testing.B) { 2885 | for i := 0; i < b.N; i++ { 2886 | Pow(2.5, 1.5) 2887 | } 2888 | } 2889 | 2890 | func BenchmarkPow10Pos(b *testing.B) { 2891 | for i := 0; i < b.N; i++ { 2892 | Pow10(300) 2893 | } 2894 | } 2895 | 2896 | func BenchmarkPow10Neg(b *testing.B) { 2897 | for i := 0; i < b.N; i++ { 2898 | Pow10(-300) 2899 | } 2900 | } 2901 | 2902 | func BenchmarkRemainder(b *testing.B) { 2903 | for i := 0; i < b.N; i++ { 2904 | Remainder(10, 3) 2905 | } 2906 | } 2907 | 2908 | func BenchmarkSignbit(b *testing.B) { 2909 | for i := 0; i < b.N; i++ { 2910 | Signbit(2.5) 2911 | } 2912 | } 2913 | 2914 | func BenchmarkSin(b *testing.B) { 2915 | for i := 0; i < b.N; i++ { 2916 | Sin(.5) 2917 | } 2918 | } 2919 | 2920 | func BenchmarkSincos(b *testing.B) { 2921 | for i := 0; i < b.N; i++ { 2922 | Sincos(.5) 2923 | } 2924 | } 2925 | 2926 | func BenchmarkSinh(b *testing.B) { 2927 | for i := 0; i < b.N; i++ { 2928 | Sinh(2.5) 2929 | } 2930 | } 2931 | 2932 | var Global float32 2933 | 2934 | func BenchmarkSqrt(b *testing.B) { 2935 | var x, y float32 2936 | x, y = 0.0, 10.0 2937 | for i := 0; i < b.N; i++ { 2938 | x += Sqrt(y) 2939 | } 2940 | Global = x 2941 | } 2942 | 2943 | func BenchmarkSqrtIndirect(b *testing.B) { 2944 | var x, y float32 2945 | x, y = 0.0, 10.0 2946 | f := Sqrt 2947 | for i := 0; i < b.N; i++ { 2948 | x += f(y) 2949 | } 2950 | Global = x 2951 | } 2952 | 2953 | // func BenchmarkSqrtGo(b *testing.B) { 2954 | // var x, y float32 2955 | // x, y = 0.0, 10.0 2956 | // for i := 0; i < b.N; i++ { 2957 | // x += SqrtGo(y) 2958 | // } 2959 | // Global = x 2960 | // } 2961 | 2962 | func isPrime(i int) bool { 2963 | // Yes, this is a dumb way to write this code, 2964 | // but calling Sqrt repeatedly in this way demonstrates 2965 | // the benefit of using a direct SQRT instruction on systems 2966 | // that have one, whereas the obvious loop seems not to 2967 | // demonstrate such a benefit. 2968 | for j := 2; float32(j) <= Sqrt(float32(i)); j++ { 2969 | if i%j == 0 { 2970 | return false 2971 | } 2972 | } 2973 | return true 2974 | } 2975 | 2976 | func BenchmarkSqrtPrime(b *testing.B) { 2977 | any := false 2978 | for i := 0; i < b.N; i++ { 2979 | if isPrime(100003) { 2980 | any = true 2981 | } 2982 | } 2983 | if any { 2984 | Global = 1 2985 | } 2986 | } 2987 | 2988 | func BenchmarkTan(b *testing.B) { 2989 | for i := 0; i < b.N; i++ { 2990 | Tan(.5) 2991 | } 2992 | } 2993 | 2994 | func BenchmarkTanh(b *testing.B) { 2995 | for i := 0; i < b.N; i++ { 2996 | Tanh(2.5) 2997 | } 2998 | } 2999 | func BenchmarkTrunc(b *testing.B) { 3000 | for i := 0; i < b.N; i++ { 3001 | Trunc(.5) 3002 | } 3003 | } 3004 | 3005 | func BenchmarkY0(b *testing.B) { 3006 | for i := 0; i < b.N; i++ { 3007 | Y0(2.5) 3008 | } 3009 | } 3010 | 3011 | func BenchmarkY1(b *testing.B) { 3012 | for i := 0; i < b.N; i++ { 3013 | Y1(2.5) 3014 | } 3015 | } 3016 | 3017 | func BenchmarkYn(b *testing.B) { 3018 | for i := 0; i < b.N; i++ { 3019 | Yn(2, 2.5) 3020 | } 3021 | } 3022 | -------------------------------------------------------------------------------- /asin.go: -------------------------------------------------------------------------------- 1 | package math32 2 | 3 | func Asin(x float32) float32 { 4 | if x == 0 { 5 | return x // special case 6 | } 7 | sign := false 8 | if x < 0 { 9 | x = -x 10 | sign = true 11 | } 12 | if x > 1 { 13 | return NaN() // special case 14 | } 15 | 16 | temp := Sqrt(1 - x*x) 17 | if x > 0.7 { 18 | temp = Pi/2 - satan(temp/x) 19 | } else { 20 | temp = satan(x / temp) 21 | } 22 | 23 | if sign { 24 | temp = -temp 25 | } 26 | return temp 27 | } 28 | -------------------------------------------------------------------------------- /asinh.go: -------------------------------------------------------------------------------- 1 | package math32 2 | 3 | // The original C code, the long comment, and the constants 4 | // below are from FreeBSD's /usr/src/lib/msun/src/s_asinh.c 5 | // and came with this notice. The go code is a simplified 6 | // version of the original C. 7 | // 8 | // ==================================================== 9 | // Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. 10 | // 11 | // Developed at SunPro, a Sun Microsystems, Inc. business. 12 | // Permission to use, copy, modify, and distribute this 13 | // software is freely granted, provided that this notice 14 | // is preserved. 15 | // ==================================================== 16 | // 17 | // 18 | // asinh(x) 19 | // Method : 20 | // Based on 21 | // asinh(x) = sign(x) * log [ |x| + sqrt(x*x+1) ] 22 | // we have 23 | // asinh(x) := x if 1+x*x=1, 24 | // := sign(x)*(log(x)+ln2)) for large |x|, else 25 | // := sign(x)*log(2|x|+1/(|x|+sqrt(x*x+1))) if|x|>2, else 26 | // := sign(x)*log1p(|x| + x**2/(1 + sqrt(1+x**2))) 27 | // 28 | 29 | // Asinh returns the inverse hyperbolic sine of x. 30 | // 31 | // Special cases are: 32 | // 33 | // Asinh(±0) = ±0 34 | // Asinh(±Inf) = ±Inf 35 | // Asinh(NaN) = NaN 36 | func Asinh(x float32) float32 { 37 | const ( 38 | Ln2 = 6.93147180559945286227e-01 // 0x3FE62E42FEFA39EF 39 | NearZero = 1.0 / (1 << 28) // 2**-28 40 | Large = 1 << 28 // 2**28 41 | ) 42 | // special cases 43 | if IsNaN(x) || IsInf(x, 0) { 44 | return x 45 | } 46 | sign := false 47 | if x < 0 { 48 | x = -x 49 | sign = true 50 | } 51 | var temp float32 52 | switch { 53 | case x > Large: 54 | temp = Log(x) + Ln2 // |x| > 2**28 55 | case x > 2: 56 | temp = Log(2*x + 1./(Sqrt(x*x+1)+x)) // 2**28 > |x| > 2.0 57 | case x < NearZero: 58 | temp = x // |x| < 2**-28 59 | default: 60 | temp = Log1p(x + x*x/(1+Sqrt(1+x*x))) // 2.0 > |x| > 2**-28 61 | } 62 | if sign { 63 | temp = -temp 64 | } 65 | return temp 66 | } 67 | -------------------------------------------------------------------------------- /atan.go: -------------------------------------------------------------------------------- 1 | package math32 2 | 3 | func Atan(x float32) float32 { 4 | if x == 0 { 5 | return x 6 | } 7 | if x > 0 { 8 | return satan(x) 9 | } 10 | return -satan(-x) 11 | } 12 | 13 | // The original C code, the long comment, and the constants below were 14 | // from http://netlib.sandia.gov/cephes/cmath/atan.c, available from 15 | // http://www.netlib.org/cephes/cmath.tgz. 16 | // The go code is a version of the original C. 17 | // 18 | // atan.c 19 | // Inverse circular tangent (arctangent) 20 | // 21 | // SYNOPSIS: 22 | // double x, y, atan(); 23 | // y = atan( x ); 24 | // 25 | // DESCRIPTION: 26 | // Returns radian angle between -pi/2 and +pi/2 whose tangent is x. 27 | // 28 | // Range reduction is from three intervals into the interval from zero to 0.66. 29 | // The approximant uses a rational function of degree 4/5 of the form 30 | // x + x**3 P(x)/Q(x). 31 | // 32 | // ACCURACY: 33 | // Relative error: 34 | // arithmetic domain # trials peak rms 35 | // DEC -10, 10 50000 2.4e-17 8.3e-18 36 | // IEEE -10, 10 10^6 1.8e-16 5.0e-17 37 | // 38 | // Cephes Math Library Release 2.8: June, 2000 39 | // Copyright 1984, 1987, 1989, 1992, 2000 by Stephen L. Moshier 40 | // 41 | // The readme file at http://netlib.sandia.gov/cephes/ says: 42 | // Some software in this archive may be from the book _Methods and 43 | // Programs for Mathematical Functions_ (Prentice-Hall or Simon & Schuster 44 | // International, 1989) or from the Cephes Mathematical Library, a 45 | // commercial product. In either event, it is copyrighted by the author. 46 | // What you see here may be used freely but it comes with no support or 47 | // guarantee. 48 | // 49 | // The two known misprints in the book are repaired here in the 50 | // source listings for the gamma function and the incomplete beta 51 | // integral. 52 | // 53 | // Stephen L. Moshier 54 | // moshier@na-net.ornl.gov 55 | 56 | // xatan evaluates a series valid in the range [0, 0.66]. 57 | func xatan(x float32) float32 { 58 | const ( 59 | P0 = -8.750608600031904122785e-01 60 | P1 = -1.615753718733365076637e+01 61 | P2 = -7.500855792314704667340e+01 62 | P3 = -1.228866684490136173410e+02 63 | P4 = -6.485021904942025371773e+01 64 | Q0 = +2.485846490142306297962e+01 65 | Q1 = +1.650270098316988542046e+02 66 | Q2 = +4.328810604912902668951e+02 67 | Q3 = +4.853903996359136964868e+02 68 | Q4 = +1.945506571482613964425e+02 69 | ) 70 | z := x * x 71 | z = z * ((((P0*z+P1)*z+P2)*z+P3)*z + P4) / (((((z+Q0)*z+Q1)*z+Q2)*z+Q3)*z + Q4) 72 | z = x*z + x 73 | return z 74 | } 75 | 76 | // satan reduces its argument (known to be positive) 77 | // to the range [0, 0.66] and calls xatan. 78 | func satan(x float32) float32 { 79 | const ( 80 | Morebits float32 = 6.123233995736765886130e-17 // pi/2 = PIO2 + Morebits 81 | Tan3pio8 float32 = 2.41421356237309504880 // tan(3*pi/8) 82 | ) 83 | if x <= 0.66 { 84 | return xatan(x) 85 | } 86 | if x > Tan3pio8 { 87 | return Pi/2 - xatan(1./x) + Morebits 88 | } 89 | return Pi/4 + xatan((x-1)/(x+1)) + 0.5*Morebits 90 | } 91 | -------------------------------------------------------------------------------- /atan2.go: -------------------------------------------------------------------------------- 1 | package math32 2 | 3 | // Atan2 returns the arc tangent of y/x, using the signs of the two to determine the quadrant of the return value. 4 | // Special cases are (in order): 5 | // 6 | // Atan2(y, NaN) = NaN 7 | // Atan2(NaN, x) = NaN 8 | // Atan2(+0, x>=0) = +0 9 | // Atan2(-0, x>=0) = -0 10 | // Atan2(+0, x<=-0) = +Pi 11 | // Atan2(-0, x<=-0) = -Pi 12 | // Atan2(y>0, 0) = +Pi/2 13 | // Atan2(y<0, 0) = -Pi/2 14 | // Atan2(+Inf, +Inf) = +Pi/4 15 | // Atan2(-Inf, +Inf) = -Pi/4 16 | // Atan2(+Inf, -Inf) = 3Pi/4 17 | // Atan2(-Inf, -Inf) = -3Pi/4 18 | // Atan2(y, +Inf) = 0 19 | // Atan2(y>0, -Inf) = +Pi 20 | // Atan2(y<0, -Inf) = -Pi 21 | // Atan2(+Inf, x) = +Pi/2 22 | // Atan2(-Inf, x) = -Pi/2 23 | func Atan2(y, x float32) float32 { 24 | // special cases 25 | switch { 26 | case IsNaN(y) || IsNaN(x): 27 | return NaN() 28 | case y == 0: 29 | if x >= 0 && !Signbit(x) { 30 | return Copysign(0, y) 31 | } 32 | return Copysign(Pi, y) 33 | case x == 0: 34 | return Copysign(Pi/2, y) 35 | case IsInf(x, 0): 36 | if IsInf(x, 1) { 37 | switch { 38 | case IsInf(y, 0): 39 | return Copysign(Pi/4, y) 40 | default: 41 | return Copysign(0, y) 42 | } 43 | } 44 | switch { 45 | case IsInf(y, 0): 46 | return Copysign(3*Pi/4, y) 47 | default: 48 | return Copysign(Pi, y) 49 | } 50 | case IsInf(y, 0): 51 | return Copysign(Pi/2, y) 52 | } 53 | 54 | // Call atan and determine the quadrant. 55 | q := Atan(y / x) 56 | if x < 0 { 57 | if q <= 0 { 58 | return q + Pi 59 | } 60 | return q - Pi 61 | } 62 | return q 63 | } 64 | -------------------------------------------------------------------------------- /atanh.go: -------------------------------------------------------------------------------- 1 | package math32 2 | 3 | // The original C code, the long comment, and the constants 4 | // below are from FreeBSD's /usr/src/lib/msun/src/e_atanh.c 5 | // and came with this notice. The go code is a simplified 6 | // version of the original C. 7 | // 8 | // ==================================================== 9 | // Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. 10 | // 11 | // Developed at SunPro, a Sun Microsystems, Inc. business. 12 | // Permission to use, copy, modify, and distribute this 13 | // software is freely granted, provided that this notice 14 | // is preserved. 15 | // ==================================================== 16 | // 17 | // 18 | // __ieee754_atanh(x) 19 | // Method : 20 | // 1. Reduce x to positive by atanh(-x) = -atanh(x) 21 | // 2. For x>=0.5 22 | // 1 2x x 23 | // atanh(x) = --- * log(1 + -------) = 0.5 * log1p(2 * --------) 24 | // 2 1 - x 1 - x 25 | // 26 | // For x<0.5 27 | // atanh(x) = 0.5*log1p(2x+2x*x/(1-x)) 28 | // 29 | // Special cases: 30 | // atanh(x) is NaN if |x| > 1 with signal; 31 | // atanh(NaN) is that NaN with no signal; 32 | // atanh(+-1) is +-INF with signal. 33 | // 34 | 35 | // Atanh returns the inverse hyperbolic tangent of x. 36 | // 37 | // Special cases are: 38 | // 39 | // Atanh(1) = +Inf 40 | // Atanh(±0) = ±0 41 | // Atanh(-1) = -Inf 42 | // Atanh(x) = NaN if x < -1 or x > 1 43 | // Atanh(NaN) = NaN 44 | func Atanh(x float32) float32 { 45 | const NearZero = 1.0 / (1 << 28) // 2**-28 46 | // special cases 47 | switch { 48 | case x < -1 || x > 1 || IsNaN(x): 49 | return NaN() 50 | case x == 1: 51 | return Inf(1) 52 | case x == -1: 53 | return Inf(-1) 54 | } 55 | sign := false 56 | if x < 0 { 57 | x = -x 58 | sign = true 59 | } 60 | var temp float32 61 | switch { 62 | case x < NearZero: 63 | temp = x 64 | case x < 0.5: 65 | temp = x + x 66 | temp = 0.5 * Log1p(temp+temp*x/(1-x)) 67 | default: 68 | temp = 0.5 * Log1p((x+x)/(1-x)) 69 | } 70 | if sign { 71 | temp = -temp 72 | } 73 | return temp 74 | } 75 | -------------------------------------------------------------------------------- /bits.go: -------------------------------------------------------------------------------- 1 | package math32 2 | 3 | const ( 4 | uvnan = 0x7FE00000 5 | uvinf = 0x7F800000 6 | uvone = 0x3f800000 7 | uvneginf = 0xFF800000 8 | mask = 0xFF 9 | shift = 32 - 8 - 1 10 | bias = 127 11 | signMask = 1 << 31 12 | fracMask = 1<= 0, negative infinity if sign < 0. 16 | func Inf(sign int) float32 { 17 | var v uint32 18 | if sign >= 0 { 19 | v = uvinf 20 | } else { 21 | v = uvneginf 22 | } 23 | return Float32frombits(v) 24 | } 25 | 26 | // NaN returns an IEEE 754 “not-a-number” value. 27 | func NaN() float32 { return Float32frombits(uvnan) } 28 | 29 | // IsNaN reports whether f is an IEEE 754 “not-a-number” value. 30 | func IsNaN(f float32) (is bool) { 31 | // IEEE 754 says that only NaNs satisfy f != f. 32 | // To avoid the floating-point hardware, could use: 33 | // x := Float32bits(f) 34 | // return uint32(x>>shift)&mask == mask && x != uvinf && x != uvneginf 35 | return f != f 36 | } 37 | 38 | // IsInf reports whether f is an infinity, according to sign. 39 | // If sign > 0, IsInf reports whether f is positive infinity. 40 | // If sign < 0, IsInf reports whether f is negative infinity. 41 | // If sign == 0, IsInf reports whether f is either infinity. 42 | func IsInf(f float32, sign int) bool { 43 | // Test for infinity by comparing against maximum float. 44 | // To avoid the floating-point hardware, could use: 45 | // x := Float32bits(f) 46 | // return sign >= 0 && x == uvinf || sign <= 0 && x == uvneginf 47 | return sign >= 0 && f > MaxFloat32 || sign <= 0 && f < -MaxFloat32 48 | } 49 | 50 | // normalize returns a normal number y and exponent exp 51 | // satisfying x == y × 2**exp. It assumes x is finite and non-zero. 52 | func normalize(x float32) (y float32, exp int) { 53 | const SmallestNormal = 1.1754943508222875079687365e-38 // 2**-(127 - 1) 54 | if Abs(x) < SmallestNormal { 55 | return x * (1 << shift), -shift 56 | } 57 | return x, 0 58 | } 59 | -------------------------------------------------------------------------------- /cbrt.go: -------------------------------------------------------------------------------- 1 | package math32 2 | 3 | import "math" 4 | 5 | // Cbrt returns the cube root of x. 6 | // 7 | // Special cases are: 8 | // 9 | // Cbrt(±0) = ±0 10 | // Cbrt(±Inf) = ±Inf 11 | // Cbrt(NaN) = NaN 12 | func Cbrt(x float32) float32 { 13 | return float32(math.Cbrt(float64(x))) 14 | } 15 | -------------------------------------------------------------------------------- /const.go: -------------------------------------------------------------------------------- 1 | package math32 2 | 3 | // Mathematical constants. 4 | const ( 5 | E = float32(2.71828182845904523536028747135266249775724709369995957496696763) // http://oeis.org/A001113 6 | Pi = float32(3.14159265358979323846264338327950288419716939937510582097494459) // http://oeis.org/A000796 7 | Phi = float32(1.61803398874989484820458683436563811772030917980576286213544862) // http://oeis.org/A001622 8 | 9 | Sqrt2 = float32(1.41421356237309504880168872420969807856967187537694807317667974) // http://oeis.org/A002193 10 | SqrtE = float32(1.64872127070012814684865078781416357165377610071014801157507931) // http://oeis.org/A019774 11 | SqrtPi = float32(1.77245385090551602729816748334114518279754945612238712821380779) // http://oeis.org/A002161 12 | SqrtPhi = float32(1.27201964951406896425242246173749149171560804184009624861664038) // http://oeis.org/A139339 13 | 14 | Ln2 = float32(0.693147180559945309417232121458176568075500134360255254120680009) // http://oeis.org/A002162 15 | Log2E = float32(1 / Ln2) 16 | Ln10 = float32(2.30258509299404568401799145468436420760110148862877297603332790) // http://oeis.org/A002392 17 | Log10E = float32(1 / Ln10) 18 | ) 19 | 20 | // Floating-point limit values. 21 | // Max is the largest finite value representable by the type. 22 | // SmallestNonzero is the smallest positive, non-zero value representable by the type. 23 | const ( 24 | MaxFloat32 = 3.40282346638528859811704183484516925440e+38 // 2**127 * (2**24 - 1) / 2**23 25 | SmallestNonzeroFloat32 = 1.401298464324817070923729583289916131280e-45 // 1 / 2**(127 - 1 + 23) 26 | ) 27 | 28 | // Integer limit values. 29 | const ( 30 | MaxInt8 = 1<<7 - 1 31 | MinInt8 = -1 << 7 32 | MaxInt16 = 1<<15 - 1 33 | MinInt16 = -1 << 15 34 | MaxInt32 = 1<<31 - 1 35 | MinInt32 = -1 << 31 36 | MaxInt64 = 1<<63 - 1 37 | MinInt64 = -1 << 63 38 | MaxUint8 = 1<<8 - 1 39 | MaxUint16 = 1<<16 - 1 40 | MaxUint32 = 1<<32 - 1 41 | MaxUint64 = 1<<64 - 1 42 | ) 43 | -------------------------------------------------------------------------------- /copysign.go: -------------------------------------------------------------------------------- 1 | package math32 2 | 3 | import "math" 4 | 5 | // Copysign returns a value with the magnitude of f and the sign of sign. 6 | func Copysign(x, y float32) float32 { 7 | const sign = 1 << 31 8 | return math.Float32frombits(math.Float32bits(x)&^sign | math.Float32bits(y)&sign) 9 | } 10 | -------------------------------------------------------------------------------- /cosh.go: -------------------------------------------------------------------------------- 1 | package math32 2 | 3 | func Cosh(x float32) float32 { 4 | x = Abs(x) 5 | if x > 21 { 6 | return Exp(x) * 0.5 7 | } 8 | ex := Exp(x) 9 | return (ex + 1./ex) * 0.5 10 | } 11 | -------------------------------------------------------------------------------- /dim.go: -------------------------------------------------------------------------------- 1 | package math32 2 | 3 | // Dim returns the maximum of x-y or 0. 4 | // 5 | // Special cases are: 6 | // 7 | // Dim(+Inf, +Inf) = NaN 8 | // Dim(-Inf, -Inf) = NaN 9 | // Dim(x, NaN) = Dim(NaN, x) = NaN 10 | func Dim(x, y float32) float32 { 11 | return dim(x, y) 12 | } 13 | 14 | func dim(x, y float32) float32 { 15 | return max(x-y, 0) 16 | } 17 | 18 | // Max returns the larger of x or y. 19 | // 20 | // Special cases are: 21 | // 22 | // Max(x, +Inf) = Max(+Inf, x) = +Inf 23 | // Max(x, NaN) = Max(NaN, x) = NaN 24 | // Max(+0, ±0) = Max(±0, +0) = +0 25 | // Max(-0, -0) = -0 26 | func Max(x, y float32) float32 { 27 | return max(x, y) 28 | } 29 | 30 | func max(x, y float32) float32 { 31 | // special cases 32 | switch { 33 | case IsInf(x, 1) || IsInf(y, 1): 34 | return Inf(1) 35 | case IsNaN(x) || IsNaN(y): 36 | return NaN() 37 | case x == 0 && x == y: 38 | if Signbit(x) { 39 | return y 40 | } 41 | return x 42 | } 43 | if x > y { 44 | return x 45 | } 46 | return y 47 | } 48 | 49 | // Min returns the smaller of x or y. 50 | // 51 | // Special cases are: 52 | // 53 | // Min(x, -Inf) = Min(-Inf, x) = -Inf 54 | // Min(x, NaN) = Min(NaN, x) = NaN 55 | // Min(-0, ±0) = Min(±0, -0) = -0 56 | func Min(x, y float32) float32 { 57 | return min(x, y) 58 | } 59 | 60 | func min(x, y float32) float32 { 61 | // special cases 62 | switch { 63 | case IsInf(x, -1) || IsInf(y, -1): 64 | return Inf(-1) 65 | case IsNaN(x) || IsNaN(y): 66 | return NaN() 67 | case x == 0 && x == y: 68 | if Signbit(x) { 69 | return x 70 | } 71 | return y 72 | } 73 | if x < y { 74 | return x 75 | } 76 | return y 77 | } 78 | -------------------------------------------------------------------------------- /doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Package math32 provides basic constants and mathematical functions for float32 types. 3 | 4 | At its core, it's mostly just a wrapper in form of float32(math.XXX). This applies to the following functions: 5 | 6 | Acos 7 | Acosh 8 | Asin 9 | Asinh 10 | Atan 11 | Atan2 12 | Atanh 13 | Cbrt 14 | Cos 15 | Cosh 16 | Erfc 17 | Gamma 18 | J0 19 | J1 20 | Jn 21 | Log10 22 | Log1p 23 | Log2 24 | Logb 25 | Pow10 26 | Sin 27 | Sinh 28 | Tan 29 | Y0 30 | Y1 31 | 32 | Everything else is a float32 implementation. Implementation schedule is sporadic an uncertain. But eventually all functions will be replaced 33 | */ 34 | package math32 35 | -------------------------------------------------------------------------------- /erf.go: -------------------------------------------------------------------------------- 1 | package math32 2 | 3 | import "math" 4 | 5 | // Erf returns the error function of x. 6 | // 7 | // Special cases are: 8 | // 9 | // Erf(+Inf) = 1 10 | // Erf(-Inf) = -1 11 | // Erf(NaN) = NaN 12 | func Erf(x float32) float32 { 13 | return float32(math.Erf(float64(x))) 14 | } 15 | -------------------------------------------------------------------------------- /erfc.go: -------------------------------------------------------------------------------- 1 | package math32 2 | 3 | import "math" 4 | 5 | // Erfc returns the complementary error function of x. 6 | // 7 | // Special cases are: 8 | // 9 | // Erfc(+Inf) = 0 10 | // Erfc(-Inf) = 2 11 | // Erfc(NaN) = NaN 12 | func Erfc(x float32) float32 { 13 | return float32(math.Erfc(float64(x))) 14 | } 15 | -------------------------------------------------------------------------------- /exp.go: -------------------------------------------------------------------------------- 1 | package math32 2 | 3 | // Exp returns e**x, the base-e exponential of x. 4 | // 5 | // Special cases are: 6 | // 7 | // Exp(+Inf) = +Inf 8 | // Exp(NaN) = NaN 9 | // 10 | // Very large values overflow to 0 or +Inf. 11 | // Very small values underflow to 1. 12 | func Exp(x float32) float32 { 13 | if haveArchExp { 14 | return archExp(x) 15 | } 16 | return exp(x) 17 | } 18 | 19 | func exp(x float32) float32 { 20 | const ( 21 | Ln2Hi = float32(6.9313812256e-01) 22 | Ln2Lo = float32(9.0580006145e-06) 23 | Log2e = float32(1.4426950216e+00) 24 | 25 | Overflow = 7.09782712893383973096e+02 26 | Underflow = -7.45133219101941108420e+02 27 | NearZero = 1.0 / (1 << 28) // 2**-28 28 | 29 | LogMax = 0x42b2d4fc // The bitmask of log(FLT_MAX), rounded down. This value is the largest input that can be passed to exp() without producing overflow. 30 | LogMin = 0x42aeac50 // The bitmask of |log(REAL_FLT_MIN)|, rounding down 31 | 32 | ) 33 | // hx := Float32bits(x) & uint32(0x7fffffff) 34 | 35 | // special cases 36 | switch { 37 | case IsNaN(x) || IsInf(x, 1): 38 | return x 39 | case IsInf(x, -1): 40 | return 0 41 | case x > Overflow: 42 | return Inf(1) 43 | case x < Underflow: 44 | // case hx > LogMax: 45 | // return Inf(1) 46 | // case x < 0 && hx > LogMin: 47 | return 0 48 | case -NearZero < x && x < NearZero: 49 | return 1 + x 50 | } 51 | 52 | // reduce; computed as r = hi - lo for extra precision. 53 | var k int 54 | switch { 55 | case x < 0: 56 | k = int(Log2e*x - 0.5) 57 | case x > 0: 58 | k = int(Log2e*x + 0.5) 59 | } 60 | hi := x - float32(k)*Ln2Hi 61 | lo := float32(k) * Ln2Lo 62 | 63 | // compute 64 | return expmulti(hi, lo, k) 65 | } 66 | 67 | // Exp2 returns 2**x, the base-2 exponential of x. 68 | // 69 | // Special cases are the same as Exp. 70 | func Exp2(x float32) float32 { 71 | if haveArchExp2 { 72 | return archExp2(x) 73 | } 74 | return exp2(x) 75 | } 76 | 77 | func exp2(x float32) float32 { 78 | const ( 79 | Ln2Hi = 6.9313812256e-01 80 | Ln2Lo = 9.0580006145e-06 81 | 82 | Overflow = 1.0239999999999999e+03 83 | Underflow = -1.0740e+03 84 | ) 85 | 86 | // special cases 87 | switch { 88 | case IsNaN(x) || IsInf(x, 1): 89 | return x 90 | case IsInf(x, -1): 91 | return 0 92 | case x > Overflow: 93 | return Inf(1) 94 | case x < Underflow: 95 | return 0 96 | } 97 | 98 | // argument reduction; x = r×lg(e) + k with |r| ≤ ln(2)/2. 99 | // computed as r = hi - lo for extra precision. 100 | var k int 101 | switch { 102 | case x > 0: 103 | k = int(x + 0.5) 104 | case x < 0: 105 | k = int(x - 0.5) 106 | } 107 | t := x - float32(k) 108 | hi := t * Ln2Hi 109 | lo := -t * Ln2Lo 110 | 111 | // compute 112 | return expmulti(hi, lo, k) 113 | } 114 | 115 | // exp1 returns e**r × 2**k where r = hi - lo and |r| ≤ ln(2)/2. 116 | func expmulti(hi, lo float32, k int) float32 { 117 | const ( 118 | P1 = float32(1.6666667163e-01) /* 0x3e2aaaab */ 119 | P2 = float32(-2.7777778450e-03) /* 0xbb360b61 */ 120 | P3 = float32(6.6137559770e-05) /* 0x388ab355 */ 121 | P4 = float32(-1.6533901999e-06) /* 0xb5ddea0e */ 122 | P5 = float32(4.1381369442e-08) /* 0x3331bb4c */ 123 | ) 124 | 125 | r := hi - lo 126 | t := r * r 127 | c := r - t*(P1+t*(P2+t*(P3+t*(P4+t*P5)))) 128 | y := 1 - ((lo - (r*c)/(2-c)) - hi) 129 | // TODO(rsc): make sure Ldexp can handle boundary k 130 | return Ldexp(y, k) 131 | } 132 | -------------------------------------------------------------------------------- /exp2_asm.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | //go:build !noasm && !tinygo && (amd64 || 386 || arm || ppc64le || wasm) 6 | // +build !noasm 7 | // +build !tinygo 8 | // +build amd64 386 arm ppc64le wasm 9 | 10 | package math32 11 | 12 | const haveArchExp2 = true 13 | 14 | func archExp2(x float32) float32 15 | -------------------------------------------------------------------------------- /exp2_noasm.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | //go:build noasm || tinygo || !(amd64 || 386 || arm || ppc64le || wasm) 6 | // +build noasm tinygo !amd64,!386,!arm,!ppc64le,!wasm 7 | 8 | package math32 9 | 10 | const haveArchExp2 = false 11 | 12 | func archExp2(x float32) float32 { 13 | panic("not implemented") 14 | } 15 | -------------------------------------------------------------------------------- /exp_amd64.s: -------------------------------------------------------------------------------- 1 | //go:build !tinygo && !noasm 2 | // Copyright 2014 Xuanyi Chew. All rights reserved. 3 | // Use of this source code is governed by a BSD-style 4 | // license that can be found in the LICENSE file. 5 | // 6 | // The original code is lifted from the Go standard library which is governed by 7 | // a BSD-style licence which can be found here: https://golang.org/LICENSE 8 | 9 | #include "textflag.h" 10 | 11 | // The method is based on a paper by Naoki Shibata: "Efficient evaluation 12 | // methods of elementary functions suitable for SIMD computation", Proc. 13 | // of International Supercomputing Conference 2010 (ISC'10), pp. 25 -- 32 14 | // (May 2010). The paper is available at 15 | // http://www.springerlink.com/content/340228x165742104/ 16 | // 17 | // The original code and the constants below are from the author's 18 | // implementation available at http://freshmeat.net/projects/sleef. 19 | // The README file says, "The software is in public domain. 20 | // You can use the software without any obligation." 21 | // 22 | // This code is a simplified version of the original. 23 | // The magic numbers for the float32 are lifted from the same project 24 | 25 | 26 | #define LN2 0.693147182464599609375 // log_e(2) 27 | #define LOG2E 1.44269502162933349609375 // 1/LN2 28 | #define LN2U 0.693145751953125 // upper half LN2 29 | #define LN2L 1.428606765330187045e-06 // lower half LN2 30 | #define T0 1.0 31 | #define T1 0.5 32 | #define T2 0.166665524244308471679688 33 | #define T3 0.0416710823774337768554688 34 | #define T4 0.00836596917361021041870117 35 | #define PosInf 0x7F800000 36 | #define NegInf 0xFF800000 37 | 38 | // func archExp(x float32) float32 39 | TEXT ·archExp(SB),NOSPLIT,$0 40 | // test bits for not-finite 41 | MOVL x+0(FP), BX 42 | MOVQ $~(1<<31), AX // sign bit mask 43 | MOVL BX, DX 44 | ANDL AX, DX 45 | MOVL $PosInf, AX 46 | CMPL AX, DX 47 | JLE notFinite 48 | MOVL BX, X0 49 | MOVSS $LOG2E, X1 50 | MULSS X0, X1 51 | CVTSS2SL X1, BX // BX = exponent 52 | CVTSL2SS BX, X1 53 | MOVSS $LN2U, X2 54 | MULSS X1, X2 55 | SUBSS X2, X0 56 | MOVSS $LN2L, X2 57 | MULSS X1, X2 58 | SUBSS X2, X0 59 | // reduce argument 60 | MULSS $0.0625, X0 61 | // Taylor series evaluation 62 | ADDSS $T4, X1 63 | MULSS X0, X1 64 | ADDSS $T3, X1 65 | MULSS X0, X1 66 | ADDSS $T2, X1 67 | MULSS X0, X1 68 | ADDSS $T1, X1 69 | MULSS X0, X1 70 | ADDSS $T0, X1 71 | MULSS X1, X0 72 | MOVSS $2.0, X1 73 | ADDSS X0, X1 74 | MULSS X1, X0 75 | MOVSS $2.0, X1 76 | ADDSS X0, X1 77 | MULSS X1, X0 78 | MOVSS $2.0, X1 79 | ADDSS X0, X1 80 | MULSS X1, X0 81 | MOVSS $2.0, X1 82 | ADDSS X0, X1 83 | MULSS X1, X0 84 | ADDSS $1.0, X0 85 | // return fr * 2**exponent 86 | MOVL $0x7F, AX // bias 87 | ADDL AX, BX 88 | JLE underflow 89 | CMPL BX, $0xFF 90 | JGE overflow 91 | MOVL $23, CX 92 | SHLQ CX, BX 93 | MOVL BX, X1 94 | MULSS X1, X0 95 | MOVSS X0, ret+8(FP) 96 | RET 97 | notFinite: 98 | // test bits for -Inf 99 | MOVL $NegInf, AX 100 | CMPQ AX, BX 101 | JNE notNegInf 102 | // -Inf, return 0 103 | underflow: // return 0 104 | MOVL $0, AX 105 | MOVL AX, ret+8(FP) 106 | RET 107 | overflow: // return +Inf 108 | MOVL $PosInf, BX 109 | notNegInf: // NaN or +Inf, return x 110 | MOVL BX, ret+8(FP) 111 | RET 112 | 113 | TEXT ·archExp2(SB),NOSPLIT,$0 114 | JMP ·exp2(SB) 115 | -------------------------------------------------------------------------------- /exp_asm.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | //go:build !noasm && !tinygo && (amd64 || 386 || arm || ppc64le || wasm || s390x) 6 | // +build !noasm 7 | // +build !tinygo 8 | // +build amd64 386 arm ppc64le wasm s390x 9 | 10 | package math32 11 | 12 | const haveArchExp = true 13 | 14 | func archExp(x float32) float32 15 | -------------------------------------------------------------------------------- /exp_noasm.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | //go:build noasm || tinygo || !(amd64 || 386 || arm || ppc64le || wasm || s390x) 6 | // +build noasm tinygo !amd64,!386,!arm,!ppc64le,!wasm,!s390x 7 | 8 | package math32 9 | 10 | const haveArchExp = false 11 | 12 | func archExp(x float32) float32 { 13 | panic("not implemented") 14 | } 15 | -------------------------------------------------------------------------------- /expm1f.go: -------------------------------------------------------------------------------- 1 | // Copyright 2010 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package math32 6 | 7 | // The original C code, the long comment, and the constants 8 | // below are from FreeBSD's /usr/src/lib/msun/src/s_expm1.c 9 | // and came with this notice. The go code is a simplified 10 | // version of the original C. 11 | // 12 | // ==================================================== 13 | // Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. 14 | // 15 | // Developed at SunPro, a Sun Microsystems, Inc. business. 16 | // Permission to use, copy, modify, and distribute this 17 | // software is freely granted, provided that this notice 18 | // is preserved. 19 | // ==================================================== 20 | // 21 | // expm1(x) 22 | // Returns exp(x)-1, the exponential of x minus 1. 23 | // 24 | // Method 25 | // 1. Argument reduction: 26 | // Given x, find r and integer k such that 27 | // 28 | // x = k*ln2 + r, |r| <= 0.5*ln2 ~ 0.34658 29 | // 30 | // Here a correction term c will be computed to compensate 31 | // the error in r when rounded to a floating-point number. 32 | // 33 | // 2. Approximating expm1(r) by a special rational function on 34 | // the interval [0,0.34658]: 35 | // Since 36 | // r*(exp(r)+1)/(exp(r)-1) = 2+ r**2/6 - r**4/360 + ... 37 | // we define R1(r*r) by 38 | // r*(exp(r)+1)/(exp(r)-1) = 2+ r**2/6 * R1(r*r) 39 | // That is, 40 | // R1(r**2) = 6/r *((exp(r)+1)/(exp(r)-1) - 2/r) 41 | // = 6/r * ( 1 + 2.0*(1/(exp(r)-1) - 1/r)) 42 | // = 1 - r**2/60 + r**4/2520 - r**6/100800 + ... 43 | // We use a special Reme algorithm on [0,0.347] to generate 44 | // a polynomial of degree 5 in r*r to approximate R1. The 45 | // maximum error of this polynomial approximation is bounded 46 | // by 2**-61. In other words, 47 | // R1(z) ~ 1.0 + Q1*z + Q2*z**2 + Q3*z**3 + Q4*z**4 + Q5*z**5 48 | // where Q1 = -1.6666666666666567384E-2, 49 | // Q2 = 3.9682539681370365873E-4, 50 | // Q3 = -9.9206344733435987357E-6, 51 | // Q4 = 2.5051361420808517002E-7, 52 | // Q5 = -6.2843505682382617102E-9; 53 | // (where z=r*r, and the values of Q1 to Q5 are listed below) 54 | // with error bounded by 55 | // | 5 | -61 56 | // | 1.0+Q1*z+...+Q5*z - R1(z) | <= 2 57 | // | | 58 | // 59 | // expm1(r) = exp(r)-1 is then computed by the following 60 | // specific way which minimize the accumulation rounding error: 61 | // 2 3 62 | // r r [ 3 - (R1 + R1*r/2) ] 63 | // expm1(r) = r + --- + --- * [--------------------] 64 | // 2 2 [ 6 - r*(3 - R1*r/2) ] 65 | // 66 | // To compensate the error in the argument reduction, we use 67 | // expm1(r+c) = expm1(r) + c + expm1(r)*c 68 | // ~ expm1(r) + c + r*c 69 | // Thus c+r*c will be added in as the correction terms for 70 | // expm1(r+c). Now rearrange the term to avoid optimization 71 | // screw up: 72 | // ( 2 2 ) 73 | // ({ ( r [ R1 - (3 - R1*r/2) ] ) } r ) 74 | // expm1(r+c)~r - ({r*(--- * [--------------------]-c)-c} - --- ) 75 | // ({ ( 2 [ 6 - r*(3 - R1*r/2) ] ) } 2 ) 76 | // ( ) 77 | // 78 | // = r - E 79 | // 3. Scale back to obtain expm1(x): 80 | // From step 1, we have 81 | // expm1(x) = either 2**k*[expm1(r)+1] - 1 82 | // = or 2**k*[expm1(r) + (1-2**-k)] 83 | // 4. Implementation notes: 84 | // (A). To save one multiplication, we scale the coefficient Qi 85 | // to Qi*2**i, and replace z by (x**2)/2. 86 | // (B). To achieve maximum accuracy, we compute expm1(x) by 87 | // (i) if x < -56*ln2, return -1.0, (raise inexact if x!=inf) 88 | // (ii) if k=0, return r-E 89 | // (iii) if k=-1, return 0.5*(r-E)-0.5 90 | // (iv) if k=1 if r < -0.25, return 2*((r+0.5)- E) 91 | // else return 1.0+2.0*(r-E); 92 | // (v) if (k<-2||k>56) return 2**k(1-(E-r)) - 1 (or exp(x)-1) 93 | // (vi) if k <= 20, return 2**k((1-2**-k)-(E-r)), else 94 | // (vii) return 2**k(1-((E+2**-k)-r)) 95 | // 96 | // Special cases: 97 | // expm1(INF) is INF, expm1(NaN) is NaN; 98 | // expm1(-INF) is -1, and 99 | // for finite argument, only expm1(0)=0 is exact. 100 | // 101 | // Accuracy: 102 | // according to an error analysis, the error is always less than 103 | // 1 ulp (unit in the last place). 104 | // 105 | // Misc. info. 106 | // For IEEE double 107 | // if x > 7.09782712893383973096e+02 then expm1(x) overflow 108 | // 109 | // Constants: 110 | // The hexadecimal values are the intended ones for the following 111 | // constants. The decimal values may be used, provided that the 112 | // compiler will convert from decimal to binary accurately enough 113 | // to produce the hexadecimal values shown. 114 | // 115 | 116 | // Expm1 returns e**x - 1, the base-e exponential of x minus 1. 117 | // It is more accurate than Exp(x) - 1 when x is near zero. 118 | // 119 | // Special cases are: 120 | // 121 | // Expm1(+Inf) = +Inf 122 | // Expm1(-Inf) = -1 123 | // Expm1(NaN) = NaN 124 | // 125 | // Very large values overflow to -1 or +Inf. 126 | func Expm1(x float32) float32 { 127 | return expm1(x) 128 | } 129 | 130 | func expm1(x float32) float32 { 131 | const ( 132 | Othreshold = 89.415985 // 0x42b2d4fc 133 | Ln2X27 = 1.871497344970703125e+01 // 0x4195b844 134 | Ln2HalfX3 = 1.0397207736968994140625 // 0x3F851592 135 | Ln2Half = 3.465735912322998046875e-01 // 0x3eb17218 136 | Ln2Hi = 6.9313812256e-01 // 0x3f317180 137 | Ln2Lo = 9.0580006145e-06 // 0x3717f7d1 138 | InvLn2 = 1.4426950216e+00 // 0x3fb8aa3b 139 | Tiny = 1.0 / (1 << 54) // 2**-54 = 0x3c90000000000000 140 | 141 | /* scaled coefficients related to expm1 */ 142 | Q1 = -3.3333335072e-02 /* 0xbd088889 */ 143 | Q2 = 1.5873016091e-03 /* 0x3ad00d01 */ 144 | Q3 = -7.9365076090e-05 /* 0xb8a670cd */ 145 | Q4 = 4.0082177293e-06 /* 0x36867e54 */ 146 | Q5 = -2.0109921195e-07 /* 0xb457edbb */ 147 | ) 148 | 149 | // special cases 150 | switch { 151 | case IsInf(x, 1) || IsNaN(x): 152 | return x 153 | case IsInf(x, -1): 154 | return -1 155 | } 156 | 157 | absx := x 158 | sign := false 159 | if x < 0 { 160 | absx = -absx 161 | sign = true 162 | } 163 | 164 | // filter out huge argument 165 | if absx >= Ln2X27 { // if |x| >= 27 * ln2 166 | if sign { 167 | return -1 // x < -56*ln2, return -1 168 | } 169 | if absx >= Othreshold { // if |x| >= 89.415985... 170 | return Inf(1) 171 | } 172 | } 173 | 174 | // argument reduction 175 | var c float32 176 | var k int 177 | if absx > Ln2Half { // if |x| > 0.5 * ln2 178 | var hi, lo float32 179 | if absx < Ln2HalfX3 { // and |x| < 1.5 * ln2 180 | if !sign { 181 | hi = x - Ln2Hi 182 | lo = Ln2Lo 183 | k = 1 184 | } else { 185 | hi = x + Ln2Hi 186 | lo = -Ln2Lo 187 | k = -1 188 | } 189 | } else { 190 | if !sign { 191 | k = int(InvLn2*x + 0.5) 192 | } else { 193 | k = int(InvLn2*x - 0.5) 194 | } 195 | t := float32(k) 196 | hi = x - t*Ln2Hi // t * Ln2Hi is exact here 197 | lo = t * Ln2Lo 198 | } 199 | x = hi - lo 200 | c = (hi - x) - lo 201 | } else if absx < Tiny { // when |x| < 2**-54, return x 202 | return x 203 | } else { 204 | k = 0 205 | } 206 | 207 | // x is now in primary range 208 | hfx := 0.5 * x 209 | hxs := x * hfx 210 | r1 := 1 + hxs*(Q1+hxs*(Q2+hxs*(Q3+hxs*(Q4+hxs*Q5)))) 211 | t := 3 - r1*hfx 212 | e := hxs * ((r1 - t) / (6.0 - x*t)) 213 | if k != 0 { 214 | e = (x*(e-c) - c) 215 | e -= hxs 216 | switch { 217 | case k == -1: 218 | return 0.5*(x-e) - 0.5 219 | case k == 1: 220 | if x < -0.25 { 221 | return -2 * (e - (x + 0.5)) 222 | } 223 | return 1 + 2*(x-e) 224 | case k <= -2 || k > 56: // suffice to return exp(x)-1 225 | y := 1 - (e - x) 226 | y = Float32frombits(Float32bits(y) + uint32(k)<<23) // add k to y's exponent 227 | return y - 1 228 | } 229 | if k < 20 { 230 | t := Float32frombits(0x3f800000 - (0x1000000 >> uint(k))) // t=1-2**-k 231 | y := t - (e - x) 232 | y = Float32frombits(Float32bits(y) + uint32(k)<<23) // add k to y's exponent 233 | return y 234 | } 235 | t := Float32frombits(uint32(0x7f-k) << 23) // 2**-k 236 | y := x - (e + t) 237 | y += 1 238 | y = Float32frombits(Float32bits(y) + uint32(k)<<23) // add k to y's exponent 239 | return y 240 | } 241 | return x - (x*e - hxs) // c is 0 242 | } 243 | -------------------------------------------------------------------------------- /export_test.go: -------------------------------------------------------------------------------- 1 | package math32 2 | 3 | // Export internal functions for testing. 4 | 5 | // var Exp2Go = exp2 6 | var SqrtGo = sqrt 7 | var ExpGo = exp 8 | var HypotGo = hypot 9 | -------------------------------------------------------------------------------- /floor.go: -------------------------------------------------------------------------------- 1 | package math32 2 | 3 | // Floor returns the greatest integer value less than or equal to x. 4 | // 5 | // Special cases are: 6 | // 7 | // Floor(±0) = ±0 8 | // Floor(±Inf) = ±Inf 9 | // Floor(NaN) = NaN 10 | func Floor(x float32) float32 { 11 | return floor(x) 12 | } 13 | 14 | func floor(x float32) float32 { 15 | if x == 0 || IsNaN(x) || IsInf(x, 0) { 16 | return x 17 | } 18 | if x < 0 { 19 | d, fract := Modf(-x) 20 | if fract != 0.0 { 21 | d = d + 1 22 | } 23 | return -d 24 | } 25 | d, _ := Modf(x) 26 | return d 27 | } 28 | 29 | // Ceil returns the least integer value greater than or equal to x. 30 | // 31 | // Special cases are: 32 | // 33 | // Ceil(±0) = ±0 34 | // Ceil(±Inf) = ±Inf 35 | // Ceil(NaN) = NaN 36 | func Ceil(x float32) float32 { 37 | return ceil(x) 38 | } 39 | 40 | func ceil(x float32) float32 { 41 | return -Floor(-x) 42 | } 43 | 44 | // Trunc returns the integer value of x. 45 | // 46 | // Special cases are: 47 | // 48 | // Trunc(±0) = ±0 49 | // Trunc(±Inf) = ±Inf 50 | // Trunc(NaN) = NaN 51 | func Trunc(x float32) float32 { 52 | return trunc(x) 53 | } 54 | 55 | func trunc(x float32) float32 { 56 | if x == 0 || IsNaN(x) || IsInf(x, 0) { 57 | return x 58 | } 59 | d, _ := Modf(x) 60 | return d 61 | } 62 | -------------------------------------------------------------------------------- /frexp.go: -------------------------------------------------------------------------------- 1 | package math32 2 | 3 | // Frexp breaks f into a normalized fraction 4 | // and an integral power of two. 5 | // It returns frac and exp satisfying f == frac × 2**exp, 6 | // with the absolute value of frac in the interval [½, 1). 7 | // 8 | // Special cases are: 9 | // 10 | // Frexp(±0) = ±0, 0 11 | // Frexp(±Inf) = ±Inf, 0 12 | // Frexp(NaN) = NaN, 0 13 | func Frexp(f float32) (frac float32, exp int) { 14 | return frexp(f) 15 | } 16 | 17 | func frexp(f float32) (frac float32, exp int) { 18 | // special cases 19 | switch { 20 | case f == 0: 21 | return f, 0 // correctly return -0 22 | case IsInf(f, 0) || IsNaN(f): 23 | return f, 0 24 | } 25 | f, exp = normalize(f) 26 | x := Float32bits(f) 27 | exp += int((x>>shift)&mask) - bias + 1 28 | x &^= mask << shift 29 | x |= (-1 + bias) << shift 30 | frac = Float32frombits(x) 31 | return 32 | } 33 | -------------------------------------------------------------------------------- /gamma.go: -------------------------------------------------------------------------------- 1 | package math32 2 | 3 | import "math" 4 | 5 | // Gamma returns the Gamma function of x. 6 | // 7 | // Special cases are: 8 | // 9 | // Gamma(+Inf) = +Inf 10 | // Gamma(+0) = +Inf 11 | // Gamma(-0) = -Inf 12 | // Gamma(x) = NaN for integer x < 0 13 | // Gamma(-Inf) = NaN 14 | // Gamma(NaN) = NaN 15 | func Gamma(x float32) float32 { 16 | return float32(math.Gamma(float64(x))) 17 | } 18 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/chewxy/math32 2 | 3 | go 1.13 4 | -------------------------------------------------------------------------------- /hypot.go: -------------------------------------------------------------------------------- 1 | package math32 2 | 3 | /* 4 | Hypot -- sqrt(p*p + q*q), but overflows only if the result does. 5 | */ 6 | 7 | // Hypot returns Sqrt(p*p + q*q), taking care to avoid 8 | // unnecessary overflow and underflow. 9 | // 10 | // Special cases are: 11 | // 12 | // Hypot(±Inf, q) = +Inf 13 | // Hypot(p, ±Inf) = +Inf 14 | // Hypot(NaN, q) = NaN 15 | // Hypot(p, NaN) = NaN 16 | func Hypot(p, q float32) float32 { 17 | return hypot(p, q) 18 | } 19 | 20 | func hypot(p, q float32) float32 { 21 | // special cases 22 | switch { 23 | case IsInf(p, 0) || IsInf(q, 0): 24 | return Inf(1) 25 | case IsNaN(p) || IsNaN(q): 26 | return NaN() 27 | } 28 | if p < 0 { 29 | p = -p 30 | } 31 | if q < 0 { 32 | q = -q 33 | } 34 | if p < q { 35 | p, q = q, p 36 | } 37 | if p == 0 { 38 | return 0 39 | } 40 | q = q / p 41 | return p * Sqrt(1+q*q) 42 | } 43 | -------------------------------------------------------------------------------- /j0.go: -------------------------------------------------------------------------------- 1 | package math32 2 | 3 | import "math" 4 | 5 | // J0 returns the order-zero Bessel function of the first kind. 6 | // 7 | // Special cases are: 8 | // 9 | // J0(±Inf) = 0 10 | // J0(0) = 1 11 | // J0(NaN) = NaN 12 | func J0(x float32) float32 { 13 | return float32(math.J0(float64(x))) 14 | } 15 | -------------------------------------------------------------------------------- /j1.go: -------------------------------------------------------------------------------- 1 | package math32 2 | 3 | import "math" 4 | 5 | // J1 returns the order-one Bessel function of the first kind. 6 | // 7 | // Special cases are: 8 | // 9 | // J1(±Inf) = 0 10 | // J1(NaN) = NaN 11 | func J1(x float32) float32 { 12 | return float32(math.J1(float64(x))) 13 | } 14 | -------------------------------------------------------------------------------- /jn.go: -------------------------------------------------------------------------------- 1 | package math32 2 | 3 | import "math" 4 | 5 | // Jn returns the order-n Bessel function of the first kind. 6 | // 7 | // Special cases are: 8 | // 9 | // Jn(n, ±Inf) = 0 10 | // Jn(n, NaN) = NaN 11 | func Jn(n int, x float32) float32 { 12 | return float32(math.Jn(n, float64(x))) 13 | } 14 | 15 | // Yn returns the order-n Bessel function of the second kind. 16 | // 17 | // Special cases are: 18 | // 19 | // Yn(n, +Inf) = 0 20 | // Yn(n ≥ 0, 0) = -Inf 21 | // Yn(n < 0, 0) = +Inf if n is odd, -Inf if n is even 22 | // Yn(n, x < 0) = NaN 23 | // Yn(n, NaN) = NaN 24 | func Yn(n int, x float32) float32 { 25 | return float32(math.Yn(n, float64(x))) 26 | } 27 | -------------------------------------------------------------------------------- /ldexp.go: -------------------------------------------------------------------------------- 1 | package math32 2 | 3 | // Ldexp is the inverse of Frexp. 4 | // It returns frac × 2**exp. 5 | // 6 | // Special cases are: 7 | // 8 | // Ldexp(±0, exp) = ±0 9 | // Ldexp(±Inf, exp) = ±Inf 10 | // Ldexp(NaN, exp) = NaN 11 | func Ldexp(frac float32, exp int) float32 { 12 | return ldexp(frac, exp) 13 | } 14 | 15 | func ldexp(frac float32, exp int) float32 { 16 | // special cases 17 | switch { 18 | case frac == 0: 19 | return frac // correctly return -0 20 | case IsInf(frac, 0) || IsNaN(frac): 21 | return frac 22 | } 23 | frac, e := normalize(frac) 24 | exp += e 25 | x := Float32bits(frac) 26 | exp += int(x>>shift)&mask - bias 27 | if exp < -149 { 28 | return Copysign(0, frac) // underflow 29 | } 30 | if exp > 127 { // overflow 31 | if frac < 0 { 32 | return Inf(-1) 33 | } 34 | return Inf(1) 35 | } 36 | var m float32 = 1 37 | if exp < -(127 - 1) { // denormal 38 | exp += shift 39 | m = 1.0 / (1 << 23) // 1/(2**-23) 40 | } 41 | x &^= mask << shift 42 | x |= uint32(exp+bias) << shift 43 | return m * Float32frombits(x) 44 | } 45 | -------------------------------------------------------------------------------- /lgamma.go: -------------------------------------------------------------------------------- 1 | package math32 2 | 3 | import "math" 4 | 5 | // Lgamma returns the natural logarithm and sign (-1 or +1) of [Gamma](x). 6 | // 7 | // Special cases are: 8 | // 9 | // Lgamma(+Inf) = +Inf 10 | // Lgamma(0) = +Inf 11 | // Lgamma(-integer) = +Inf 12 | // Lgamma(-Inf) = -Inf 13 | // Lgamma(NaN) = NaN 14 | func Lgamma(x float32) (lgamma float32, sign int) { 15 | lg, sign := math.Lgamma(float64(x)) 16 | return float32(lg), sign 17 | } 18 | -------------------------------------------------------------------------------- /log.go: -------------------------------------------------------------------------------- 1 | package math32 2 | 3 | /* 4 | Floating-point logarithm. 5 | */ 6 | 7 | // The original C code, the long comment, and the constants 8 | // below are from FreeBSD's /usr/src/lib/msun/src/e_log.c 9 | // and came with this notice. The go code is a simpler 10 | // version of the original C. 11 | // 12 | // ==================================================== 13 | // Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. 14 | // 15 | // Developed at SunPro, a Sun Microsystems, Inc. business. 16 | // Permission to use, copy, modify, and distribute this 17 | // software is freely granted, provided that this notice 18 | // is preserved. 19 | // ==================================================== 20 | // 21 | // __ieee754_log(x) 22 | // Return the logarithm of x 23 | // 24 | // Method : 25 | // 1. Argument Reduction: find k and f such that 26 | // x = 2**k * (1+f), 27 | // where sqrt(2)/2 < 1+f < sqrt(2) . 28 | // 29 | // 2. Approximation of log(1+f). 30 | // Let s = f/(2+f) ; based on log(1+f) = log(1+s) - log(1-s) 31 | // = 2s + 2/3 s**3 + 2/5 s**5 + ....., 32 | // = 2s + s*R 33 | // We use a special Reme algorithm on [0,0.1716] to generate 34 | // a polynomial of degree 14 to approximate R. The maximum error 35 | // of this polynomial approximation is bounded by 2**-58.45. In 36 | // other words, 37 | // 2 4 6 8 10 12 14 38 | // R(z) ~ L1*s +L2*s +L3*s +L4*s +L5*s +L6*s +L7*s 39 | // (the values of L1 to L7 are listed in the program) and 40 | // | 2 14 | -58.45 41 | // | L1*s +...+L7*s - R(z) | <= 2 42 | // | | 43 | // Note that 2s = f - s*f = f - hfsq + s*hfsq, where hfsq = f*f/2. 44 | // In order to guarantee error in log below 1ulp, we compute log by 45 | // log(1+f) = f - s*(f - R) (if f is not too large) 46 | // log(1+f) = f - (hfsq - s*(hfsq+R)). (better accuracy) 47 | // 48 | // 3. Finally, log(x) = k*Ln2 + log(1+f). 49 | // = k*Ln2_hi+(f-(hfsq-(s*(hfsq+R)+k*Ln2_lo))) 50 | // Here Ln2 is split into two floating point number: 51 | // Ln2_hi + Ln2_lo, 52 | // where n*Ln2_hi is always exact for |n| < 2000. 53 | // 54 | // Special cases: 55 | // log(x) is NaN with signal if x < 0 (including -INF) ; 56 | // log(+INF) is +INF; log(0) is -INF with signal; 57 | // log(NaN) is that NaN with no signal. 58 | // 59 | // Accuracy: 60 | // according to an error analysis, the error is always less than 61 | // 1 ulp (unit in the last place). 62 | // 63 | // Constants: 64 | // The hexadecimal values are the intended ones for the following 65 | // constants. The decimal values may be used, provided that the 66 | // compiler will convert from decimal to binary accurately enough 67 | // to produce the hexadecimal values shown. 68 | 69 | // Log returns the natural logarithm of x. 70 | // 71 | // Special cases are: 72 | // 73 | // Log(+Inf) = +Inf 74 | // Log(0) = -Inf 75 | // Log(x < 0) = NaN 76 | // Log(NaN) = NaN 77 | func Log(x float32) float32 { 78 | if haveArchLog { 79 | return archLog(x) 80 | } 81 | return log(x) 82 | } 83 | 84 | func log(x float32) float32 { 85 | const ( 86 | Ln2Hi = 6.9313812256e-01 /* 0x3f317180 */ 87 | Ln2Lo = 9.0580006145e-06 /* 0x3717f7d1 */ 88 | L1 = 6.6666668653e-01 /* 0x3f2aaaab */ 89 | L2 = 4.0000000596e-01 /* 0x3ecccccd */ 90 | L3 = 2.8571429849e-01 /* 0x3e924925 */ 91 | L4 = 2.2222198546e-01 /* 0x3e638e29 */ 92 | L5 = 1.8183572590e-01 /* 0x3e3a3325 */ 93 | L6 = 1.5313838422e-01 /* 0x3e1cd04f */ 94 | L7 = 1.4798198640e-01 /* 0x3e178897 */ 95 | ) 96 | 97 | // special cases 98 | switch { 99 | case IsNaN(x) || IsInf(x, 1): 100 | return x 101 | case x < 0: 102 | return NaN() 103 | case x == 0: 104 | return Inf(-1) 105 | } 106 | 107 | // reduce 108 | f1, ki := Frexp(x) 109 | if f1 < Sqrt2/2 { 110 | f1 *= 2 111 | ki-- 112 | } 113 | f := f1 - 1 114 | k := float32(ki) 115 | 116 | // compute 117 | s := f / (2 + f) 118 | s2 := s * s 119 | s4 := s2 * s2 120 | t1 := s2 * (L1 + s4*(L3+s4*(L5+s4*L7))) 121 | t2 := s4 * (L2 + s4*(L4+s4*L6)) 122 | R := t1 + t2 123 | hfsq := 0.5 * f * f 124 | return k*Ln2Hi - ((hfsq - (s*(hfsq+R) + k*Ln2Lo)) - f) 125 | } 126 | -------------------------------------------------------------------------------- /log10.go: -------------------------------------------------------------------------------- 1 | package math32 2 | 3 | import "math" 4 | 5 | // Log10 returns the decimal logarithm of x. 6 | // The special cases are the same as for [Log]. 7 | func Log10(x float32) float32 { 8 | return float32(math.Log10(float64(x))) 9 | } 10 | -------------------------------------------------------------------------------- /log1p.go: -------------------------------------------------------------------------------- 1 | package math32 2 | 3 | import "math" 4 | 5 | // Log1p returns the natural logarithm of 1 plus its argument x. 6 | // It is more accurate than [Log](1 + x) when x is near zero. 7 | // 8 | // Special cases are: 9 | // 10 | // Log1p(+Inf) = +Inf 11 | // Log1p(±0) = ±0 12 | // Log1p(-1) = -Inf 13 | // Log1p(x < -1) = NaN 14 | // Log1p(NaN) = NaN 15 | func Log1p(x float32) float32 { 16 | return float32(math.Log1p(float64(x))) 17 | } 18 | -------------------------------------------------------------------------------- /log2.go: -------------------------------------------------------------------------------- 1 | package math32 2 | 3 | import "math" 4 | 5 | // Log2 returns the binary logarithm of x. 6 | // The special cases are the same as for [Log]. 7 | func Log2(x float32) float32 { 8 | return float32(math.Log2(float64(x))) 9 | } 10 | -------------------------------------------------------------------------------- /log_amd64.s: -------------------------------------------------------------------------------- 1 | //go:build !tinygo && !noasm 2 | // Copyright 2010 The Go Authors. All rights reserved. 3 | // Use of this source code is governed by a BSS-style 4 | // license that can be found in the LICENSE file. 5 | 6 | #include "textflag.h" 7 | 8 | #define HSqrt2 7.07106781186547524401e-01 // sqrt(2)/2 9 | #define Ln2Hi 6.9313812256e-01 // 0x3f317180 10 | #define Ln2Lo 9.0580006145e-06 // 0x3717f7d1 11 | #define L1 6.6666668653e-01 // 0x3f2aaaab 12 | #define L2 4.0000000596e-01 // 0x3ecccccd 13 | #define L3 2.8571429849e-01 // 0x3e924925 14 | #define L4 2.2222198546e-01 // 0x3e638e29 15 | #define L5 1.8183572590e-01 // 0x3e3a3325 16 | #define L6 1.5313838422e-01 // 0x3e1cd04f 17 | #define L7 1.4798198640e-01 // 0x3e178897 18 | #define NaN 0x7FE00000 19 | #define PosInf 0x7F800000 20 | #define NegInf 0xFF800000 21 | 22 | // func archLog(x float64) float64 23 | TEXT ·archLog(SB),NOSPLIT,$0 24 | // test bits for special cases 25 | MOVL x+0(FP), BX 26 | MOVQ $~(1<<31), AX // sign bit mask 27 | ANDQ BX, AX 28 | JEQ isZero 29 | MOVL $0, AX 30 | CMPL AX, BX 31 | JGT isNegative 32 | MOVL $PosInf, AX 33 | CMPQ AX, BX 34 | JLE isInfOrNaN 35 | // f1, ki := math.Frexp(x); k := float64(ki) 36 | MOVL BX, X0 37 | MOVL $0x007FFFFF, AX 38 | MOVL AX, X2 39 | ANDPS X0, X2 40 | MOVSS $0.5, X0 // 0x3FE0000000000000 41 | ORPS X0, X2 // X2= f1 42 | SHRQ $23, BX 43 | ANDL $0xFF, BX 44 | SUBL $0x7E, BX 45 | CVTSL2SS BX, X1 // x1= k, x2= f1 46 | // if f1 < math.Sqrt2/2 { k -= 1; f1 *= 2 } 47 | MOVSS $HSqrt2, X0 // x0= 0.7071, x1= k, x2= f1 48 | CMPSS X2, X0, 5 // cmpnlt; x0= 0 or ^0, x1= k, x2 = f1 49 | MOVSS $1.0, X3 // x0= 0 or ^0, x1= k, x2 = f1, x3= 1 50 | ANDPS X0, X3 // x0= 0 or ^0, x1= k, x2 = f1, x3= 0 or 1 51 | SUBSS X3, X1 // x0= 0 or ^0, x1= k, x2 = f1, x3= 0 or 1 52 | MOVSS $1.0, X0 // x0= 1, x1= k, x2= f1, x3= 0 or 1 53 | ADDSS X0, X3 // x0= 1, x1= k, x2= f1, x3= 1 or 2 54 | MULSS X3, X2 // x0= 1, x1= k, x2= f1 55 | // f := f1 - 1 56 | SUBSS X0, X2 // x1= k, x2= f 57 | // s := f / (2 + f) 58 | MOVSS $2.0, X0 59 | ADDSS X2, X0 60 | MOVUPS X2, X3 61 | DIVSS X0, X3 // x1=k, x2= f, x3= s 62 | // s2 := s * s 63 | MOVUPS X3, X4 // x1= k, x2= f, x3= s 64 | MULSS X4, X4 // x1= k, x2= f, x3= s, x4= s2 65 | // s4 := s2 * s2 66 | MOVUPS X4, X5 // x1= k, x2= f, x3= s, x4= s2 67 | MULSS X5, X5 // x1= k, x2= f, x3= s, x4= s2, x5= s4 68 | // t1 := s2 * (L1 + s4*(L3+s4*(L5+s4*L7))) 69 | MOVSS $L7, X6 70 | MULSS X5, X6 71 | ADDSS $L5, X6 72 | MULSS X5, X6 73 | ADDSS $L3, X6 74 | MULSS X5, X6 75 | ADDSS $L1, X6 76 | MULSS X6, X4 // x1= k, x2= f, x3= s, x4= t1, x5= s4 77 | // t2 := s4 * (L2 + s4*(L4+s4*L6)) 78 | MOVSS $L6, X6 79 | MULSS X5, X6 80 | ADDSS $L4, X6 81 | MULSS X5, X6 82 | ADDSS $L2, X6 83 | MULSS X6, X5 // x1= k, x2= f, x3= s, x4= t1, x5= t2 84 | // R := t1 + t2 85 | ADDSS X5, X4 // x1= k, x2= f, x3= s, x4= R 86 | // hfsq := 0.5 * f * f 87 | MOVSS $0.5, X0 88 | MULSS X2, X0 89 | MULSS X2, X0 // x0= hfsq, x1= k, x2= f, x3= s, x4= R 90 | // return k*Ln2Hi - ((hfsq - (s*(hfsq+R) + k*Ln2Lo)) - f) 91 | ADDSS X0, X4 // x0= hfsq, x1= k, x2= f, x3= s, x4= hfsq+R 92 | MULSS X4, X3 // x0= hfsq, x1= k, x2= f, x3= s*(hfsq+R) 93 | MOVSS $Ln2Lo, X4 94 | MULSS X1, X4 // x4= k*Ln2Lo 95 | ADDSS X4, X3 // x0= hfsq, x1= k, x2= f, x3= s*(hfsq+R)+k*Ln2Lo 96 | SUBSS X3, X0 // x0= hfsq-(s*(hfsq+R)+k*Ln2Lo), x1= k, x2= f 97 | SUBSS X2, X0 // x0= (hfsq-(s*(hfsq+R)+k*Ln2Lo))-f, x1= k 98 | MULSS $Ln2Hi, X1 // x0= (hfsq-(s*(hfsq+R)+k*Ln2Lo))-f, x1= k*Ln2Hi 99 | SUBSS X0, X1 // x1= k*Ln2Hi-((hfsq-(s*(hfsq+R)+k*Ln2Lo))-f) 100 | MOVSS X1, ret+8(FP) 101 | RET 102 | isInfOrNaN: 103 | MOVL BX, ret+8(FP) // +Inf or NaN, return x 104 | RET 105 | isNegative: 106 | MOVL $NaN, AX 107 | MOVL AX, ret+8(FP) // return NaN 108 | RET 109 | isZero: 110 | MOVL $NegInf, AX 111 | MOVL AX, ret+8(FP) // return -Inf 112 | RET 113 | -------------------------------------------------------------------------------- /log_asm.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | //go:build !noasm && !tinygo && (amd64 || arm || s390x || 386 || arm64 || ppc64le || wasm) 6 | // +build !noasm 7 | // +build !tinygo 8 | // +build amd64 arm s390x 386 arm64 ppc64le wasm 9 | 10 | package math32 11 | 12 | const haveArchLog = true 13 | 14 | func archLog(x float32) float32 15 | -------------------------------------------------------------------------------- /log_noasm.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | //go:build noasm || tinygo || (!amd64 && !arm && !s390x && !386 && !arm64 && !ppc64le && !wasm) 6 | // +build noasm tinygo !amd64,!arm,!s390x,!386,!arm64,!ppc64le,!wasm 7 | 8 | package math32 9 | 10 | const haveArchLog = false 11 | 12 | func archLog(x float32) float32 { 13 | panic("not implemented") 14 | } 15 | -------------------------------------------------------------------------------- /logb.go: -------------------------------------------------------------------------------- 1 | package math32 2 | 3 | import "math" 4 | 5 | // Logb returns the binary exponent of x. 6 | // 7 | // Special cases are: 8 | // 9 | // Logb(±Inf) = +Inf 10 | // Logb(0) = -Inf 11 | // Logb(NaN) = NaN 12 | func Logb(x float32) float32 { 13 | return float32(math.Logb(float64(x))) 14 | } 15 | 16 | // Ilogb returns the binary exponent of x as an integer. 17 | // 18 | // Special cases are: 19 | // 20 | // Ilogb(±Inf) = MaxInt32 21 | // Ilogb(0) = MinInt32 22 | // Ilogb(NaN) = MaxInt32 23 | func Ilogb(x float32) int { 24 | return math.Ilogb(float64(x)) 25 | } 26 | -------------------------------------------------------------------------------- /math32_test.go: -------------------------------------------------------------------------------- 1 | //go:build !tinygo 2 | // +build !tinygo 3 | 4 | package math32 5 | 6 | import ( 7 | "fmt" 8 | "os" 9 | "os/exec" 10 | "testing" 11 | ) 12 | 13 | func TestVetMath32(t *testing.T) { 14 | linuxArches := []string{"amd64", "arm", "arm64", "s390x", "ppc64le", "riscv64", "386", "mips", "mips64", "mipsle", "mips64le"} 15 | 16 | // Linux architectures 17 | for _, GOARCH := range linuxArches { 18 | GOOS := "linux" 19 | t.Run(fmt.Sprintf("GOOS=%s GOARCH=%s", GOOS, GOARCH), func(t *testing.T) { 20 | goVet(t, GOOS, GOARCH) 21 | goBuildVet(t, GOOS, GOARCH) 22 | }) 23 | } 24 | // WASM 25 | t.Run("GOOS=js GOARCH=wasm", func(t *testing.T) { 26 | goVet(t, "js", "wasm") 27 | goBuildVet(t, "js", "wasm") 28 | }) 29 | 30 | // AIX 31 | t.Run("GOOS=aix GOARCH=ppc64", func(t *testing.T) { 32 | goVet(t, "aix", "ppc64") 33 | goBuildVet(t, "aix", "ppc64") 34 | }) 35 | } 36 | 37 | func goVet(t *testing.T, GOOS, GOARCH string) { 38 | env := append(os.Environ(), "GOOS="+GOOS, "GOARCH="+GOARCH) 39 | cmd := exec.Command("go", "vet", ".") 40 | cmd.Env = env 41 | output, err := cmd.CombinedOutput() 42 | if err != nil { 43 | t.Error(string(output), err) 44 | } 45 | } 46 | 47 | func goBuildVet(t *testing.T, GOOS, GOARCH string) { 48 | env := append(os.Environ(), "GOOS="+GOOS, "GOARCH="+GOARCH) 49 | const buildname = "math32.test" 50 | defer os.Remove(buildname) 51 | cmd := exec.Command("go", "test", "-c", "-o="+buildname) 52 | cmd.Env = env 53 | output, err := cmd.CombinedOutput() 54 | if err != nil { 55 | t.Error(string(output), err) 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /mod.go: -------------------------------------------------------------------------------- 1 | package math32 2 | 3 | // Mod returns the floating-point remainder of x/y. 4 | // The magnitude of the result is less than y and its 5 | // sign agrees with that of x. 6 | // 7 | // Special cases are: 8 | // 9 | // Mod(±Inf, y) = NaN 10 | // Mod(NaN, y) = NaN 11 | // Mod(x, 0) = NaN 12 | // Mod(x, ±Inf) = x 13 | // Mod(x, NaN) = NaN 14 | func Mod(x, y float32) float32 { 15 | return mod(x, y) 16 | } 17 | 18 | func mod(x, y float32) float32 { 19 | if y == 0 || IsInf(x, 0) || IsNaN(x) || IsNaN(y) { 20 | return NaN() 21 | } 22 | if y < 0 { 23 | y = -y 24 | } 25 | 26 | yfr, yexp := Frexp(y) 27 | sign := false 28 | r := x 29 | if x < 0 { 30 | r = -x 31 | sign = true 32 | } 33 | 34 | for r >= y { 35 | rfr, rexp := Frexp(r) 36 | if rfr < yfr { 37 | rexp = rexp - 1 38 | } 39 | r = r - Ldexp(y, rexp-yexp) 40 | } 41 | if sign { 42 | r = -r 43 | } 44 | return r 45 | } 46 | -------------------------------------------------------------------------------- /modf.go: -------------------------------------------------------------------------------- 1 | package math32 2 | 3 | // Modf returns integer and fractional floating-point numbers 4 | // that sum to f. Both values have the same sign as f. 5 | // 6 | // Special cases are: 7 | // 8 | // Modf(±Inf) = ±Inf, NaN 9 | // Modf(NaN) = NaN, NaN 10 | func Modf(f float32) (int float32, frac float32) { 11 | return modf(f) 12 | } 13 | 14 | func modf(f float32) (int float32, frac float32) { 15 | if f < 1 { 16 | switch { 17 | case f < 0: 18 | int, frac = Modf(-f) 19 | return -int, -frac 20 | case f == 0: 21 | return f, f // Return -0, -0 when f == -0 22 | } 23 | return 0, f 24 | } 25 | 26 | x := Float32bits(f) 27 | e := uint(x>>shift)&mask - bias 28 | 29 | // Keep the top 9+e bits, the integer part; clear the rest. 30 | if e < 32-9 { 31 | x &^= 1<<(32-9-e) - 1 32 | } 33 | int = Float32frombits(x) 34 | frac = f - int 35 | return 36 | } 37 | -------------------------------------------------------------------------------- /nextafter.go: -------------------------------------------------------------------------------- 1 | // Copyright 2010 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package math32 6 | 7 | // Nextafter returns the next representable float32 value after x towards y. 8 | // 9 | // Special cases are: 10 | // 11 | // Nextafter32(x, x) = x 12 | // Nextafter32(NaN, y) = NaN 13 | // Nextafter32(x, NaN) = NaN 14 | func Nextafter(x, y float32) (r float32) { 15 | switch { 16 | case IsNaN(x) || IsNaN(y): // special case 17 | r = float32(NaN()) 18 | case x == y: 19 | r = x 20 | case x == 0: 21 | r = float32(Copysign(Float32frombits(1), y)) 22 | case (y > x) == (x > 0): 23 | r = Float32frombits(Float32bits(x) + 1) 24 | default: 25 | r = Float32frombits(Float32bits(x) - 1) 26 | } 27 | return 28 | } 29 | -------------------------------------------------------------------------------- /pow.go: -------------------------------------------------------------------------------- 1 | package math32 2 | 3 | import "math" 4 | 5 | func isOddInt(x float32) bool { 6 | xi, xf := Modf(x) 7 | return xf == 0 && int32(xi)&1 == 1 8 | } 9 | 10 | // Special cases taken from FreeBSD's /usr/src/lib/msun/src/e_pow.c 11 | // updated by IEEE Std. 754-2008 "Section 9.2.1 Special values". 12 | 13 | // Pow returns x**y, the base-x exponential of y. 14 | // 15 | // Special cases are (in order): 16 | // 17 | // Pow(x, ±0) = 1 for any x 18 | // Pow(1, y) = 1 for any y 19 | // Pow(x, 1) = x for any x 20 | // Pow(NaN, y) = NaN 21 | // Pow(x, NaN) = NaN 22 | // Pow(±0, y) = ±Inf for y an odd integer < 0 23 | // Pow(±0, -Inf) = +Inf 24 | // Pow(±0, +Inf) = +0 25 | // Pow(±0, y) = +Inf for finite y < 0 and not an odd integer 26 | // Pow(±0, y) = ±0 for y an odd integer > 0 27 | // Pow(±0, y) = +0 for finite y > 0 and not an odd integer 28 | // Pow(-1, ±Inf) = 1 29 | // Pow(x, +Inf) = +Inf for |x| > 1 30 | // Pow(x, -Inf) = +0 for |x| > 1 31 | // Pow(x, +Inf) = +0 for |x| < 1 32 | // Pow(x, -Inf) = +Inf for |x| < 1 33 | // Pow(+Inf, y) = +Inf for y > 0 34 | // Pow(+Inf, y) = +0 for y < 0 35 | // Pow(-Inf, y) = Pow(-0, -y) 36 | // Pow(x, y) = NaN for finite x < 0 and finite non-integer y 37 | func Pow(x, y float32) float32 { 38 | switch { 39 | case y == 0 || x == 1: 40 | return 1 41 | case y == 1: 42 | return x 43 | case y == 0.5: 44 | return Sqrt(x) 45 | case y == -0.5: 46 | return 1 / Sqrt(x) 47 | case IsNaN(x) || IsNaN(y): 48 | return NaN() 49 | case x == 0: 50 | switch { 51 | case y < 0: 52 | if isOddInt(y) { 53 | return Copysign(Inf(1), x) 54 | } 55 | return Inf(1) 56 | case y > 0: 57 | if isOddInt(y) { 58 | return x 59 | } 60 | return 0 61 | } 62 | case IsInf(y, 0): 63 | switch { 64 | case x == -1: 65 | return 1 66 | case (Abs(x) < 1) == IsInf(y, 1): 67 | return 0 68 | default: 69 | return Inf(1) 70 | } 71 | case IsInf(x, 0): 72 | if IsInf(x, -1) { 73 | return Pow(1./x, -y) // Pow(-0, -y) 74 | } 75 | switch { 76 | case y < 0: 77 | return 0 78 | case y > 0: 79 | return Inf(1) 80 | } 81 | } 82 | 83 | absy := y 84 | flip := false 85 | if absy < 0 { 86 | absy = -absy 87 | flip = true 88 | } 89 | yi, yf := Modf(absy) 90 | if yf != 0 && x < 0 { 91 | return NaN() 92 | } 93 | if yi >= 1<<31 { 94 | return Exp(y * Log(x)) 95 | } 96 | 97 | // ans = a1 * 2**ae (= 1 for now). 98 | a1 := float32(1.0) 99 | ae := 0 100 | 101 | // ans *= x**yf 102 | if yf != 0 { 103 | if yf > 0.5 { 104 | yf-- 105 | yi++ 106 | } 107 | a1 = Exp(yf * Log(x)) 108 | } 109 | 110 | // ans *= x**yi 111 | // by multiplying in successive squarings 112 | // of x according to bits of yi. 113 | // accumulate powers of two into exp. 114 | x1, xe := Frexp(x) 115 | for i := int32(yi); i != 0; i >>= 1 { 116 | if i&1 == 1 { 117 | a1 *= x1 118 | ae += xe 119 | } 120 | x1 *= x1 121 | xe <<= 1 122 | if x1 < .5 { 123 | x1 += x1 124 | xe-- 125 | } 126 | } 127 | 128 | // ans = a1*2**ae 129 | // if flip { ans = 1 / ans } 130 | // but in the opposite order 131 | if flip { 132 | a1 = 1 / a1 133 | ae = -ae 134 | } 135 | return Ldexp(a1, ae) 136 | } 137 | 138 | func Pow10(e int) float32 { 139 | return float32(math.Pow10(e)) 140 | } 141 | -------------------------------------------------------------------------------- /remainder.go: -------------------------------------------------------------------------------- 1 | package math32 2 | 3 | // The original C code and the comment below are from 4 | // FreeBSD's /usr/src/lib/msun/src/e_remainder.c and came 5 | // with this notice. The go code is a simplified version of 6 | // the original C. 7 | // 8 | // ==================================================== 9 | // Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. 10 | // 11 | // Developed at SunPro, a Sun Microsystems, Inc. business. 12 | // Permission to use, copy, modify, and distribute this 13 | // software is freely granted, provided that this notice 14 | // is preserved. 15 | // ==================================================== 16 | // 17 | // __ieee754_remainder(x,y) 18 | // Return : 19 | // returns x REM y = x - [x/y]*y as if in infinite 20 | // precision arithmetic, where [x/y] is the (infinite bit) 21 | // integer nearest x/y (in half way cases, choose the even one). 22 | // Method : 23 | // Based on Mod() returning x - [x/y]chopped * y exactly. 24 | 25 | // Remainder returns the IEEE 754 floating-point remainder of x/y. 26 | // 27 | // Special cases are: 28 | // 29 | // Remainder(±Inf, y) = NaN 30 | // Remainder(NaN, y) = NaN 31 | // Remainder(x, 0) = NaN 32 | // Remainder(x, ±Inf) = x 33 | // Remainder(x, NaN) = NaN 34 | func Remainder(x, y float32) float32 { 35 | if haveArchRemainder { 36 | return archRemainder(x, y) 37 | } 38 | return remainder(x, y) 39 | } 40 | 41 | func remainder(x, y float32) float32 { 42 | 43 | // special cases 44 | switch { 45 | case IsNaN(x) || IsNaN(y) || IsInf(x, 0) || y == 0: 46 | return NaN() 47 | case IsInf(y, 0): 48 | return x 49 | } 50 | 51 | hx := Float32bits(x) 52 | hy := Float32bits(y) 53 | 54 | hy &= 0x7fffffff 55 | hx &= 0x7fffffff 56 | 57 | if hy <= 0x7effffff { 58 | x = Mod(x, y+y) // now x < 2y 59 | } 60 | 61 | if hx-hy == 0 { 62 | return 0 63 | } 64 | 65 | sign := false 66 | if x < 0 { 67 | x = -x 68 | sign = true 69 | } 70 | 71 | if y < 0 { 72 | y = -y 73 | } 74 | 75 | if hy < 0x01000000 { 76 | if x+x > y { 77 | x -= y 78 | if x+x >= y { 79 | x -= y 80 | } 81 | } 82 | } else { 83 | yHalf := 0.5 * y 84 | if x > yHalf { 85 | x -= y 86 | if x >= yHalf { 87 | x -= y 88 | } 89 | } 90 | } 91 | 92 | if sign { 93 | x = -x 94 | } 95 | return x 96 | } 97 | -------------------------------------------------------------------------------- /remainder_amd64.s: -------------------------------------------------------------------------------- 1 | //go:build !tinygo && !noasm 2 | // Copyright 2011 The Go Authors. All rights reserved. 3 | // Use of this source code is governed by a BSD-style 4 | // license that can be found in the LICENSE file. 5 | 6 | #include "textflag.h" 7 | 8 | TEXT ·archRemainder(SB),NOSPLIT,$0 9 | JMP ·remainder(SB) 10 | -------------------------------------------------------------------------------- /remainder_asm.go: -------------------------------------------------------------------------------- 1 | //go:build !noasm && !tinygo && (amd64 || s390x || arm || ppc64le || 386 || wasm) 2 | // +build !noasm 3 | // +build !tinygo 4 | // +build amd64 s390x arm ppc64le 386 wasm 5 | 6 | package math32 7 | 8 | const haveArchRemainder = true 9 | 10 | func archRemainder(x, y float32) float32 11 | -------------------------------------------------------------------------------- /remainder_noasm.go: -------------------------------------------------------------------------------- 1 | //go:build noasm || tinygo || (!amd64 && !s390x && !arm && !ppc64le && !386 && !wasm) 2 | // +build noasm tinygo !amd64,!s390x,!arm,!ppc64le,!386,!wasm 3 | 4 | package math32 5 | 6 | const haveArchRemainder = false 7 | 8 | func archRemainder(x, y float32) float32 { 9 | panic("not implemented") 10 | } 11 | -------------------------------------------------------------------------------- /round.go: -------------------------------------------------------------------------------- 1 | package math32 2 | 3 | // Round returns the nearest integer, rounding half away from zero. 4 | // 5 | // Special cases are: 6 | // 7 | // Round(±0) = ±0 8 | // Round(±Inf) = ±Inf 9 | // Round(NaN) = NaN 10 | func Round(x float32) float32 { 11 | // Round is a faster implementation of: 12 | // 13 | // func Round(x float64) float64 { 14 | // t := Trunc(x) 15 | // if Abs(x-t) >= 0.5 { 16 | // return t + Copysign(1, x) 17 | // } 18 | // return t 19 | // } 20 | bits := Float32bits(x) 21 | e := uint(bits>>shift) & mask 22 | if e < bias { 23 | // Round abs(x) < 1 including denormals. 24 | bits &= signMask // +-0 25 | if e == bias-1 { 26 | bits |= uvone // +-1 27 | } 28 | } else if e < bias+shift { 29 | // Round any abs(x) >= 1 containing a fractional component [0,1). 30 | // 31 | // Numbers with larger exponents are returned unchanged since they 32 | // must be either an integer, infinity, or NaN. 33 | const half = 1 << (shift - 1) 34 | e -= bias 35 | bits += half >> e 36 | bits &^= fracMask >> e 37 | } 38 | return Float32frombits(bits) 39 | } 40 | 41 | // RoundToEven returns the nearest integer, rounding ties to even. 42 | // 43 | // Special cases are: 44 | // 45 | // RoundToEven(±0) = ±0 46 | // RoundToEven(±Inf) = ±Inf 47 | // RoundToEven(NaN) = NaN 48 | func RoundToEven(x float32) float32 { 49 | // RoundToEven is a faster implementation of: 50 | // 51 | // func RoundToEven(x float64) float64 { 52 | // t := math.Trunc(x) 53 | // odd := math.Remainder(t, 2) != 0 54 | // if d := math.Abs(x - t); d > 0.5 || (d == 0.5 && odd) { 55 | // return t + math.Copysign(1, x) 56 | // } 57 | // return t 58 | // } 59 | bits := Float32bits(x) 60 | e := uint(bits>>shift) & mask 61 | if e >= bias { 62 | // Round abs(x) >= 1. 63 | // - Large numbers without fractional components, infinity, and NaN are unchanged. 64 | // - Add 0.499.. or 0.5 before truncating depending on whether the truncated 65 | // number is even or odd (respectively). 66 | const halfMinusULP = (1 << (shift - 1)) - 1 67 | e -= bias 68 | bits += (halfMinusULP + (bits>>(shift-e))&1) >> e 69 | bits &^= fracMask >> e 70 | } else if e == bias-1 && bits&fracMask != 0 { 71 | // Round 0.5 < abs(x) < 1. 72 | bits = bits&signMask | uvone // +-1 73 | } else { 74 | // Round abs(x) <= 0.5 including denormals. 75 | bits &= signMask // +-0 76 | } 77 | return Float32frombits(bits) 78 | } 79 | -------------------------------------------------------------------------------- /signbit.go: -------------------------------------------------------------------------------- 1 | package math32 2 | 3 | // Signbit returns true if x is negative or negative zero. 4 | func Signbit(x float32) bool { 5 | return Float32bits(x)&(1<<31) != 0 6 | } 7 | -------------------------------------------------------------------------------- /sincos.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package math32 6 | 7 | import ( 8 | "math/bits" 9 | ) 10 | 11 | /* 12 | Floating-point sine and cosine. 13 | */ 14 | 15 | // The original C code, the long comment, and the constants 16 | // below were from http://netlib.sandia.gov/cephes/cmath/sin.c, 17 | // available from http://www.netlib.org/cephes/cmath.tgz. 18 | // The go code is a simplified version of the original C. 19 | // 20 | // sin.c 21 | // 22 | // Circular sine 23 | // 24 | // SYNOPSIS: 25 | // 26 | // double x, y, sin(); 27 | // y = sin( x ); 28 | // 29 | // DESCRIPTION: 30 | // 31 | // Range reduction is into intervals of pi/4. The reduction error is nearly 32 | // eliminated by contriving an extended precision modular arithmetic. 33 | // 34 | // Two polynomial approximating functions are employed. 35 | // Between 0 and pi/4 the sine is approximated by 36 | // x + x**3 P(x**2). 37 | // Between pi/4 and pi/2 the cosine is represented as 38 | // 1 - x**2 Q(x**2). 39 | // 40 | // ACCURACY: 41 | // 42 | // Relative error: 43 | // arithmetic domain # trials peak rms 44 | // DEC 0, 10 150000 3.0e-17 7.8e-18 45 | // IEEE -1.07e9,+1.07e9 130000 2.1e-16 5.4e-17 46 | // 47 | // Partial loss of accuracy begins to occur at x = 2**30 = 1.074e9. The loss 48 | // is not gradual, but jumps suddenly to about 1 part in 10e7. Results may 49 | // be meaningless for x > 2**49 = 5.6e14. 50 | // 51 | // cos.c 52 | // 53 | // Circular cosine 54 | // 55 | // SYNOPSIS: 56 | // 57 | // double x, y, cos(); 58 | // y = cos( x ); 59 | // 60 | // DESCRIPTION: 61 | // 62 | // Range reduction is into intervals of pi/4. The reduction error is nearly 63 | // eliminated by contriving an extended precision modular arithmetic. 64 | // 65 | // Two polynomial approximating functions are employed. 66 | // Between 0 and pi/4 the cosine is approximated by 67 | // 1 - x**2 Q(x**2). 68 | // Between pi/4 and pi/2 the sine is represented as 69 | // x + x**3 P(x**2). 70 | // 71 | // ACCURACY: 72 | // 73 | // Relative error: 74 | // arithmetic domain # trials peak rms 75 | // IEEE -1.07e9,+1.07e9 130000 2.1e-16 5.4e-17 76 | // DEC 0,+1.07e9 17000 3.0e-17 7.2e-18 77 | // 78 | // Cephes Math Library Release 2.8: June, 2000 79 | // Copyright 1984, 1987, 1989, 1992, 2000 by Stephen L. Moshier 80 | // 81 | // The readme file at http://netlib.sandia.gov/cephes/ says: 82 | // Some software in this archive may be from the book _Methods and 83 | // Programs for Mathematical Functions_ (Prentice-Hall or Simon & Schuster 84 | // International, 1989) or from the Cephes Mathematical Library, a 85 | // commercial product. In either event, it is copyrighted by the author. 86 | // What you see here may be used freely but it comes with no support or 87 | // guarantee. 88 | // 89 | // The two known misprints in the book are repaired here in the 90 | // source listings for the gamma function and the incomplete beta 91 | // integral. 92 | // 93 | // Stephen L. Moshier 94 | // moshier@na-net.ornl.gov 95 | 96 | // sin coefficients 97 | var _sin = [...]float32{ 98 | 1.58962301576546568060e-10, // 0x3de5d8fd1fd19ccd 99 | -2.50507477628578072866e-8, // 0xbe5ae5e5a9291f5d 100 | 2.75573136213857245213e-6, // 0x3ec71de3567d48a1 101 | -1.98412698295895385996e-4, // 0xbf2a01a019bfdf03 102 | 8.33333333332211858878e-3, // 0x3f8111111110f7d0 103 | -1.66666666666666307295e-1, // 0xbfc5555555555548 104 | } 105 | 106 | // cos coefficients 107 | var _cos = [...]float32{ 108 | -1.13585365213876817300e-11, // 0xbda8fa49a0861a9b 109 | 2.08757008419747316778e-9, // 0x3e21ee9d7b4e3f05 110 | -2.75573141792967388112e-7, // 0xbe927e4f7eac4bc6 111 | 2.48015872888517045348e-5, // 0x3efa01a019c844f5 112 | -1.38888888888730564116e-3, // 0xbf56c16c16c14f91 113 | 4.16666666666665929218e-2, // 0x3fa555555555554b 114 | } 115 | 116 | // Sincos returns Sin(x), Cos(x). 117 | // 118 | // Special cases are: 119 | // 120 | // Sincos(±0) = ±0, 1 121 | // Sincos(±Inf) = NaN, NaN 122 | // Sincos(NaN) = NaN, NaN 123 | func Sincos(x float32) (sin, cos float32) { 124 | const ( 125 | PI4A = 7.85398125648498535156e-1 // 0x3fe921fb40000000, Pi/4 split into three parts 126 | PI4B = 3.77489470793079817668e-8 // 0x3e64442d00000000, 127 | PI4C = 2.69515142907905952645e-15 // 0x3ce8469898cc5170, 128 | ) 129 | // special cases 130 | switch { 131 | case x == 0: 132 | return x, 1 // return ±0.0, 1.0 133 | case IsNaN(x) || IsInf(x, 0): 134 | return NaN(), NaN() 135 | } 136 | 137 | // make argument positive 138 | sinSign, cosSign := false, false 139 | if x < 0 { 140 | x = -x 141 | sinSign = true 142 | } 143 | 144 | var j uint64 145 | var y, z float32 146 | if x >= reduceThreshold { 147 | j, z = trigReduce(x) 148 | } else { 149 | j = uint64(x * (4 / Pi)) // integer part of x/(Pi/4), as integer for tests on the phase angle 150 | y = float32(j) // integer part of x/(Pi/4), as float 151 | 152 | if j&1 == 1 { // map zeros to origin 153 | j++ 154 | y++ 155 | } 156 | j &= 7 // octant modulo 2Pi radians (360 degrees) 157 | z = ((x - y*PI4A) - y*PI4B) - y*PI4C // Extended precision modular arithmetic 158 | } 159 | if j > 3 { // reflect in x axis 160 | j -= 4 161 | sinSign, cosSign = !sinSign, !cosSign 162 | } 163 | if j > 1 { 164 | cosSign = !cosSign 165 | } 166 | 167 | zz := z * z 168 | cos = 1.0 - 0.5*zz + zz*zz*((((((_cos[0]*zz)+_cos[1])*zz+_cos[2])*zz+_cos[3])*zz+_cos[4])*zz+_cos[5]) 169 | sin = z + z*zz*((((((_sin[0]*zz)+_sin[1])*zz+_sin[2])*zz+_sin[3])*zz+_sin[4])*zz+_sin[5]) 170 | if j == 1 || j == 2 { 171 | sin, cos = cos, sin 172 | } 173 | if cosSign { 174 | cos = -cos 175 | } 176 | if sinSign { 177 | sin = -sin 178 | } 179 | return 180 | } 181 | 182 | // Sin returns the sine of the radian argument x. 183 | // 184 | // Special cases are: 185 | // 186 | // Sin(±0) = ±0 187 | // Sin(±Inf) = NaN 188 | // Sin(NaN) = NaN 189 | func Sin(x float32) float32 { 190 | const ( 191 | PI4A = 7.85398125648498535156e-1 // 0x3fe921fb40000000, Pi/4 split into three parts 192 | PI4B = 3.77489470793079817668e-8 // 0x3e64442d00000000, 193 | PI4C = 2.69515142907905952645e-15 // 0x3ce8469898cc5170, 194 | ) 195 | // special cases 196 | switch { 197 | case x == 0 || IsNaN(x): 198 | return x // return ±0 || NaN() 199 | case IsInf(x, 0): 200 | return NaN() 201 | } 202 | 203 | // make argument positive but save the sign 204 | sign := false 205 | if x < 0 { 206 | x = -x 207 | sign = true 208 | } 209 | 210 | var j uint64 211 | var y, z float32 212 | if x >= reduceThreshold { 213 | j, z = trigReduce(x) 214 | } else { 215 | j = uint64(x * (4 / Pi)) // integer part of x/(Pi/4), as integer for tests on the phase angle 216 | y = float32(j) // integer part of x/(Pi/4), as float 217 | 218 | // map zeros to origin 219 | if j&1 == 1 { 220 | j++ 221 | y++ 222 | } 223 | j &= 7 // octant modulo 2Pi radians (360 degrees) 224 | z = ((x - y*PI4A) - y*PI4B) - y*PI4C // Extended precision modular arithmetic 225 | } 226 | // reflect in x axis 227 | if j > 3 { 228 | sign = !sign 229 | j -= 4 230 | } 231 | zz := z * z 232 | if j == 1 || j == 2 { 233 | y = 1.0 - 0.5*zz + zz*zz*((((((_cos[0]*zz)+_cos[1])*zz+_cos[2])*zz+_cos[3])*zz+_cos[4])*zz+_cos[5]) 234 | } else { 235 | y = z + z*zz*((((((_sin[0]*zz)+_sin[1])*zz+_sin[2])*zz+_sin[3])*zz+_sin[4])*zz+_sin[5]) 236 | } 237 | if sign { 238 | y = -y 239 | } 240 | return y 241 | } 242 | 243 | // Cos returns the cosine of the radian argument x. 244 | // 245 | // Special cases are: 246 | // 247 | // Cos(±Inf) = NaN 248 | // Cos(NaN) = NaN 249 | func Cos(x float32) float32 { 250 | const ( 251 | PI4A = 7.85398125648498535156e-1 // 0x3fe921fb40000000, Pi/4 split into three parts 252 | PI4B = 3.77489470793079817668e-8 // 0x3e64442d00000000, 253 | PI4C = 2.69515142907905952645e-15 // 0x3ce8469898cc5170, 254 | ) 255 | // special cases 256 | switch { 257 | case IsNaN(x) || IsInf(x, 0): 258 | return NaN() 259 | } 260 | 261 | // make argument positive 262 | sign := false 263 | x = Abs(x) 264 | 265 | var j uint64 266 | var y, z float32 267 | if x >= reduceThreshold { 268 | j, z = trigReduce(x) 269 | } else { 270 | j = uint64(x * (4 / Pi)) // integer part of x/(Pi/4), as integer for tests on the phase angle 271 | y = float32(j) // integer part of x/(Pi/4), as float 272 | 273 | // map zeros to origin 274 | if j&1 == 1 { 275 | j++ 276 | y++ 277 | } 278 | j &= 7 // octant modulo 2Pi radians (360 degrees) 279 | z = ((x - y*PI4A) - y*PI4B) - y*PI4C // Extended precision modular arithmetic 280 | } 281 | 282 | if j > 3 { 283 | j -= 4 284 | sign = !sign 285 | } 286 | if j > 1 { 287 | sign = !sign 288 | } 289 | 290 | zz := z * z 291 | if j == 1 || j == 2 { 292 | y = z + z*zz*((((((_sin[0]*zz)+_sin[1])*zz+_sin[2])*zz+_sin[3])*zz+_sin[4])*zz+_sin[5]) 293 | } else { 294 | y = 1.0 - 0.5*zz + zz*zz*((((((_cos[0]*zz)+_cos[1])*zz+_cos[2])*zz+_cos[3])*zz+_cos[4])*zz+_cos[5]) 295 | } 296 | if sign { 297 | y = -y 298 | } 299 | return y 300 | } 301 | 302 | // reduceThreshold is the maximum value of x where the reduction using Pi/4 303 | // in 3 float64 parts still gives accurate results. This threshold 304 | // is set by y*C being representable as a float64 without error 305 | // where y is given by y = floor(x * (4 / Pi)) and C is the leading partial 306 | // terms of 4/Pi. Since the leading terms (PI4A and PI4B in sin.go) have 30 307 | // and 32 trailing zero bits, y should have less than 30 significant bits. 308 | // 309 | // y < 1<<30 -> floor(x*4/Pi) < 1<<30 -> x < (1<<30 - 1) * Pi/4 310 | // 311 | // So, conservatively we can take x < 1<<29. 312 | // Above this threshold Payne-Hanek range reduction must be used. 313 | const reduceThreshold = 1 << 29 314 | 315 | // trigReduce implements Payne-Hanek range reduction by Pi/4 316 | // for x > 0. It returns the integer part mod 8 (j) and 317 | // the fractional part (z) of x / (Pi/4). 318 | // The implementation is based on: 319 | // "ARGUMENT REDUCTION FOR HUGE ARGUMENTS: Good to the Last Bit" 320 | // K. C. Ng et al, March 24, 1992 321 | // The simulated multi-precision calculation of x*B uses 64-bit integer arithmetic. 322 | func trigReduce(x float32) (j uint64, z float32) { 323 | const PI4 = Pi / 4 324 | if x < PI4 { 325 | return 0, x 326 | } 327 | // Extract out the integer and exponent such that, 328 | // x = ix * 2 ** exp. 329 | ix := Float32bits(x) 330 | exp := int(ix>>shift&mask) - bias - shift 331 | ix &^= mask << shift 332 | ix |= 1 << shift 333 | // Use the exponent to extract the 3 appropriate uint64 digits from mPi4, 334 | // B ~ (z0, z1, z2), such that the product leading digit has the exponent -61. 335 | // Note, exp >= -53 since x >= PI4 and exp < 971 for maximum float64. 336 | const floatingbits = 32 - 3 337 | digit, bitshift := uint(exp+floatingbits)/32, uint(exp+floatingbits)%32 338 | z0 := (mPi4[digit] << bitshift) | (mPi4[digit+1] >> (32 - bitshift)) 339 | z1 := (mPi4[digit+1] << bitshift) | (mPi4[digit+2] >> (32 - bitshift)) 340 | z2 := (mPi4[digit+2] << bitshift) | (mPi4[digit+3] >> (32 - bitshift)) 341 | // Multiply mantissa by the digits and extract the upper two digits (hi, lo). 342 | z2hi, _ := bits.Mul64(z2, uint64(ix)) 343 | z1hi, z1lo := bits.Mul64(z1, uint64(ix)) 344 | z0lo := z0 * uint64(ix) 345 | lo, c := bits.Add64(z1lo, z2hi, 0) 346 | hi, _ := bits.Add64(z0lo, z1hi, c) 347 | // The top 3 bits are j. 348 | j = hi >> floatingbits 349 | // Extract the fraction and find its magnitude. 350 | hi = hi<<3 | lo>>floatingbits 351 | lz := uint(bits.LeadingZeros64(hi)) 352 | e := uint64(bias - (lz + 1)) 353 | // Clear implicit mantissa bit and shift into place. 354 | hi = (hi << (lz + 1)) | (lo >> (32 - (lz + 1))) 355 | hi >>= 43 - shift 356 | // Include the exponent and convert to a float. 357 | hi |= e << shift 358 | z = Float32frombits(uint32(hi)) 359 | // Map zeros to origin. 360 | if j&1 == 1 { 361 | j++ 362 | j &= 7 363 | z-- 364 | } 365 | // Multiply the fractional part by pi/4. 366 | return j, z * PI4 367 | } 368 | 369 | // mPi4 is the binary digits of 4/pi as a uint64 array, 370 | // that is, 4/pi = Sum mPi4[i]*2^(-64*i) 371 | // 19 64-bit digits and the leading one bit give 1217 bits 372 | // of precision to handle the largest possible float64 exponent. 373 | var mPi4 = [...]uint64{ 374 | 0x0000000000000001, 375 | 0x45f306dc9c882a53, 376 | 0xf84eafa3ea69bb81, 377 | 0xb6c52b3278872083, 378 | 0xfca2c757bd778ac3, 379 | 0x6e48dc74849ba5c0, 380 | 0x0c925dd413a32439, 381 | 0xfc3bd63962534e7d, 382 | 0xd1046bea5d768909, 383 | 0xd338e04d68befc82, 384 | 0x7323ac7306a673e9, 385 | 0x3908bf177bf25076, 386 | 0x3ff12fffbc0b301f, 387 | 0xde5e2316b414da3e, 388 | 0xda6cfd9e4f96136e, 389 | 0x9e8c7ecd3cbfd45a, 390 | 0xea4f758fd7cbe2f6, 391 | 0x7a0e73ef14a525d4, 392 | 0xd7f6bf623f1aba10, 393 | 0xac06608df8f6d757, 394 | } 395 | -------------------------------------------------------------------------------- /sinhf.go: -------------------------------------------------------------------------------- 1 | package math32 2 | 3 | // Sinh returns the hyperbolic sine of x. 4 | // 5 | // Special cases are: 6 | // 7 | // Sinh(±0) = ±0 8 | // Sinh(±Inf) = ±Inf 9 | // Sinh(NaN) = NaN 10 | func Sinh(x float32) float32 { 11 | // The coefficients are #2029 from Hart & Cheney. (20.36D) 12 | const ( 13 | P0 = -0.6307673640497716991184787251e+6 14 | P1 = -0.8991272022039509355398013511e+5 15 | P2 = -0.2894211355989563807284660366e+4 16 | P3 = -0.2630563213397497062819489e+2 17 | Q0 = -0.6307673640497716991212077277e+6 18 | Q1 = 0.1521517378790019070696485176e+5 19 | Q2 = -0.173678953558233699533450911e+3 20 | ) 21 | 22 | sign := false 23 | if x < 0 { 24 | x = -x 25 | sign = true 26 | } 27 | 28 | var temp float32 29 | switch { 30 | case x > 21: 31 | temp = Exp(x) * 0.5 32 | 33 | case x > 0.5: 34 | ex := Exp(x) 35 | temp = (ex - 1./ex) * 0.5 36 | 37 | default: 38 | sq := x * x 39 | temp = (((P3*sq+P2)*sq+P1)*sq + P0) * x 40 | temp = temp / (((sq+Q2)*sq+Q1)*sq + Q0) 41 | } 42 | 43 | if sign { 44 | temp = -temp 45 | } 46 | return temp 47 | } 48 | -------------------------------------------------------------------------------- /sqrt.go: -------------------------------------------------------------------------------- 1 | package math32 2 | 3 | // Sqrt returns the square root of x. 4 | 5 | // Special cases are: 6 | // 7 | // Sqrt(+Inf) = +Inf 8 | // Sqrt(±0) = ±0 9 | // Sqrt(x < 0) = NaN 10 | // Sqrt(NaN) = NaN 11 | func Sqrt(x float32) float32 { 12 | if haveArchSqrt { 13 | return archSqrt(x) 14 | } 15 | return sqrt(x) 16 | } 17 | 18 | // TODO: add assembly for !build noasm 19 | func sqrt(x float32) float32 { 20 | // special cases 21 | switch { 22 | case x == 0 || IsNaN(x) || IsInf(x, 1): 23 | return x 24 | case x < 0: 25 | return NaN() 26 | } 27 | ix := Float32bits(x) 28 | 29 | // normalize x 30 | exp := int((ix >> shift) & mask) 31 | if exp == 0 { // subnormal x 32 | for ix&(1<>= 1 // exp = exp/2, exponent of square root 45 | // generate sqrt(x) bit by bit 46 | ix <<= 1 47 | var q, s uint32 // q = sqrt(x) 48 | r := uint32(1 << (shift + 1)) // r = moving bit from MSB to LSB 49 | for r != 0 { 50 | t := s + r 51 | if t <= ix { 52 | s = t + r 53 | ix -= t 54 | q += r 55 | } 56 | ix <<= 1 57 | r >>= 1 58 | } 59 | // final rounding 60 | if ix != 0 { // remainder, result not exact 61 | q += q & 1 // round according to extra bit 62 | } 63 | ix = q>>1 + uint32(exp-1+bias)< 2**49 = 5.6e14. 38 | // [Accuracy loss statement from sin.go comments.] 39 | // 40 | // Cephes Math Library Release 2.8: June, 2000 41 | // Copyright 1984, 1987, 1989, 1992, 2000 by Stephen L. Moshier 42 | // 43 | // The readme file at http://netlib.sandia.gov/cephes/ says: 44 | // Some software in this archive may be from the book _Methods and 45 | // Programs for Mathematical Functions_ (Prentice-Hall or Simon & Schuster 46 | // International, 1989) or from the Cephes Mathematical Library, a 47 | // commercial product. In either event, it is copyrighted by the author. 48 | // What you see here may be used freely but it comes with no support or 49 | // guarantee. 50 | // 51 | // The two known misprints in the book are repaired here in the 52 | // source listings for the gamma function and the incomplete beta 53 | // integral. 54 | // 55 | // Stephen L. Moshier 56 | // moshier@na-net.ornl.gov 57 | 58 | // tan coefficients 59 | var _tanP = [...]float32{ 60 | -1.30936939181383777646e4, // 0xc0c992d8d24f3f38 61 | 1.15351664838587416140e6, // 0x413199eca5fc9ddd 62 | -1.79565251976484877988e7, // 0xc1711fead3299176 63 | } 64 | var _tanQ = [...]float32{ 65 | 1.00000000000000000000e0, 66 | 1.36812963470692954678e4, //0x40cab8a5eeb36572 67 | -1.32089234440210967447e6, //0xc13427bc582abc96 68 | 2.50083801823357915839e7, //0x4177d98fc2ead8ef 69 | -5.38695755929454629881e7, //0xc189afe03cbe5a31 70 | } 71 | 72 | // Tan returns the tangent of the radian argument x. 73 | // 74 | // Special cases are: 75 | // 76 | // Tan(±0) = ±0 77 | // Tan(±Inf) = NaN 78 | // Tan(NaN) = NaN 79 | func Tan(x float32) float32 { 80 | return tan(x) 81 | } 82 | 83 | func tan(x float32) float32 { 84 | const ( 85 | PI4A = 7.85398125648498535156e-1 // 0x3fe921fb40000000, Pi/4 split into three parts 86 | PI4B = 3.77489470793079817668e-8 // 0x3e64442d00000000, 87 | PI4C = 2.69515142907905952645e-15 // 0x3ce8469898cc5170, 88 | ) 89 | // special cases 90 | switch { 91 | case x == 0 || IsNaN(x): 92 | return x // return ±0 || NaN() 93 | case IsInf(x, 0): 94 | return NaN() 95 | } 96 | 97 | // make argument positive but save the sign 98 | sign := false 99 | if x < 0 { 100 | x = -x 101 | sign = true 102 | } 103 | var j uint64 104 | var y, z float32 105 | if x >= reduceThreshold { 106 | j, z = trigReduce(x) 107 | } else { 108 | j = uint64(x * (4 / Pi)) // integer part of x/(Pi/4), as integer for tests on the phase angle 109 | y = float32(j) // integer part of x/(Pi/4), as float 110 | 111 | /* map zeros and singularities to origin */ 112 | if j&1 == 1 { 113 | j++ 114 | y++ 115 | } 116 | 117 | z = ((x - y*PI4A) - y*PI4B) - y*PI4C 118 | } 119 | zz := z * z 120 | 121 | if zz > 1e-14 { 122 | y = z + z*(zz*(((_tanP[0]*zz)+_tanP[1])*zz+_tanP[2])/((((zz+_tanQ[1])*zz+_tanQ[2])*zz+_tanQ[3])*zz+_tanQ[4])) 123 | } else { 124 | y = z 125 | } 126 | if j&2 == 2 { 127 | y = -1 / y 128 | } 129 | if sign { 130 | y = -y 131 | } 132 | return y 133 | } 134 | -------------------------------------------------------------------------------- /tanh.go: -------------------------------------------------------------------------------- 1 | package math32 2 | 3 | // The original C code, the long comment, and the constants 4 | // below were from http://netlib.sandia.gov/cephes/cmath/tanh.c, 5 | // available from http://www.netlib.org/cephes/single.tgz. 6 | // The go code is a simplified version of the original C. 7 | // tanhf.c 8 | // 9 | // Hyperbolic tangent 10 | // 11 | // 12 | // 13 | // SYNOPSIS: 14 | // 15 | // float x, y, tanhf(); 16 | // 17 | // y = tanhf( x ); 18 | // 19 | // 20 | // 21 | // DESCRIPTION: 22 | // 23 | // Returns hyperbolic tangent of argument in the range MINLOG to 24 | // MAXLOG. 25 | // 26 | // A polynomial approximation is used for |x| < 0.625. 27 | // Otherwise, 28 | // 29 | // tanh(x) = sinh(x)/cosh(x) = 1 - 2/(exp(2x) + 1). 30 | // 31 | // 32 | // 33 | // ACCURACY: 34 | // 35 | // Relative error: 36 | // arithmetic domain # trials peak rms 37 | // IEEE -2,2 100000 1.3e-7 2.6e-8 38 | // 39 | // 40 | 41 | /* 42 | Cephes Math Library Release 2.2: June, 1992 43 | Copyright 1984, 1987, 1989, 1992 by Stephen L. Moshier 44 | Direct inquiries to 30 Frost Street, Cambridge, MA 02140 45 | */ 46 | 47 | /* Single precision hyperbolic tangent 48 | * test interval: [-0.625, +0.625] 49 | * trials: 10000 50 | * peak relative error: 7.2e-8 51 | * rms relative error: 2.6e-8 52 | */ 53 | 54 | // Tanh returns the hyperbolic tangent of x. 55 | // 56 | // Special cases are: 57 | // 58 | // Tanh(±0) = ±0 59 | // Tanh(±Inf) = ±1 60 | // Tanh(NaN) = NaN 61 | func Tanh(x float32) float32 { 62 | const MAXLOG = 88.02969187150841 63 | z := Abs(x) 64 | switch { 65 | case z > 0.5*MAXLOG: 66 | if x < 0 { 67 | return -1 68 | } 69 | return 1 70 | case z >= 0.625: 71 | s := Exp(z + z) 72 | z = 1 - 2/(s+1) 73 | if x < 0 { 74 | z = -z 75 | } 76 | default: 77 | if x == 0 { 78 | return x 79 | } 80 | s := x * x 81 | z = ((((-5.70498872745e-3*s+2.06390887954e-2)*s-5.37397155531e-2)*s+1.33314422036e-1)*s-3.33332819422e-1)*s*x + x 82 | } 83 | return z 84 | } 85 | -------------------------------------------------------------------------------- /unsafe.go: -------------------------------------------------------------------------------- 1 | package math32 2 | 3 | import "unsafe" 4 | 5 | // Float32bits returns the IEEE 754 binary representation of f. 6 | func Float32bits(f float32) uint32 { return *(*uint32)(unsafe.Pointer(&f)) } 7 | 8 | // Float32frombits returns the floating point number corresponding 9 | // to the IEEE 754 binary representation b. 10 | func Float32frombits(b uint32) float32 { return *(*float32)(unsafe.Pointer(&b)) } 11 | 12 | // Float64bits returns the IEEE 754 binary representation of f. 13 | func Float64bits(f float64) uint64 { return *(*uint64)(unsafe.Pointer(&f)) } 14 | 15 | // Float64frombits returns the floating point number corresponding 16 | // the IEEE 754 binary representation b. 17 | func Float64frombits(b uint64) float64 { return *(*float64)(unsafe.Pointer(&b)) } 18 | 19 | func float32ibits(f float32) int32 { return *(*int32)(unsafe.Pointer(&f)) } 20 | 21 | func float32fromibits(b int32) float32 { return *(*float32)(unsafe.Pointer(&b)) } 22 | -------------------------------------------------------------------------------- /y0.go: -------------------------------------------------------------------------------- 1 | package math32 2 | 3 | import "math" 4 | 5 | // Y0 returns the order-zero Bessel function of the second kind. 6 | // 7 | // Special cases are: 8 | // 9 | // Y0(+Inf) = 0 10 | // Y0(0) = -Inf 11 | // Y0(x < 0) = NaN 12 | // Y0(NaN) = NaN 13 | func Y0(x float32) float32 { 14 | return float32(math.Y0(float64(x))) 15 | } 16 | -------------------------------------------------------------------------------- /y1.go: -------------------------------------------------------------------------------- 1 | package math32 2 | 3 | import "math" 4 | 5 | // Y1 returns the order-one Bessel function of the second kind. 6 | // 7 | // Special cases are: 8 | // 9 | // Y1(+Inf) = 0 10 | // Y1(0) = -Inf 11 | // Y1(x < 0) = NaN 12 | // Y1(NaN) = NaN 13 | func Y1(x float32) float32 { 14 | return float32(math.Y1(float64(x))) 15 | } 16 | --------------------------------------------------------------------------------