pax_global_header00006660000000000000000000000064146730556130014524gustar00rootroot0000000000000052 comment=7ba2c0836c8562f127d173d9d0588c162111793c math32-1.11.1/000077500000000000000000000000001467305561300127035ustar00rootroot00000000000000math32-1.11.1/.github/000077500000000000000000000000001467305561300142435ustar00rootroot00000000000000math32-1.11.1/.github/workflows/000077500000000000000000000000001467305561300163005ustar00rootroot00000000000000math32-1.11.1/.github/workflows/go.yml000066400000000000000000000004711467305561300174320ustar00rootroot00000000000000name: Go on: push: branches: [ master ] pull_request: branches: [ master ] jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: Set up Go uses: actions/setup-go@v3 with: go-version: 1.18 - name: Test run: go test -v ./... math32-1.11.1/.gitignore000066400000000000000000000004121467305561300146700ustar00rootroot00000000000000# Compiled Object files, Static and Dynamic libs (Shared Objects) *.o *.a *.so # Folders _obj _test # Architecture specific extensions/prefixes *.[568vq] [568vq].out *.cgo1.go *.cgo2.c _cgo_defun.c _cgo_gotypes.go _cgo_export.* _testmain.go *.exe *.test *.prof math32-1.11.1/LICENSE000066400000000000000000000024741467305561300137170ustar00rootroot00000000000000BSD 2-Clause License Copyright (c) 2021, Xuanyi Chew and the Go Authors All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. math32-1.11.1/README.md000066400000000000000000000007031467305561300141620ustar00rootroot00000000000000# math32 [![GoDoc](https://godoc.org/github.com/chewxy/math32?status.svg)](https://godoc.org/github.com/chewxy/math32) 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. The original code is lifted from the Go standard library which is governed by a BSD-style licence which can be found here: https://golang.org/LICENSE. math32-1.11.1/_exp_arm64.s000066400000000000000000000124331467305561300150360ustar00rootroot00000000000000//go:build !tinygo && !noasm // Copyright 2017 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. #define Ln2Hi 6.9313812256e-01 #define Ln2Lo 9.0580006145e-06 #define Log2e 1.4426950216e+00 #define Overflow 7.097827e+02 #define Underflow -7.451332e+02 #define Overflow2 1.024000e+03 #define Underflow2 -1.0740e+03 #define NearZero 0x317fffff // 2**-28 #define PosInf 0x7f800000 #define FracMask 0x07fffff #define C1 0x34000000 // 2**-23 #define P1 1.6666667163e-01 // 0x3FC55555; 0x55555555 #define P2 -2.7777778450e-03 // 0xBF66C16C; 0x16BEBD93 #define P3 6.6137559770e-05 // 0x3F11566A; 0xAF25DE2C #define P4 -1.6533901999e-06 // 0xBEBBBD41; 0xC5D26BF1 #define P5 4.1381369442e-08 // 0x3E663769; 0x72BEA4D0 // Exp returns e**x, the base-e exponential of x. // This is an assembly implementation of the method used for function Exp in file exp.go. // // func archExp(x float32) float32 TEXT ·archExp(SB),$0-12 FMOVS x+0(FP), F0 // F0 = x FCMPS F0, F0 BNE isNaN // x = NaN, return NaN FMOVS $Overflow, F1 FCMPS F1, F0 BGT overflow // x > Overflow, return PosInf FMOVS $Underflow, F1 FCMPS F1, F0 BLT underflow // x < Underflow, return 0 MOVW $NearZero, R0 FMOVS R0, F2 FABSS F0, F3 FMOVS $1.0, F1 // F1 = 1.0 FCMPS F2, F3 BLT nearzero // fabs(x) < NearZero, return 1 + x // argument reduction, x = k*ln2 + r, |r| <= 0.5*ln2 // computed as r = hi - lo for extra precision. FMOVS $Log2e, F2 FMOVS $0.5, F3 FNMSUBS F0, F3, F2, F4 // Log2e*x - 0.5 FMADDS F0, F3, F2, F3 // Log2e*x + 0.5 FCMPS $0.0, F0 FCSELS LT, F4, F3, F3 // F3 = k FCVTZSS F3, R1 // R1 = int(k) SCVTFS R1, F3 // F3 = float32(int(k)) FMOVS $Ln2Hi, F4 // F4 = Ln2Hi FMOVS $Ln2Lo, F5 // F5 = Ln2Lo FMSUBS F3, F0, F4, F4 // F4 = hi = x - float32(int(k))*Ln2Hi FMULS F3, F5 // F5 = lo = float32(int(k)) * Ln2Lo FSUBS F5, F4, F6 // F6 = r = hi - lo FMULS F6, F6, F7 // F7 = t = r * r // compute y FMOVS $P5, F8 // F8 = P5 FMOVS $P4, F9 // F9 = P4 FMADDS F7, F9, F8, F13 // P4+t*P5 FMOVS $P3, F10 // F10 = P3 FMADDS F7, F10, F13, F13 // P3+t*(P4+t*P5) FMOVS $P2, F11 // F11 = P2 FMADDS F7, F11, F13, F13 // P2+t*(P3+t*(P4+t*P5)) FMOVS $P1, F12 // F12 = P1 FMADDS F7, F12, F13, F13 // P1+t*(P2+t*(P3+t*(P4+t*P5))) FMSUBS F7, F6, F13, F13 // F13 = c = r - t*(P1+t*(P2+t*(P3+t*(P4+t*P5)))) FMOVS $2.0, F14 FSUBS F13, F14 FMULS F6, F13, F15 FDIVS F14, F15 // F15 = (r*c)/(2-c) FSUBS F15, F5, F15 // lo-(r*c)/(2-c) FSUBS F4, F15, F15 // (lo-(r*c)/(2-c))-hi FSUBS F15, F1, F16 // F16 = y = 1-((lo-(r*c)/(2-c))-hi) // inline Ldexp(y, k), benefit: // 1, no parameter pass overhead. // 2, skip unnecessary checks for Inf/NaN/Zero FMOVS F16, R0 ANDS $FracMask, R0, R2 // fraction LSRW $23, R0, R5 // exponent ADDS R1, R5 // R1 = int(k) CMPW $1, R5 BGE normal ADDS $23, R5 // denormal MOVW $C1, R8 FMOVS R8, F1 // m = 2**-23 normal: ORRW R5<<23, R2, R0 FMOVS R0, F0 FMULS F1, F0 // return m * x FMOVS F0, ret+8(FP) RET nearzero: FADDS F1, F0 isNaN: FMOVS F0, ret+8(FP) RET underflow: MOVW ZR, ret+8(FP) RET overflow: MOVW $PosInf, R0 MOVW R0, ret+8(FP) RET // Exp2 returns 2**x, the base-2 exponential of x. // This is an assembly implementation of the method used for function Exp2 in file exp.go. // // func archExp2(x float32) float32 TEXT ·archExp2(SB),$0-12 // Is this correct? FMOVS x+0(FP), F0 // F0 = x FCMPS F0, F0 BNE isNaN // x = NaN, return NaN FMOVS $Overflow2, F1 FCMPS F1, F0 BGT overflow // x > Overflow, return PosInf FMOVS $Underflow2, F1 FCMPS F1, F0 BLT underflow // x < Underflow, return 0 // argument reduction; x = r*lg(e) + k with |r| <= ln(2)/2 // computed as r = hi - lo for extra precision. FMOVS $0.5, F2 FSUBS F2, F0, F3 // x + 0.5 FADDS F2, F0, F4 // x - 0.5 FCMPS $0.0, F0 FCSELS LT, F3, F4, F3 // F3 = k FCVTZSS F3, R1 // R1 = int(k) SCVTFS R1, F3 // F3 = float32(int(k)) FSUBS F3, F0, F3 // t = x - float32(int(k)) FMOVS $Ln2Hi, F4 // F4 = Ln2Hi FMOVS $Ln2Lo, F5 // F5 = Ln2Lo FMULS F3, F4 // F4 = hi = t * Ln2Hi FNMULS F3, F5 // F5 = lo = -t * Ln2Lo FSUBS F5, F4, F6 // F6 = r = hi - lo FMULS F6, F6, F7 // F7 = t = r * r // compute y FMOVS $P5, F8 // F8 = P5 FMOVS $P4, F9 // F9 = P4 FMADDS F7, F9, F8, F13 // P4+t*P5 FMOVS $P3, F10 // F10 = P3 FMADDS F7, F10, F13, F13 // P3+t*(P4+t*P5) FMOVS $P2, F11 // F11 = P2 FMADDS F7, F11, F13, F13 // P2+t*(P3+t*(P4+t*P5)) FMOVS $P1, F12 // F12 = P1 FMADDS F7, F12, F13, F13 // P1+t*(P2+t*(P3+t*(P4+t*P5))) FMSUBS F7, F6, F13, F13 // F13 = c = r - t*(P1+t*(P2+t*(P3+t*(P4+t*P5)))) FMOVS $2.0, F14 FSUBS F13, F14 FMULS F6, F13, F15 FDIVS F14, F15 // F15 = (r*c)/(2-c) FMOVS $1.0, F1 // F1 = 1.0 FSUBS F15, F5, F15 // lo-(r*c)/(2-c) FSUBS F4, F15, F15 // (lo-(r*c)/(2-c))-hi FSUBS F15, F1, F16 // F16 = y = 1-((lo-(r*c)/(2-c))-hi) // inline Ldexp(y, k), benefit: // 1, no parameter pass overhead. // 2, skip unnecessary checks for Inf/NaN/Zero FMOVS F16, R0 ANDS $FracMask, R0, R2 // fraction LSRW $23, R0, R5 // exponent ADDS R1, R5 // R1 = int(k) CMPW $1, R5 BGE normal ADDS $23, R5 // denormal MOVW $C1, R8 FMOVS R8, F1 // m = 2**-52 normal: ORRW R5<<23, R2, R0 FMOVS R0, F0 FMULS F1, F0 // return m * x isNaN: FMOVS F0, ret+8(FP) RET underflow: MOVW ZR, ret+8(FP) RET overflow: MOVW $PosInf, R0 MOVW R0, ret+8(FP) RET math32-1.11.1/_stubs_risc64.s000066400000000000000000000007311467305561300155610ustar00rootroot00000000000000//go:build !tinygo && !noasm #include "textflag.h" // func archExp(x float32) float32 TEXT ·archExp(SB),NOSPLIT,$0 B ·exp(SB) // func archExp2(x float32) float32 TEXT ·archExp2(SB),NOSPLIT,$0 B ·exp2(SB) // func archLog(x float32) float32 TEXT ·archLog(SB),NOSPLIT,$0 B ·log(SB) // func archRemainder(x, y float32) float32 TEXT ·archRemainder(SB),NOSPLIT,$0 B ·remainder(SB) // func archSqrt(x float32) float32 TEXT ·archSqrt(SB),NOSPLIT,$0 B ·sqrt(SB) math32-1.11.1/abs.go000066400000000000000000000003151467305561300137760ustar00rootroot00000000000000package math32 // Abs returns the absolute value of x. // // Special cases are: // Abs(±Inf) = +Inf // Abs(NaN) = NaN func Abs(x float32) float32 { return Float32frombits(Float32bits(x) &^ (1 << 31)) } math32-1.11.1/acos.go000066400000000000000000000002641467305561300141610ustar00rootroot00000000000000package math32 // Acos returns the arccosine, in radians, of x. // // Special case is: // Acos(x) = NaN if x < -1 or x > 1 func Acos(x float32) float32 { return Pi/2 - Asin(x) } math32-1.11.1/acosh.go000066400000000000000000000027231467305561300143330ustar00rootroot00000000000000package math32 // The original C code, the long comment, and the constants // below are from FreeBSD's /usr/src/lib/msun/src/e_acosh.c // and came with this notice. The go code is a simplified // version of the original C. // // ==================================================== // Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. // // Developed at SunPro, a Sun Microsystems, Inc. business. // Permission to use, copy, modify, and distribute this // software is freely granted, provided that this notice // is preserved. // ==================================================== // // // __ieee754_acosh(x) // Method : // Based on // acosh(x) = log [ x + sqrt(x*x-1) ] // we have // acosh(x) := log(x)+ln2, if x is large; else // acosh(x) := log(2x-1/(sqrt(x*x-1)+x)) if x>2; else // acosh(x) := log1p(t+sqrt(2.0*t+t*t)); where t=x-1. // // Special cases: // acosh(x) is NaN with signal if x<1. // acosh(NaN) is NaN without signal. // // Acosh returns the inverse hyperbolic cosine of x. // // Special cases are: // Acosh(+Inf) = +Inf // Acosh(x) = NaN if x < 1 // Acosh(NaN) = NaN func Acosh(x float32) float32 { const Large = 1 << 28 // 2**28 // first case is special case switch { case x < 1 || IsNaN(x): return NaN() case x == 1: return 0 case x >= Large: return Log(x) + Ln2 // x > 2**28 case x > 2: return Log(2*x - 1/(x+Sqrt(x*x-1))) // 2**28 > x > 2 } t := x - 1 return Log1p(t + Sqrt(2*t+t*t)) // 2 >= x > 1 } math32-1.11.1/all_test.go000066400000000000000000002011421467305561300150410ustar00rootroot00000000000000// Copyright 2009 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package math32_test import ( "fmt" "testing" . "github.com/chewxy/math32" ) var vf = []float32{ 4.9790119248836735e+00, 7.7388724745781045e+00, -2.7688005719200159e-01, -5.0106036182710749e+00, 9.6362937071984173e+00, 2.9263772392439646e+00, 5.2290834314593066e+00, 2.7279399104360102e+00, 1.8253080916808550e+00, -8.6859247685756013e+00, } // The expected results below were computed by the high precision calculators // at http://keisan.casio.com/. More exact input values (array vf[], above) // were obtained by printing them with "%.26f". The answers were calculated // to 26 digits (by using the "Digit number" drop-down control of each // calculator). var acos = []float32{ 1.0496193546107222142571536e+00, 6.8584012813664425171660692e-01, 1.5984878714577160325521819e+00, 2.0956199361475859327461799e+00, 2.7053008467824138592616927e-01, 1.2738121680361776018155625e+00, 1.0205369421140629186287407e+00, 1.2945003481781246062157835e+00, 1.3872364345374451433846657e+00, 2.6231510803970463967294145e+00, } var acosh = []float32{ 2.4743347004159012494457618e+00, 2.8576385344292769649802701e+00, 7.2796961502981066190593175e-01, 2.4796794418831451156471977e+00, 3.0552020742306061857212962e+00, 2.044238592688586588942468e+00, 2.5158701513104513595766636e+00, 1.99050839282411638174299e+00, 1.6988625798424034227205445e+00, 2.9611454842470387925531875e+00, } var asin = []float32{ 5.2117697218417440497416805e-01, 8.8495619865825236751471477e-01, -02.769154466281941332086016e-02, -5.2482360935268931351485822e-01, 1.3002662421166552333051524e+00, 2.9698415875871901741575922e-01, 5.5025938468083370060258102e-01, 2.7629597861677201301553823e-01, 1.83559892257451475846656e-01, -1.0523547536021497774980928e+00, } var asinh = []float32{ 2.3083139124923523427628243e+00, 2.743551594301593620039021e+00, -2.7345908534880091229413487e-01, -2.3145157644718338650499085e+00, 2.9613652154015058521951083e+00, 1.7949041616585821933067568e+00, 2.3564032905983506405561554e+00, 1.7287118790768438878045346e+00, 1.3626658083714826013073193e+00, -2.8581483626513914445234004e+00, } var atan = []float32{ 1.372590262129621651920085e+00, 1.442290609645298083020664e+00, -2.7011324359471758245192595e-01, -1.3738077684543379452781531e+00, 1.4673921193587666049154681e+00, 1.2415173565870168649117764e+00, 1.3818396865615168979966498e+00, 1.2194305844639670701091426e+00, 1.0696031952318783760193244e+00, -1.4561721938838084990898679e+00, } var atanh = []float32{ 5.4651163712251938116878204e-01, 1.0299474112843111224914709e+00, -2.7695084420740135145234906e-02, -5.5072096119207195480202529e-01, 1.9943940993171843235906642e+00, 3.01448604578089708203017e-01, 5.8033427206942188834370595e-01, 2.7987997499441511013958297e-01, 1.8459947964298794318714228e-01, -1.3273186910532645867272502e+00, } var atan2 = []float32{ 1.1088291730037004444527075e+00, 9.1218183188715804018797795e-01, 1.5984772603216203736068915e+00, 2.0352918654092086637227327e+00, 8.0391819139044720267356014e-01, 1.2861075249894661588866752e+00, 1.0889904479131695712182587e+00, 1.3044821793397925293797357e+00, 1.3902530903455392306872261e+00, 2.2859857424479142655411058e+00, } var cbrt = []float32{ 1.7075799841925094446722675e+00, 1.9779982212970353936691498e+00, -6.5177429017779910853339447e-01, -1.7111838886544019873338113e+00, 2.1279920909827937423960472e+00, 1.4303536770460741452312367e+00, 1.7357021059106154902341052e+00, 1.3972633462554328350552916e+00, 1.2221149580905388454977636e+00, -2.0556003730500069110343596e+00, } var ceil = []float32{ 5.0000000000000000e+00, 8.0000000000000000e+00, 0.0000000000000000e+00, -5.0000000000000000e+00, 1.0000000000000000e+01, 3.0000000000000000e+00, 6.0000000000000000e+00, 3.0000000000000000e+00, 2.0000000000000000e+00, -8.0000000000000000e+00, } var copysign = []float32{ -4.9790119248836735e+00, -7.7388724745781045e+00, -2.7688005719200159e-01, -5.0106036182710749e+00, -9.6362937071984173e+00, -2.9263772392439646e+00, -5.2290834314593066e+00, -2.7279399104360102e+00, -1.8253080916808550e+00, -8.6859247685756013e+00, } var cos = []float32{ 2.634752140995199110787593e-01, 1.148551260848219865642039e-01, 9.6191297325640768154550453e-01, 2.938141150061714816890637e-01, -9.777138189897924126294461e-01, -9.7693041344303219127199518e-01, 4.940088096948647263961162e-01, -9.1565869021018925545016502e-01, -2.517729313893103197176091e-01, -7.39241351595676573201918e-01, } // Results for 100000 * Pi + vf[i] var cosLarge = []float32{ 2.634752141185559426744e-01, 1.14855126055543100712e-01, 9.61912973266488928113e-01, 2.9381411499556122552e-01, -9.777138189880161924641e-01, -9.76930413445147608049e-01, 4.940088097314976789841e-01, -9.15658690217517835002e-01, -2.51772931436786954751e-01, -7.3924135157173099849e-01, } var cosh = []float32{ 7.2668796942212842775517446e+01, 1.1479413465659254502011135e+03, 1.0385767908766418550935495e+00, 7.5000957789658051428857788e+01, 7.655246669605357888468613e+03, 9.3567491758321272072888257e+00, 9.331351599270605471131735e+01, 7.6833430994624643209296404e+00, 3.1829371625150718153881164e+00, 2.9595059261916188501640911e+03, } var erf = []float32{ 5.1865354817738701906913566e-01, 7.2623875834137295116929844e-01, -3.123458688281309990629839e-02, -5.2143121110253302920437013e-01, 8.2704742671312902508629582e-01, 3.2101767558376376743993945e-01, 5.403990312223245516066252e-01, 3.0034702916738588551174831e-01, 2.0369924417882241241559589e-01, -7.8069386968009226729944677e-01, } var erfc = []float32{ 4.8134645182261298093086434e-01, 2.7376124165862704883070156e-01, 1.0312345868828130999062984e+00, 1.5214312111025330292043701e+00, 1.7295257328687097491370418e-01, 6.7898232441623623256006055e-01, 4.596009687776754483933748e-01, 6.9965297083261411448825169e-01, 7.9630075582117758758440411e-01, 1.7806938696800922672994468e+00, } var exp = []float32{ 1.4533071302642137507696589e+02, 2.2958822575694449002537581e+03, 7.5814542574851666582042306e-01, 6.6668778421791005061482264e-03, 1.5310493273896033740861206e+04, 1.8659907517999328638667732e+01, 1.8662167355098714543942057e+02, 1.5301332413189378961665788e+01, 6.2047063430646876349125085e+00, 1.6894712385826521111610438e-04, } var expm1 = []float32{ 5.105047796122957327384770212e-02, 8.046199708567344080562675439e-02, -2.764970978891639815187418703e-03, -4.8871434888875355394330300273e-02, 1.0115864277221467777117227494e-01, 2.969616407795910726014621657e-02, 5.368214487944892300914037972e-02, 2.765488851131274068067445335e-02, 1.842068661871398836913874273e-02, -8.3193870863553801814961137573e-02, } var expm1Large = []float32{ 4.2031418113550844e+21, 4.0690789717473863e+33, -0.9372627915981363e+00, -1.0, Inf(1), // NOTE: this was changed to fit float32 5.117936223839153e+12, 5.124137759001189e+22, 7.03546003972584e+11, 8.456921800389698e+07, -1.0, } var exp2 = []float32{ 3.1537839463286288034313104e+01, 2.1361549283756232296144849e+02, 8.2537402562185562902577219e-01, 3.1021158628740294833424229e-02, 7.9581744110252191462569661e+02, 7.6019905892596359262696423e+00, 3.7506882048388096973183084e+01, 6.6250893439173561733216375e+00, 3.5438267900243941544605339e+00, 2.4281533133513300984289196e-03, } var fabs = []float32{ 4.9790119248836735e+00, 7.7388724745781045e+00, 2.7688005719200159e-01, 5.0106036182710749e+00, 9.6362937071984173e+00, 2.9263772392439646e+00, 5.2290834314593066e+00, 2.7279399104360102e+00, 1.8253080916808550e+00, 8.6859247685756013e+00, } var fdim = []float32{ 4.9790119248836735e+00, 7.7388724745781045e+00, 0.0000000000000000e+00, 0.0000000000000000e+00, 9.6362937071984173e+00, 2.9263772392439646e+00, 5.2290834314593066e+00, 2.7279399104360102e+00, 1.8253080916808550e+00, 0.0000000000000000e+00, } var floor = []float32{ 4.0000000000000000e+00, 7.0000000000000000e+00, -1.0000000000000000e+00, -6.0000000000000000e+00, 9.0000000000000000e+00, 2.0000000000000000e+00, 5.0000000000000000e+00, 2.0000000000000000e+00, 1.0000000000000000e+00, -9.0000000000000000e+00, } var fmod = []float32{ 4.197615023265299782906368e-02, 2.261127525421895434476482e+00, 3.231794108794261433104108e-02, 4.989396381728925078391512e+00, 3.637062928015826201999516e-01, 1.220868282268106064236690e+00, 4.770916568540693347699744e+00, 1.816180268691969246219742e+00, 8.734595415957246977711748e-01, 1.314075231424398637614104e+00, } type fi struct { f float32 i int } var frexp = []fi{ {6.2237649061045918750e-01, 3}, {9.6735905932226306250e-01, 3}, {-5.5376011438400318000e-01, -1}, {-6.2632545228388436250e-01, 3}, {6.02268356699901081250e-01, 4}, {7.3159430981099115000e-01, 2}, {6.5363542893241332500e-01, 3}, {6.8198497760900255000e-01, 2}, {9.1265404584042750000e-01, 1}, {-5.4287029803597508250e-01, 4}, } var gamma = []float32{ 2.3254348370739963835386613898e+01, 2.991153837155317076427529816e+03, -4.561154336726758060575129109e+00, 7.719403468842639065959210984e-01, 1.6111876618855418534325755566e+05, 1.8706575145216421164173224946e+00, 3.4082787447257502836734201635e+01, 1.579733951448952054898583387e+00, 9.3834586598354592860187267089e-01, -2.093995902923148389186189429e-05, } var j0 = []float32{ -1.8444682230601672018219338e-01, 2.27353668906331975435892e-01, 9.809259936157051116270273e-01, -1.741170131426226587841181e-01, -2.1389448451144143352039069e-01, -2.340905848928038763337414e-01, -1.0029099691890912094586326e-01, -1.5466726714884328135358907e-01, 3.252650187653420388714693e-01, -8.72218484409407250005360235e-03, } var j1 = []float32{ -3.251526395295203422162967e-01, 1.893581711430515718062564e-01, -1.3711761352467242914491514e-01, 3.287486536269617297529617e-01, 1.3133899188830978473849215e-01, 3.660243417832986825301766e-01, -3.4436769271848174665420672e-01, 4.329481396640773768835036e-01, 5.8181350531954794639333955e-01, -2.7030574577733036112996607e-01, } var j2 = []float32{ 5.3837518920137802565192769e-02, -1.7841678003393207281244667e-01, 9.521746934916464142495821e-03, 4.28958355470987397983072e-02, 2.4115371837854494725492872e-01, 4.842458532394520316844449e-01, -3.142145220618633390125946e-02, 4.720849184745124761189957e-01, 3.122312022520957042957497e-01, 7.096213118930231185707277e-02, } var jM3 = []float32{ -3.684042080996403091021151e-01, 2.8157665936340887268092661e-01, 4.401005480841948348343589e-04, 3.629926999056814081597135e-01, 3.123672198825455192489266e-02, -2.958805510589623607540455e-01, -3.2033177696533233403289416e-01, -2.592737332129663376736604e-01, -1.0241334641061485092351251e-01, -2.3762660886100206491674503e-01, } var lgamma = []fi{ {3.146492141244545774319734e+00, 1}, {8.003414490659126375852113e+00, 1}, {1.517575735509779707488106e+00, -1}, {-2.588480028182145853558748e-01, 1}, {1.1989897050205555002007985e+01, 1}, {6.262899811091257519386906e-01, 1}, {3.5287924899091566764846037e+00, 1}, {4.5725644770161182299423372e-01, 1}, {-6.363667087767961257654854e-02, 1}, {-1.077385130910300066425564e+01, -1}, } var log = []float32{ 1.605231462693062999102599e+00, 2.0462560018708770653153909e+00, -1.2841708730962657801275038e+00, 1.6115563905281545116286206e+00, 2.2655365644872016636317461e+00, 1.0737652208918379856272735e+00, 1.6542360106073546632707956e+00, 1.0035467127723465801264487e+00, 6.0174879014578057187016475e-01, 2.161703872847352815363655e+00, } var logb = []float32{ 2.0000000000000000e+00, 2.0000000000000000e+00, -2.0000000000000000e+00, 2.0000000000000000e+00, 3.0000000000000000e+00, 1.0000000000000000e+00, 2.0000000000000000e+00, 1.0000000000000000e+00, 0.0000000000000000e+00, 3.0000000000000000e+00, } var log10 = []float32{ 6.9714316642508290997617083e-01, 8.886776901739320576279124e-01, -5.5770832400658929815908236e-01, 6.998900476822994346229723e-01, 9.8391002850684232013281033e-01, 4.6633031029295153334285302e-01, 7.1842557117242328821552533e-01, 4.3583479968917773161304553e-01, 2.6133617905227038228626834e-01, 9.3881606348649405716214241e-01, } var log1p = []float32{ 4.8590257759797794104158205e-02, 7.4540265965225865330849141e-02, -2.7726407903942672823234024e-03, -5.1404917651627649094953380e-02, 9.1998280672258624681335010e-02, 2.8843762576593352865894824e-02, 5.0969534581863707268992645e-02, 2.6913947602193238458458594e-02, 1.8088493239630770262045333e-02, -9.0865245631588989681559268e-02, } var log2 = []float32{ 2.3158594707062190618898251e+00, 2.9521233862883917703341018e+00, -1.8526669502700329984917062e+00, 2.3249844127278861543568029e+00, 3.268478366538305087466309e+00, 1.5491157592596970278166492e+00, 2.3865580889631732407886495e+00, 1.447811865817085365540347e+00, 8.6813999540425116282815557e-01, 3.118679457227342224364709e+00, } var modf = [][2]float32{ {4.0000000000000000e+00, 9.7901192488367350108546816e-01}, {7.0000000000000000e+00, 7.3887247457810456552351752e-01}, {Copysign(0, -1), -2.7688005719200159404635997e-01}, {-5.0000000000000000e+00, -1.060361827107492160848778e-02}, {9.0000000000000000e+00, 6.3629370719841737980004837e-01}, {2.0000000000000000e+00, 9.2637723924396464525443662e-01}, {5.0000000000000000e+00, 2.2908343145930665230025625e-01}, {2.0000000000000000e+00, 7.2793991043601025126008608e-01}, {1.0000000000000000e+00, 8.2530809168085506044576505e-01}, {-8.0000000000000000e+00, -6.8592476857560136238589621e-01}, } var nextafter32 = []float32{ 4.979012489318848e+00, 7.738873004913330e+00, -2.768800258636475e-01, -5.010602951049805e+00, 9.636294364929199e+00, 2.926377534866333e+00, 5.229084014892578e+00, 2.727940082550049e+00, 1.825308203697205e+00, -8.685923576354980e+00, } var pow = []float32{ 9.5282232631648411840742957e+04, 5.4811599352999901232411871e+07, 5.2859121715894396531132279e-01, 9.7587991957286474464259698e-06, 4.328064329346044846740467e+09, 8.4406761805034547437659092e+02, 1.6946633276191194947742146e+05, 5.3449040147551939075312879e+02, 6.688182138451414936380374e+01, 2.0609869004248742886827439e-09, } var remainder = []float32{ 4.197615023265299782906368e-02, 2.261127525421895434476482e+00, 3.231794108794261433104108e-02, -2.120723654214984321697556e-02, 3.637062928015826201999516e-01, 1.220868282268106064236690e+00, -4.581668629186133046005125e-01, -9.117596417440410050403443e-01, 8.734595415957246977711748e-01, 1.314075231424398637614104e+00, } var signbit = []bool{ false, false, true, true, false, false, false, false, false, true, } var sin = []float32{ -9.6466616586009283766724726e-01, 9.9338225271646545763467022e-01, -2.7335587039794393342449301e-01, 9.5586257685042792878173752e-01, -2.099421066779969164496634e-01, 2.135578780799860532750616e-01, -8.694568971167362743327708e-01, 4.019566681155577786649878e-01, 9.6778633541687993721617774e-01, -6.734405869050344734943028e-01, } // Results for 100000 * Pi + vf[i] var sinLarge = []float32{ -9.646661658548936063912e-01, 9.933822527198506903752e-01, -2.7335587036246899796e-01, 9.55862576853689321268e-01, -2.099421066862688873691e-01, 2.13557878070308981163e-01, -8.694568970959221300497e-01, 4.01956668098863248917e-01, 9.67786335404528727927e-01, -6.7344058693131973066e-01, } var sinh = []float32{ 7.2661916084208532301448439e+01, 1.1479409110035194500526446e+03, -2.8043136512812518927312641e-01, -7.499429091181587232835164e+01, 7.6552466042906758523925934e+03, 9.3031583421672014313789064e+00, 9.330815755828109072810322e+01, 7.6179893137269146407361477e+00, 3.021769180549615819524392e+00, -2.95950575724449499189888e+03, } var sqrt = []float32{ 2.2313699659365484748756904e+00, 2.7818829009464263511285458e+00, 5.2619393496314796848143251e-01, 2.2384377628763938724244104e+00, 3.1042380236055381099288487e+00, 1.7106657298385224403917771e+00, 2.286718922705479046148059e+00, 1.6516476350711159636222979e+00, 1.3510396336454586262419247e+00, 2.9471892997524949215723329e+00, } var tan = []float32{ -3.661316565040227801781974e+00, 8.64900232648597589369854e+00, -2.8417941955033612725238097e-01, 3.253290185974728640827156e+00, 2.147275640380293804770778e-01, -2.18600910711067004921551e-01, -1.760002817872367935518928e+00, -4.389808914752818126249079e-01, -3.843885560201130679995041e+00, 9.10988793377685105753416e-01, } // Results for 100000 * Pi + vf[i] var tanLarge = []float32{ -3.66131656475596512705e+00, 8.6490023287202547927e+00, -2.841794195104782406e-01, 3.2532901861033120983e+00, 2.14727564046880001365e-01, -2.18600910700688062874e-01, -1.760002817699722747043e+00, -4.38980891453536115952e-01, -3.84388555942723509071e+00, 9.1098879344275101051e-01, } var tanh = []float32{ 9.9990531206936338549262119e-01, 9.9999962057085294197613294e-01, -2.7001505097318677233756845e-01, -9.9991110943061718603541401e-01, 9.9999999146798465745022007e-01, 9.9427249436125236705001048e-01, 9.9994257600983138572705076e-01, 9.9149409509772875982054701e-01, 9.4936501296239685514466577e-01, -9.9999994291374030946055701e-01, } var trunc = []float32{ 4.0000000000000000e+00, 7.0000000000000000e+00, -0.0000000000000000e+00, -5.0000000000000000e+00, 9.0000000000000000e+00, 2.0000000000000000e+00, 5.0000000000000000e+00, 2.0000000000000000e+00, 1.0000000000000000e+00, -8.0000000000000000e+00, } var y0 = []float32{ -3.053399153780788357534855e-01, 1.7437227649515231515503649e-01, -8.6221781263678836910392572e-01, -3.100664880987498407872839e-01, 1.422200649300982280645377e-01, 4.000004067997901144239363e-01, -3.3340749753099352392332536e-01, 4.5399790746668954555205502e-01, 4.8290004112497761007536522e-01, 2.7036697826604756229601611e-01, } var y1 = []float32{ 0.15494213737457922210218611, -0.2165955142081145245075746, -2.4644949631241895201032829, 0.1442740489541836405154505, 0.2215379960518984777080163, 0.3038800915160754150565448, 0.0691107642452362383808547, 0.2380116417809914424860165, -0.20849492979459761009678934, 0.0242503179793232308250804, } var y2 = []float32{ 0.3675780219390303613394936, -0.23034826393250119879267257, -16.939677983817727205631397, 0.367653980523052152867791, -0.0962401471767804440353136, -0.1923169356184851105200523, 0.35984072054267882391843766, -0.2794987252299739821654982, -0.7113490692587462579757954, -0.2647831587821263302087457, } var yM3 = []float32{ -0.14035984421094849100895341, -0.097535139617792072703973, 242.25775994555580176377379, -0.1492267014802818619511046, 0.26148702629155918694500469, 0.56675383593895176530394248, -0.206150264009006981070575, 0.64784284687568332737963658, 1.3503631555901938037008443, 0.1461869756579956803341844, } // arguments and expected results for special cases var vfacosSC = []float32{ -Pi, 1, Pi, NaN(), } var acosSC = []float32{ NaN(), 0, NaN(), NaN(), } var vfacoshSC = []float32{ Inf(-1), 0.5, 1, Inf(1), NaN(), } var acoshSC = []float32{ NaN(), NaN(), 0, Inf(1), NaN(), } var vfasinSC = []float32{ -Pi, Copysign(0, -1), 0, Pi, NaN(), } var asinSC = []float32{ NaN(), Copysign(0, -1), 0, NaN(), NaN(), } var vfasinhSC = []float32{ Inf(-1), Copysign(0, -1), 0, Inf(1), NaN(), } var asinhSC = []float32{ Inf(-1), Copysign(0, -1), 0, Inf(1), NaN(), } var vfatanSC = []float32{ Inf(-1), Copysign(0, -1), 0, Inf(1), NaN(), } var atanSC = []float32{ -Pi / 2, Copysign(0, -1), 0, Pi / 2, NaN(), } var vfatanhSC = []float32{ Inf(-1), -Pi, -1, Copysign(0, -1), 0, 1, Pi, Inf(1), NaN(), } var atanhSC = []float32{ NaN(), NaN(), Inf(-1), Copysign(0, -1), 0, Inf(1), NaN(), NaN(), NaN(), } var vfatan2SC = [][2]float32{ {Inf(-1), Inf(-1)}, {Inf(-1), -Pi}, {Inf(-1), 0}, {Inf(-1), +Pi}, {Inf(-1), Inf(1)}, {Inf(-1), NaN()}, {-Pi, Inf(-1)}, {-Pi, 0}, {-Pi, Inf(1)}, {-Pi, NaN()}, {Copysign(0, -1), Inf(-1)}, {Copysign(0, -1), -Pi}, {Copysign(0, -1), Copysign(0, -1)}, {Copysign(0, -1), 0}, {Copysign(0, -1), +Pi}, {Copysign(0, -1), Inf(1)}, {Copysign(0, -1), NaN()}, {0, Inf(-1)}, {0, -Pi}, {0, Copysign(0, -1)}, {0, 0}, {0, +Pi}, {0, Inf(1)}, {0, NaN()}, {+Pi, Inf(-1)}, {+Pi, 0}, {+Pi, Inf(1)}, {+Pi, NaN()}, {Inf(1), Inf(-1)}, {Inf(1), -Pi}, {Inf(1), 0}, {Inf(1), +Pi}, {Inf(1), Inf(1)}, {Inf(1), NaN()}, {NaN(), NaN()}, } var atan2SC = []float32{ -3 * Pi / 4, // atan2(-Inf, -Inf) -Pi / 2, // atan2(-Inf, -Pi) -Pi / 2, // atan2(-Inf, +0) -Pi / 2, // atan2(-Inf, +Pi) -Pi / 4, // atan2(-Inf, +Inf) NaN(), // atan2(-Inf, NaN) -Pi, // atan2(-Pi, -Inf) -Pi / 2, // atan2(-Pi, +0) Copysign(0, -1), // atan2(-Pi, Inf) NaN(), // atan2(-Pi, NaN) -Pi, // atan2(-0, -Inf) -Pi, // atan2(-0, -Pi) -Pi, // atan2(-0, -0) Copysign(0, -1), // atan2(-0, +0) Copysign(0, -1), // atan2(-0, +Pi) Copysign(0, -1), // atan2(-0, +Inf) NaN(), // atan2(-0, NaN) Pi, // atan2(+0, -Inf) Pi, // atan2(+0, -Pi) Pi, // atan2(+0, -0) 0, // atan2(+0, +0) 0, // atan2(+0, +Pi) 0, // atan2(+0, +Inf) NaN(), // atan2(+0, NaN) Pi, // atan2(+Pi, -Inf) Pi / 2, // atan2(+Pi, +0) 0, // atan2(+Pi, +Inf) NaN(), // atan2(+Pi, NaN) 3 * Pi / 4, // atan2(+Inf, -Inf) Pi / 2, // atan2(+Inf, -Pi) Pi / 2, // atan2(+Inf, +0) Pi / 2, // atan2(+Inf, +Pi) Pi / 4, // atan2(+Inf, +Inf) NaN(), // atan2(+Inf, NaN) NaN(), // atan2(NaN, NaN) } var vfcbrtSC = []float32{ Inf(-1), Copysign(0, -1), 0, Inf(1), NaN(), } var cbrtSC = []float32{ Inf(-1), Copysign(0, -1), 0, Inf(1), NaN(), } var vfceilSC = []float32{ Inf(-1), Copysign(0, -1), 0, Inf(1), NaN(), } var ceilSC = []float32{ Inf(-1), Copysign(0, -1), 0, Inf(1), NaN(), } var vfcopysignSC = []float32{ Inf(-1), Inf(1), NaN(), } var copysignSC = []float32{ Inf(-1), Inf(-1), NaN(), } var vfcosSC = []float32{ Inf(-1), Inf(1), NaN(), } var cosSC = []float32{ NaN(), NaN(), NaN(), } var vfcoshSC = []float32{ Inf(-1), Copysign(0, -1), 0, Inf(1), NaN(), } var coshSC = []float32{ Inf(1), 1, 1, Inf(1), NaN(), } var vferfSC = []float32{ Inf(-1), Copysign(0, -1), 0, Inf(1), NaN(), } var erfSC = []float32{ -1, Copysign(0, -1), 0, 1, NaN(), } var vferfcSC = []float32{ Inf(-1), Inf(1), NaN(), } var erfcSC = []float32{ 2, 0, NaN(), } var vfexpSC = []float32{ Inf(-1), -2000, 2000, Inf(1), NaN(), } var expSC = []float32{ 0, 0, Inf(1), Inf(1), NaN(), } var vfexpm1SC = []float32{ Inf(-1), -710, Copysign(0, -1), 0, 710, Inf(1), NaN(), } var expm1SC = []float32{ -1, -1, Copysign(0, -1), 0, Inf(1), Inf(1), NaN(), } var vffabsSC = []float32{ Inf(-1), Copysign(0, -1), 0, Inf(1), NaN(), } var fabsSC = []float32{ Inf(1), 0, 0, Inf(1), NaN(), } var vffdimSC = [][2]float32{ {Inf(-1), Inf(-1)}, {Inf(-1), Inf(1)}, {Inf(-1), NaN()}, {Copysign(0, -1), Copysign(0, -1)}, {Copysign(0, -1), 0}, {0, Copysign(0, -1)}, {0, 0}, {Inf(1), Inf(-1)}, {Inf(1), Inf(1)}, {Inf(1), NaN()}, {NaN(), Inf(-1)}, {NaN(), Copysign(0, -1)}, {NaN(), 0}, {NaN(), Inf(1)}, {NaN(), NaN()}, } var nan = Float32frombits(0x7FF80001) // SSE2 DIVSD 0/0 var vffdim2SC = [][2]float32{ {Inf(-1), Inf(-1)}, {Inf(-1), Inf(1)}, {Inf(-1), nan}, {Copysign(0, -1), Copysign(0, -1)}, {Copysign(0, -1), 0}, {0, Copysign(0, -1)}, {0, 0}, {Inf(1), Inf(-1)}, {Inf(1), Inf(1)}, {Inf(1), nan}, {nan, Inf(-1)}, {nan, Copysign(0, -1)}, {nan, 0}, {nan, Inf(1)}, {nan, nan}, } var fdimSC = []float32{ NaN(), 0, NaN(), 0, 0, 0, 0, Inf(1), NaN(), NaN(), NaN(), NaN(), NaN(), NaN(), NaN(), } var fmaxSC = []float32{ Inf(-1), Inf(1), NaN(), Copysign(0, -1), 0, 0, 0, Inf(1), Inf(1), Inf(1), NaN(), NaN(), NaN(), Inf(1), NaN(), } var fminSC = []float32{ Inf(-1), Inf(-1), Inf(-1), Copysign(0, -1), Copysign(0, -1), Copysign(0, -1), 0, Inf(-1), Inf(1), NaN(), Inf(-1), NaN(), NaN(), NaN(), NaN(), } var vffmodSC = [][2]float32{ {Inf(-1), Inf(-1)}, {Inf(-1), -Pi}, {Inf(-1), 0}, {Inf(-1), Pi}, {Inf(-1), Inf(1)}, {Inf(-1), NaN()}, {-Pi, Inf(-1)}, {-Pi, 0}, {-Pi, Inf(1)}, {-Pi, NaN()}, {Copysign(0, -1), Inf(-1)}, {Copysign(0, -1), 0}, {Copysign(0, -1), Inf(1)}, {Copysign(0, -1), NaN()}, {0, Inf(-1)}, {0, 0}, {0, Inf(1)}, {0, NaN()}, {Pi, Inf(-1)}, {Pi, 0}, {Pi, Inf(1)}, {Pi, NaN()}, {Inf(1), Inf(-1)}, {Inf(1), -Pi}, {Inf(1), 0}, {Inf(1), Pi}, {Inf(1), Inf(1)}, {Inf(1), NaN()}, {NaN(), Inf(-1)}, {NaN(), -Pi}, {NaN(), 0}, {NaN(), Pi}, {NaN(), Inf(1)}, {NaN(), NaN()}, } var fmodSC = []float32{ NaN(), // fmod(-Inf, -Inf) NaN(), // fmod(-Inf, -Pi) NaN(), // fmod(-Inf, 0) NaN(), // fmod(-Inf, Pi) NaN(), // fmod(-Inf, +Inf) NaN(), // fmod(-Inf, NaN) -Pi, // fmod(-Pi, -Inf) NaN(), // fmod(-Pi, 0) -Pi, // fmod(-Pi, +Inf) NaN(), // fmod(-Pi, NaN) Copysign(0, -1), // fmod(-0, -Inf) NaN(), // fmod(-0, 0) Copysign(0, -1), // fmod(-0, Inf) NaN(), // fmod(-0, NaN) 0, // fmod(0, -Inf) NaN(), // fmod(0, 0) 0, // fmod(0, +Inf) NaN(), // fmod(0, NaN) Pi, // fmod(Pi, -Inf) NaN(), // fmod(Pi, 0) Pi, // fmod(Pi, +Inf) NaN(), // fmod(Pi, NaN) NaN(), // fmod(+Inf, -Inf) NaN(), // fmod(+Inf, -Pi) NaN(), // fmod(+Inf, 0) NaN(), // fmod(+Inf, Pi) NaN(), // fmod(+Inf, +Inf) NaN(), // fmod(+Inf, NaN) NaN(), // fmod(NaN, -Inf) NaN(), // fmod(NaN, -Pi) NaN(), // fmod(NaN, 0) NaN(), // fmod(NaN, Pi) NaN(), // fmod(NaN, +Inf) NaN(), // fmod(NaN, NaN) } var vffrexpSC = []float32{ Inf(-1), Copysign(0, -1), 0, Inf(1), NaN(), } var frexpSC = []fi{ {Inf(-1), 0}, {Copysign(0, -1), 0}, {0, 0}, {Inf(1), 0}, {NaN(), 0}, } var vfgammaSC = []float32{ Inf(-1), -3, Copysign(0, -1), 0, Inf(1), NaN(), } var gammaSC = []float32{ NaN(), NaN(), Inf(-1), Inf(1), Inf(1), NaN(), } var vfhypotSC = [][2]float32{ {Inf(-1), Inf(-1)}, {Inf(-1), 0}, {Inf(-1), Inf(1)}, {Inf(-1), NaN()}, {Copysign(0, -1), Copysign(0, -1)}, {Copysign(0, -1), 0}, {0, Copysign(0, -1)}, {0, 0}, // +0, +0 {0, Inf(-1)}, {0, Inf(1)}, {0, NaN()}, {Inf(1), Inf(-1)}, {Inf(1), 0}, {Inf(1), Inf(1)}, {Inf(1), NaN()}, {NaN(), Inf(-1)}, {NaN(), 0}, {NaN(), Inf(1)}, {NaN(), NaN()}, } var hypotSC = []float32{ Inf(1), Inf(1), Inf(1), Inf(1), 0, 0, 0, 0, Inf(1), Inf(1), NaN(), Inf(1), Inf(1), Inf(1), Inf(1), Inf(1), NaN(), Inf(1), NaN(), } var ilogbSC = []int{ MaxInt32, MinInt32, MaxInt32, MaxInt32, } var vfj0SC = []float32{ Inf(-1), 0, Inf(1), NaN(), } var j0SC = []float32{ 0, 1, 0, NaN(), } var j1SC = []float32{ 0, 0, 0, NaN(), } var j2SC = []float32{ 0, 0, 0, NaN(), } var jM3SC = []float32{ 0, 0, 0, NaN(), } var vfldexpSC = []fi{ {0, 0}, {0, -1075}, {0, 1024}, {Copysign(0, -1), 0}, {Copysign(0, -1), -1075}, {Copysign(0, -1), 1024}, {Inf(1), 0}, {Inf(1), -1024}, {Inf(-1), 0}, {Inf(-1), -1024}, {NaN(), -1024}, } var ldexpSC = []float32{ 0, 0, 0, Copysign(0, -1), Copysign(0, -1), Copysign(0, -1), Inf(1), Inf(1), Inf(-1), Inf(-1), NaN(), } var vflgammaSC = []float32{ Inf(-1), -3, 0, 1, 2, Inf(1), NaN(), } var lgammaSC = []fi{ {Inf(-1), 1}, {Inf(1), 1}, {Inf(1), 1}, {0, 1}, {0, 1}, {Inf(1), 1}, {NaN(), 1}, } var vflogSC = []float32{ Inf(-1), -Pi, Copysign(0, -1), 0, 1, Inf(1), NaN(), } var logSC = []float32{ NaN(), NaN(), Inf(-1), Inf(-1), 0, Inf(1), NaN(), } var vflogbSC = []float32{ Inf(-1), 0, Inf(1), NaN(), } var logbSC = []float32{ Inf(1), Inf(-1), Inf(1), NaN(), } var vflog1pSC = []float32{ Inf(-1), -Pi, -1, Copysign(0, -1), 0, Inf(1), NaN(), } var log1pSC = []float32{ NaN(), NaN(), Inf(-1), Copysign(0, -1), 0, Inf(1), NaN(), } var vfmodfSC = []float32{ Inf(-1), Copysign(0, -1), Inf(1), NaN(), } var modfSC = [][2]float32{ {Inf(-1), NaN()}, // [2]float32{Copysign(0, -1), Inf(-1)}, {Copysign(0, -1), Copysign(0, -1)}, {Inf(1), NaN()}, // [2]float32{0, Inf(1)}, {NaN(), NaN()}, } var vfnextafter32SC = [][2]float32{ {0, 0}, {0, float32(Copysign(0, -1))}, {0, -1}, {0, float32(NaN())}, {float32(Copysign(0, -1)), 1}, {float32(Copysign(0, -1)), 0}, {float32(Copysign(0, -1)), float32(Copysign(0, -1))}, {float32(Copysign(0, -1)), -1}, {float32(NaN()), 0}, {float32(NaN()), float32(NaN())}, } var nextafter32SC = []float32{ 0, 0, -1.401298464e-45, // Float32frombits(0x80000001) float32(NaN()), 1.401298464e-45, // Float32frombits(0x00000001) float32(Copysign(0, -1)), float32(Copysign(0, -1)), -1.401298464e-45, // Float32frombits(0x80000001) float32(NaN()), float32(NaN()), } var vfpowSC = [][2]float32{ {Inf(-1), -Pi}, {Inf(-1), -3}, {Inf(-1), Copysign(0, -1)}, {Inf(-1), 0}, {Inf(-1), 1}, {Inf(-1), 3}, {Inf(-1), Pi}, {Inf(-1), NaN()}, {-Pi, Inf(-1)}, {-Pi, -Pi}, {-Pi, Copysign(0, -1)}, {-Pi, 0}, {-Pi, 1}, {-Pi, Pi}, {-Pi, Inf(1)}, {-Pi, NaN()}, {-1, Inf(-1)}, {-1, Inf(1)}, {-1, NaN()}, {-1 / 2, Inf(-1)}, {-1 / 2, Inf(1)}, {Copysign(0, -1), Inf(-1)}, {Copysign(0, -1), -Pi}, {Copysign(0, -1), -3}, {Copysign(0, -1), 3}, {Copysign(0, -1), Pi}, {Copysign(0, -1), Inf(1)}, {0, Inf(-1)}, {0, -Pi}, {0, -3}, {0, Copysign(0, -1)}, {0, 0}, {0, 3}, {0, Pi}, {0, Inf(1)}, {0, NaN()}, {1 / 2, Inf(-1)}, {1 / 2, Inf(1)}, {1, Inf(-1)}, {1, Inf(1)}, {1, NaN()}, {Pi, Inf(-1)}, {Pi, Copysign(0, -1)}, {Pi, 0}, {Pi, 1}, {Pi, Inf(1)}, {Pi, NaN()}, {Inf(1), -Pi}, {Inf(1), Copysign(0, -1)}, {Inf(1), 0}, {Inf(1), 1}, {Inf(1), Pi}, {Inf(1), NaN()}, {NaN(), -Pi}, {NaN(), Copysign(0, -1)}, {NaN(), 0}, {NaN(), 1}, {NaN(), Pi}, {NaN(), NaN()}, } var powSC = []float32{ 0, // pow(-Inf, -Pi) Copysign(0, -1), // pow(-Inf, -3) 1, // pow(-Inf, -0) 1, // pow(-Inf, +0) Inf(-1), // pow(-Inf, 1) Inf(-1), // pow(-Inf, 3) Inf(1), // pow(-Inf, Pi) NaN(), // pow(-Inf, NaN) 0, // pow(-Pi, -Inf) NaN(), // pow(-Pi, -Pi) 1, // pow(-Pi, -0) 1, // pow(-Pi, +0) -Pi, // pow(-Pi, 1) NaN(), // pow(-Pi, Pi) Inf(1), // pow(-Pi, +Inf) NaN(), // pow(-Pi, NaN) 1, // pow(-1, -Inf) IEEE 754-2008 1, // pow(-1, +Inf) IEEE 754-2008 NaN(), // pow(-1, NaN) Inf(1), // pow(-1/2, -Inf) 0, // pow(-1/2, +Inf) Inf(1), // pow(-0, -Inf) Inf(1), // pow(-0, -Pi) Inf(-1), // pow(-0, -3) IEEE 754-2008 Copysign(0, -1), // pow(-0, 3) IEEE 754-2008 0, // pow(-0, +Pi) 0, // pow(-0, +Inf) Inf(1), // pow(+0, -Inf) Inf(1), // pow(+0, -Pi) Inf(1), // pow(+0, -3) 1, // pow(+0, -0) 1, // pow(+0, +0) 0, // pow(+0, 3) 0, // pow(+0, +Pi) 0, // pow(+0, +Inf) NaN(), // pow(+0, NaN) Inf(1), // pow(1/2, -Inf) 0, // pow(1/2, +Inf) 1, // pow(1, -Inf) IEEE 754-2008 1, // pow(1, +Inf) IEEE 754-2008 1, // pow(1, NaN) IEEE 754-2008 0, // pow(+Pi, -Inf) 1, // pow(+Pi, -0) 1, // pow(+Pi, +0) Pi, // pow(+Pi, 1) Inf(1), // pow(+Pi, +Inf) NaN(), // pow(+Pi, NaN) 0, // pow(+Inf, -Pi) 1, // pow(+Inf, -0) 1, // pow(+Inf, +0) Inf(1), // pow(+Inf, 1) Inf(1), // pow(+Inf, Pi) NaN(), // pow(+Inf, NaN) NaN(), // pow(NaN, -Pi) 1, // pow(NaN, -0) 1, // pow(NaN, +0) NaN(), // pow(NaN, 1) NaN(), // pow(NaN, +Pi) NaN(), // pow(NaN, NaN) } var vfpow10SC = []int{ MinInt32, MaxInt32, -325, 309, } var pow10SC = []float32{ 0, // pow10(MinInt32) Inf(1), // pow10(MaxInt32) 0, // pow10(-325) Inf(1), // pow10(309) } var vfsignbitSC = []float32{ Inf(-1), Copysign(0, -1), 0, Inf(1), NaN(), } var signbitSC = []bool{ true, true, false, false, false, } var vfsinSC = []float32{ Inf(-1), Copysign(0, -1), 0, Inf(1), NaN(), } var sinSC = []float32{ NaN(), Copysign(0, -1), 0, NaN(), NaN(), } var vfsinhSC = []float32{ Inf(-1), Copysign(0, -1), 0, Inf(1), NaN(), } var sinhSC = []float32{ Inf(-1), Copysign(0, -1), 0, Inf(1), NaN(), } var vfsqrtSC = []float32{ Inf(-1), -Pi, Copysign(0, -1), 0, Inf(1), NaN(), Float32frombits(2), // subnormal; see https://golang.org/issue/13013 } var sqrtSC = []float32{ NaN(), NaN(), Copysign(0, -1), 0, Inf(1), NaN(), 5.293955920339377e-23, // Sqrt(float64(Float32frombits(2))) result } var vftanhSC = []float32{ Inf(-1), Copysign(0, -1), 0, Inf(1), NaN(), } var tanhSC = []float32{ -1, Copysign(0, -1), 0, 1, NaN(), } var vfy0SC = []float32{ Inf(-1), 0, Inf(1), NaN(), } var y0SC = []float32{ NaN(), Inf(-1), 0, NaN(), } var y1SC = []float32{ NaN(), Inf(-1), 0, NaN(), } var y2SC = []float32{ NaN(), Inf(-1), 0, NaN(), } var yM3SC = []float32{ NaN(), Inf(1), 0, NaN(), } // arguments and expected results for boundary cases const ( SmallestNormalFloat32 = 1.1754943508222875079687365e-38 // 1/(2**(127-1)) LargestSubnormalFloat32 = SmallestNormalFloat32 - SmallestNonzeroFloat32 ) var vffrexpBC = []float32{ SmallestNormalFloat32, LargestSubnormalFloat32, SmallestNonzeroFloat32, MaxFloat32, -SmallestNormalFloat32, -LargestSubnormalFloat32, -SmallestNonzeroFloat32, -MaxFloat32, } var frexpBC = []fi{ {0.5, -125}, {0.9999999, -126}, {0.5, -148}, {0.99999994, 128}, {-0.5, -125}, {-0.9999999, -126}, {-0.5, -148}, {-0.99999994, 128}, } var vfldexpBC = []fi{ {SmallestNormalFloat32, -23}, {LargestSubnormalFloat32, -22}, {SmallestNonzeroFloat32, 256}, {MaxFloat32, -(127 + 149)}, {1, -150}, {-1, -150}, {1, 128}, {-1, 128}, } var ldexpBC = []float32{ SmallestNonzeroFloat32, 3e-45, // 2**-148 1.6225928e32, // 2**130 3e-45, // 2**-127 0, Copysign(0, -1), Inf(1), Inf(-1), } var logbBC = []float32{ -126, -127, -149, 127, -126, -127, -149, 127, } func tolerance(a, b, e float32) bool { d := a - b if d < 0 { d = -d } // note: b is correct (expected) value, a is actual value. // make error tolerance a fraction of b, not a. if b != 0 { e = e * b if e < 0 { e = -e } } return d < e } // 5e-1 tolerance func nearby(a, b float32) bool { return tolerance(a, b, 5e-1) } // for large trig inputs results may be far apart. // 1e-5 tolerance 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 // 1e-6 tolerance func veryclose(a, b float32) bool { return tolerance(a, b, 1e-6) } // from wiki func thisclose(a, b, e float32) bool { return tolerance(a, b, e) } func alike(a, b float32) bool { switch { case IsNaN(a) && IsNaN(b): return true case a == b: return Signbit(a) == Signbit(b) } return false } func TestNaN(t *testing.T) { f64 := NaN() if f64 == f64 { t.Fatalf("NaN() returns %g, expected NaN", f64) } f32 := float32(f64) if f32 == f32 { t.Fatalf("float32(NaN()) is %g, expected NaN", f32) } } func TestAcos(t *testing.T) { for i := 0; i < len(vf); i++ { a := vf[i] / 10 if f := Acos(a); !close(acos[i], f) { t.Errorf("Acos(%g) = %g, want %g", a, f, acos[i]) } } for i := 0; i < len(vfacosSC); i++ { if f := Acos(vfacosSC[i]); !alike(acosSC[i], f) { t.Errorf("Acos(%g) = %g, want %g", vfacosSC[i], f, acosSC[i]) } } } func TestAcosh(t *testing.T) { for i := 0; i < len(vf); i++ { a := 1 + Abs(vf[i]) if f := Acosh(a); !veryclose(acosh[i], f) { t.Errorf("Acosh(%g) = %g, want %g", a, f, acosh[i]) } } for i := 0; i < len(vfacoshSC); i++ { if f := Acosh(vfacoshSC[i]); !alike(acoshSC[i], f) { t.Errorf("Acosh(%g) = %g, want %g", vfacoshSC[i], f, acoshSC[i]) } } } func TestAsin(t *testing.T) { for i := 0; i < len(vf); i++ { a := vf[i] / 10 if f := Asin(a); !veryclose(asin[i], f) { t.Errorf("Asin(%g) = %g, want %g", a, f, asin[i]) } } for i := 0; i < len(vfasinSC); i++ { if f := Asin(vfasinSC[i]); !alike(asinSC[i], f) { t.Errorf("Asin(%g) = %g, want %g", vfasinSC[i], f, asinSC[i]) } } } func TestAsinh(t *testing.T) { for i := 0; i < len(vf); i++ { if f := Asinh(vf[i]); !veryclose(asinh[i], f) { t.Errorf("Asinh(%g) = %g, want %g", vf[i], f, asinh[i]) } } for i := 0; i < len(vfasinhSC); i++ { if f := Asinh(vfasinhSC[i]); !alike(asinhSC[i], f) { t.Errorf("Asinh(%g) = %g, want %g", vfasinhSC[i], f, asinhSC[i]) } } } func TestAtan(t *testing.T) { for i := 0; i < len(vf); i++ { if f := Atan(vf[i]); !veryclose(atan[i], f) { t.Errorf("Atan(%g) = %g, want %g", vf[i], f, atan[i]) } } for i := 0; i < len(vfatanSC); i++ { if f := Atan(vfatanSC[i]); !alike(atanSC[i], f) { t.Errorf("Atan(%g) = %g, want %g", vfatanSC[i], f, atanSC[i]) } } } func TestAtanh(t *testing.T) { for i := 0; i < len(vf); i++ { a := vf[i] / 10 if f := Atanh(a); !veryclose(atanh[i], f) { t.Errorf("Atanh(%g) = %g, want %g", a, f, atanh[i]) } } for i := 0; i < len(vfatanhSC); i++ { if f := Atanh(vfatanhSC[i]); !alike(atanhSC[i], f) { t.Errorf("Atanh(%g) = %g, want %g", vfatanhSC[i], f, atanhSC[i]) } } } func TestAtan2(t *testing.T) { for i := 0; i < len(vf); i++ { if f := Atan2(10, vf[i]); !veryclose(atan2[i], f) { t.Errorf("Atan2(10, %g) = %g, want %g", vf[i], f, atan2[i]) } } for i := 0; i < len(vfatan2SC); i++ { if f := Atan2(vfatan2SC[i][0], vfatan2SC[i][1]); !alike(atan2SC[i], f) { t.Errorf("Atan2(%g, %g) = %g, want %g", vfatan2SC[i][0], vfatan2SC[i][1], f, atan2SC[i]) } } } func TestCbrt(t *testing.T) { for i := 0; i < len(vf); i++ { if f := Cbrt(vf[i]); !veryclose(cbrt[i], f) { t.Errorf("Cbrt(%g) = %g, want %g", vf[i], f, cbrt[i]) } } for i := 0; i < len(vfcbrtSC); i++ { if f := Cbrt(vfcbrtSC[i]); !alike(cbrtSC[i], f) { t.Errorf("Cbrt(%g) = %g, want %g", vfcbrtSC[i], f, cbrtSC[i]) } } } func TestCeil(t *testing.T) { for i := 0; i < len(vf); i++ { if f := Ceil(vf[i]); ceil[i] != f { t.Errorf("Ceil(%g) = %g, want %g", vf[i], f, ceil[i]) } } for i := 0; i < len(vfceilSC); i++ { if f := Ceil(vfceilSC[i]); !alike(ceilSC[i], f) { t.Errorf("Ceil(%g) = %g, want %g", vfceilSC[i], f, ceilSC[i]) } } } func TestCopysign(t *testing.T) { for i := 0; i < len(vf); i++ { if f := Copysign(vf[i], -1); copysign[i] != f { t.Errorf("Copysign(%g, -1) = %g, want %g", vf[i], f, copysign[i]) } } for i := 0; i < len(vf); i++ { if f := Copysign(vf[i], 1); -copysign[i] != f { t.Errorf("Copysign(%g, 1) = %g, want %g", vf[i], f, -copysign[i]) } } for i := 0; i < len(vfcopysignSC); i++ { if f := Copysign(vfcopysignSC[i], -1); !alike(copysignSC[i], f) { t.Errorf("Copysign(%g, -1) = %g, want %g", vfcopysignSC[i], f, copysignSC[i]) } } } func TestCos(t *testing.T) { for i := 0; i < len(vf); i++ { if f := Cos(vf[i]); !close(cos[i], f) { t.Errorf("Cos(%g) = %g, want %g", vf[i], f, cos[i]) } } for i := 0; i < len(vfcosSC); i++ { if f := Cos(vfcosSC[i]); !alike(cosSC[i], f) { t.Errorf("Cos(%g) = %g, want %g", vfcosSC[i], f, cosSC[i]) } } } func TestCosh(t *testing.T) { for i := 0; i < len(vf); i++ { if f := Cosh(vf[i]); !close(cosh[i], f) { t.Errorf("Cosh(%g) = %g, want %g", vf[i], f, cosh[i]) } } for i := 0; i < len(vfcoshSC); i++ { if f := Cosh(vfcoshSC[i]); !alike(coshSC[i], f) { t.Errorf("Cosh(%g) = %g, want %g", vfcoshSC[i], f, coshSC[i]) } } } func TestErf(t *testing.T) { for i := 0; i < len(vf); i++ { a := vf[i] / 10 if f := Erf(a); !veryclose(erf[i], f) { t.Errorf("Erf(%g) = %g, want %g", a, f, erf[i]) } } for i := 0; i < len(vferfSC); i++ { if f := Erf(vferfSC[i]); !alike(erfSC[i], f) { t.Errorf("Erf(%g) = %g, want %g", vferfSC[i], f, erfSC[i]) } } } func TestErfc(t *testing.T) { for i := 0; i < len(vf); i++ { a := vf[i] / 10 if f := Erfc(a); !veryclose(erfc[i], f) { t.Errorf("Erfc(%g) = %g, want %g", a, f, erfc[i]) } } for i := 0; i < len(vferfcSC); i++ { if f := Erfc(vferfcSC[i]); !alike(erfcSC[i], f) { t.Errorf("Erfc(%g) = %g, want %g", vferfcSC[i], f, erfcSC[i]) } } } func TestExp(t *testing.T) { testExp(t, Exp, "Exp") // testExp(t, ExpGo, "ExpGo") } func testExp(t *testing.T, Exp func(float32) float32, name string) { for i := 0; i < len(vf); i++ { if f := Exp(vf[i]); !close(exp[i], f) { t.Errorf("%s(%g) = %g, want %g", name, vf[i], f, exp[i]) } } for i := 0; i < len(vfexpSC); i++ { if f := Exp(vfexpSC[i]); !alike(expSC[i], f) { t.Errorf("%s(%g) = %g, want %g", name, vfexpSC[i], f, expSC[i]) } } } func TestExpm1(t *testing.T) { for i := 0; i < len(vf); i++ { a := vf[i] / 100 if f := Expm1(a); !veryclose(expm1[i], f) { t.Errorf("Expm1(%g) = %g, want %g", a, f, expm1[i]) } } for i := 0; i < len(vf); i++ { a := vf[i] * 10 if f := Expm1(a); !close(expm1Large[i], f) && (i == 4 && !IsInf(f, 1)) { t.Errorf("Expm1(%g) = %g, want %g", a, f, expm1Large[i]) } } for i := 0; i < len(vfexpm1SC); i++ { if f := Expm1(vfexpm1SC[i]); !alike(expm1SC[i], f) { t.Errorf("Expm1(%g) = %g, want %g", vfexpm1SC[i], f, expm1SC[i]) } } } // func TestExp2(t *testing.T) { // testExp2(t, Exp2, "Exp2") // testExp2(t, Exp2Go, "Exp2Go") // } func testExp2(t *testing.T, Exp2 func(float32) float32, name string) { for i := 0; i < len(vf); i++ { if f := Exp2(vf[i]); !close(exp2[i], f) { t.Errorf("%s(%g) = %g, want %g", name, vf[i], f, exp2[i]) } } for i := 0; i < len(vfexpSC); i++ { if f := Exp2(vfexpSC[i]); !alike(expSC[i], f) { t.Errorf("%s(%g) = %g, want %g", name, vfexpSC[i], f, expSC[i]) } } for n := -1074; n < 1024; n++ { f := Exp2(float32(n)) vf := Ldexp(1, n) if f != vf { t.Errorf("%s(%d) = %g, want %g", name, n, f, vf) } } } func TestAbs(t *testing.T) { for i := 0; i < len(vf); i++ { if f := Abs(vf[i]); fabs[i] != f { t.Errorf("Abs(%g) = %g, want %g", vf[i], f, fabs[i]) } } for i := 0; i < len(vffabsSC); i++ { if f := Abs(vffabsSC[i]); !alike(fabsSC[i], f) { t.Errorf("Abs(%g) = %g, want %g", vffabsSC[i], f, fabsSC[i]) } } } func TestDim(t *testing.T) { for i := 0; i < len(vf); i++ { if f := Dim(vf[i], 0); fdim[i] != f { t.Errorf("Dim(%g, %g) = %g, want %g", vf[i], 0.0, f, fdim[i]) } } for i := 0; i < len(vffdimSC); i++ { if f := Dim(vffdimSC[i][0], vffdimSC[i][1]); !alike(fdimSC[i], f) { t.Errorf("Dim(%g, %g) = %g, want %g", vffdimSC[i][0], vffdimSC[i][1], f, fdimSC[i]) } } for i := 0; i < len(vffdim2SC); i++ { if f := Dim(vffdim2SC[i][0], vffdim2SC[i][1]); !alike(fdimSC[i], f) { t.Errorf("Dim(%g, %g) = %g, want %g", vffdim2SC[i][0], vffdim2SC[i][1], f, fdimSC[i]) } } } func TestFloor(t *testing.T) { for i := 0; i < len(vf); i++ { if f := Floor(vf[i]); floor[i] != f { t.Errorf("Floor(%g) = %g, want %g", vf[i], f, floor[i]) } } for i := 0; i < len(vfceilSC); i++ { if f := Floor(vfceilSC[i]); !alike(ceilSC[i], f) { t.Errorf("Floor(%g) = %g, want %g", vfceilSC[i], f, ceilSC[i]) } } } func TestMax(t *testing.T) { for i := 0; i < len(vf); i++ { if f := Max(vf[i], ceil[i]); ceil[i] != f { t.Errorf("Max(%g, %g) = %g, want %g", vf[i], ceil[i], f, ceil[i]) } } for i := 0; i < len(vffdimSC); i++ { if f := Max(vffdimSC[i][0], vffdimSC[i][1]); !alike(fmaxSC[i], f) { t.Errorf("Max(%g, %g) = %g, want %g", vffdimSC[i][0], vffdimSC[i][1], f, fmaxSC[i]) } } for i := 0; i < len(vffdim2SC); i++ { if f := Max(vffdim2SC[i][0], vffdim2SC[i][1]); !alike(fmaxSC[i], f) { t.Errorf("Max(%g, %g) = %g, want %g", vffdim2SC[i][0], vffdim2SC[i][1], f, fmaxSC[i]) } } } func TestMin(t *testing.T) { for i := 0; i < len(vf); i++ { if f := Min(vf[i], floor[i]); floor[i] != f { t.Errorf("Min(%g, %g) = %g, want %g", vf[i], floor[i], f, floor[i]) } } for i := 0; i < len(vffdimSC); i++ { if f := Min(vffdimSC[i][0], vffdimSC[i][1]); !alike(fminSC[i], f) { t.Errorf("Min(%g, %g) = %g, want %g", vffdimSC[i][0], vffdimSC[i][1], f, fminSC[i]) } } for i := 0; i < len(vffdim2SC); i++ { if f := Min(vffdim2SC[i][0], vffdim2SC[i][1]); !alike(fminSC[i], f) { t.Errorf("Min(%g, %g) = %g, want %g", vffdim2SC[i][0], vffdim2SC[i][1], f, fminSC[i]) } } } func TestMod(t *testing.T) { for i := 0; i < len(vf); i++ { if f := Mod(10, vf[i]); !close(fmod[i], f) { t.Errorf("Mod(10, %g) = %g, want %g", vf[i], f, fmod[i]) } } for i := 0; i < len(vffmodSC); i++ { if f := Mod(vffmodSC[i][0], vffmodSC[i][1]); !alike(fmodSC[i], f) { t.Errorf("Mod(%g, %g) = %g, want %g", vffmodSC[i][0], vffmodSC[i][1], f, fmodSC[i]) } } } func TestFrexp(t *testing.T) { for i := 0; i < len(vf); i++ { if f, j := Frexp(vf[i]); !veryclose(frexp[i].f, f) || frexp[i].i != j { t.Errorf("Frexp(%g) = %g, %d, want %g, %d", vf[i], f, j, frexp[i].f, frexp[i].i) } } for i := 0; i < len(vffrexpSC); i++ { if f, j := Frexp(vffrexpSC[i]); !alike(frexpSC[i].f, f) || frexpSC[i].i != j { t.Errorf("Frexp(%g) = %g, %d, want %g, %d", vffrexpSC[i], f, j, frexpSC[i].f, frexpSC[i].i) } } for i := 0; i < len(vffrexpBC); i++ { if f, j := Frexp(vffrexpBC[i]); !alike(frexpBC[i].f, f) || frexpBC[i].i != j { t.Errorf("Frexp(%g) = %g, %d, want %g, %d", vffrexpBC[i], f, j, frexpBC[i].f, frexpBC[i].i) } } } func TestGamma(t *testing.T) { for i := 0; i < len(vf); i++ { if f := Gamma(vf[i]); !thisclose(gamma[i], f, 1e-4) { t.Errorf("Gamma(%g) = %g, want %g", vf[i], f, gamma[i]) } } for i := 0; i < len(vfgammaSC); i++ { if f := Gamma(vfgammaSC[i]); !alike(gammaSC[i], f) { t.Errorf("Gamma(%g) = %g, want %g", vfgammaSC[i], f, gammaSC[i]) } } } func TestHypot(t *testing.T) { for i := 0; i < len(vf); i++ { a := Abs(1e20 * tanh[i] * Sqrt(2)) if f := Hypot(1e20*tanh[i], 1e20*tanh[i]); !veryclose(a, f) { t.Errorf("Hypot(%g, %g) = %g, want %g", 1e20*tanh[i], 1e20*tanh[i], f, a) } } for i := 0; i < len(vfhypotSC); i++ { if f := Hypot(vfhypotSC[i][0], vfhypotSC[i][1]); !alike(hypotSC[i], f) { t.Errorf("Hypot(%g, %g) = %g, want %g", vfhypotSC[i][0], vfhypotSC[i][1], f, hypotSC[i]) } } } func TestIlogb(t *testing.T) { for i := 0; i < len(vf); i++ { a := frexp[i].i - 1 // adjust because fr in the interval [½, 1) if e := Ilogb(vf[i]); a != e { t.Errorf("Ilogb(%g) = %d, want %d", vf[i], e, a) } } for i := 0; i < len(vflogbSC); i++ { if e := Ilogb(vflogbSC[i]); ilogbSC[i] != e { t.Errorf("Ilogb(%g) = %d, want %d", vflogbSC[i], e, ilogbSC[i]) } } for i := 0; i < len(vffrexpBC); i++ { if e := Ilogb(vffrexpBC[i]); int(logbBC[i]) != e { t.Errorf("Ilogb(%g) = %d, want %d", vffrexpBC[i], e, int(logbBC[i])) } } } func TestJ0(t *testing.T) { for i := 0; i < len(vf); i++ { if f := J0(vf[i]); !thisclose(j0[i], f, 4e-5) { t.Errorf("J0(%g) = %g, want %g", vf[i], f, j0[i]) } } for i := 0; i < len(vfj0SC); i++ { if f := J0(vfj0SC[i]); !alike(j0SC[i], f) { t.Errorf("J0(%g) = %g, want %g", vfj0SC[i], f, j0SC[i]) } } } func TestJ1(t *testing.T) { for i := 0; i < len(vf); i++ { if f := J1(vf[i]); !close(j1[i], f) { t.Errorf("J1(%g) = %g, want %g", vf[i], f, j1[i]) } } for i := 0; i < len(vfj0SC); i++ { if f := J1(vfj0SC[i]); !alike(j1SC[i], f) { t.Errorf("J1(%g) = %g, want %g", vfj0SC[i], f, j1SC[i]) } } } func TestJn(t *testing.T) { for i := 0; i < len(vf); i++ { if f := Jn(2, vf[i]); !close(j2[i], f) { t.Errorf("Jn(2, %g) = %g, want %g", vf[i], f, j2[i]) } if f := Jn(-3, vf[i]); !close(jM3[i], f) { t.Errorf("Jn(-3, %g) = %g, want %g", vf[i], f, jM3[i]) } } for i := 0; i < len(vfj0SC); i++ { if f := Jn(2, vfj0SC[i]); !alike(j2SC[i], f) { t.Errorf("Jn(2, %g) = %g, want %g", vfj0SC[i], f, j2SC[i]) } if f := Jn(-3, vfj0SC[i]); !alike(jM3SC[i], f) { t.Errorf("Jn(-3, %g) = %g, want %g", vfj0SC[i], f, jM3SC[i]) } } } func TestLdexp(t *testing.T) { for i := 0; i < len(vf); i++ { if f := Ldexp(frexp[i].f, frexp[i].i); !veryclose(vf[i], f) { t.Errorf("Ldexp(%g, %d) = %g, want %g", frexp[i].f, frexp[i].i, f, vf[i]) } } for i := 0; i < len(vffrexpSC); i++ { if f := Ldexp(frexpSC[i].f, frexpSC[i].i); !alike(vffrexpSC[i], f) { t.Errorf("Ldexp(%g, %d) = %g, want %g", frexpSC[i].f, frexpSC[i].i, f, vffrexpSC[i]) } } for i := 0; i < len(vfldexpSC); i++ { if f := Ldexp(vfldexpSC[i].f, vfldexpSC[i].i); !alike(ldexpSC[i], f) { t.Errorf("Ldexp(%g, %d) = %g, want %g", vfldexpSC[i].f, vfldexpSC[i].i, f, ldexpSC[i]) } } for i := 0; i < len(vffrexpBC); i++ { if f := Ldexp(frexpBC[i].f, frexpBC[i].i); !alike(vffrexpBC[i], f) { t.Errorf("Ldexp(%g, %d) = %g, want %g", frexpBC[i].f, frexpBC[i].i, f, vffrexpBC[i]) } } for i := 0; i < len(vfldexpBC); i++ { if f := Ldexp(vfldexpBC[i].f, vfldexpBC[i].i); !alike(ldexpBC[i], f) { t.Errorf("Ldexp(%g, %d) = %g, want %g", vfldexpBC[i].f, vfldexpBC[i].i, f, ldexpBC[i]) } } } func TestLgamma(t *testing.T) { for i := 0; i < len(vf); i++ { if f, s := Lgamma(vf[i]); !thisclose(lgamma[i].f, f, 1e-4) || lgamma[i].i != s { t.Errorf("Lgamma(%g) = %g, %d, want %g, %d", vf[i], f, s, lgamma[i].f, lgamma[i].i) } } for i := 0; i < len(vflgammaSC); i++ { if f, s := Lgamma(vflgammaSC[i]); !alike(lgammaSC[i].f, f) || lgammaSC[i].i != s { t.Errorf("Lgamma(%g) = %g, %d, want %g, %d", vflgammaSC[i], f, s, lgammaSC[i].f, lgammaSC[i].i) } } } func TestLog(t *testing.T) { for i := 0; i < len(vf); i++ { a := Abs(vf[i]) if f := Log(a); !close(log[i], f) { t.Errorf("Log(%g) = %g, want %g", a, f, log[i]) } } if f := Log(10); f != Ln10 { t.Errorf("Log(%g) = %g, want %g", 10.0, f, Ln10) } for i := 0; i < len(vflogSC); i++ { if f := Log(vflogSC[i]); !alike(logSC[i], f) { t.Errorf("Log(%g) = %g, want %g", vflogSC[i], f, logSC[i]) } } } func TestLogb(t *testing.T) { for i := 0; i < len(vf); i++ { if f := Logb(vf[i]); logb[i] != f { t.Errorf("Logb(%g) = %g, want %g", vf[i], f, logb[i]) } } for i := 0; i < len(vflogbSC); i++ { if f := Logb(vflogbSC[i]); !alike(logbSC[i], f) { t.Errorf("Logb(%g) = %g, want %g", vflogbSC[i], f, logbSC[i]) } } for i := 0; i < len(vffrexpBC); i++ { if f := Logb(vffrexpBC[i]); !alike(logbBC[i], f) { t.Errorf("Logb(%g) = %g, want %g", vffrexpBC[i], f, logbBC[i]) } } } func TestLog10(t *testing.T) { for i := 0; i < len(vf); i++ { a := Abs(vf[i]) if f := Log10(a); !veryclose(log10[i], f) { t.Errorf("Log10(%g) = %g, want %g", a, f, log10[i]) } } if f := Log10(E); f != Log10E { t.Errorf("Log10(%g) = %g, want %g", E, f, Log10E) } for i := 0; i < len(vflogSC); i++ { if f := Log10(vflogSC[i]); !alike(logSC[i], f) { t.Errorf("Log10(%g) = %g, want %g", vflogSC[i], f, logSC[i]) } } } func TestLog1p(t *testing.T) { for i := 0; i < len(vf); i++ { a := vf[i] / 100 if f := Log1p(a); !veryclose(log1p[i], f) { t.Errorf("Log1p(%g) = %g, want %g", a, f, log1p[i]) } } a := float32(9.0) if f := Log1p(a); f != Ln10 { t.Errorf("Log1p(%g) = %g, want %g", a, f, Ln10) } for i := 0; i < len(vflogSC); i++ { if f := Log1p(vflog1pSC[i]); !alike(log1pSC[i], f) { t.Errorf("Log1p(%g) = %g, want %g", vflog1pSC[i], f, log1pSC[i]) } } } func TestLog2(t *testing.T) { for i := 0; i < len(vf); i++ { a := Abs(vf[i]) if f := Log2(a); !veryclose(log2[i], f) { t.Errorf("Log2(%g) = %g, want %g", a, f, log2[i]) } } if f := Log2(E); f != Log2E { t.Errorf("Log2(%g) = %g, want %g", E, f, Log2E) } for i := 0; i < len(vflogSC); i++ { if f := Log2(vflogSC[i]); !alike(logSC[i], f) { t.Errorf("Log2(%g) = %g, want %g", vflogSC[i], f, logSC[i]) } } for i := -149; i <= 127; i++ { f := Ldexp(1, i) l := Log2(f) if l != float32(i) { t.Errorf("Log2(2**%d) = %g, want %d", i, l, i) } } } func TestModf(t *testing.T) { for i := 0; i < len(vf); i++ { if f, g := Modf(vf[i]); !veryclose(modf[i][0], f) || !thisclose(modf[i][1], g, 1e-4) { t.Errorf("Modf(%g) = %g, %g, want %g, %g", vf[i], f, g, modf[i][0], modf[i][1]) } } for i := 0; i < len(vfmodfSC); i++ { if f, g := Modf(vfmodfSC[i]); !alike(modfSC[i][0], f) || !alike(modfSC[i][1], g) { t.Errorf("Modf(%g) = %g, %g, want %g, %g", vfmodfSC[i], f, g, modfSC[i][0], modfSC[i][1]) } } } func TestNextafter(t *testing.T) { for i := 0; i < len(vf); i++ { vfi := vf[i] if f := Nextafter(vfi, 10); nextafter32[i] != f { t.Errorf("Nextafter32(%g, %g) = %g want %g", vfi, 10.0, f, nextafter32[i]) } } for i := 0; i < len(vfnextafter32SC); i++ { if f := Nextafter(vfnextafter32SC[i][0], vfnextafter32SC[i][1]); !alike(nextafter32SC[i], f) { t.Errorf("Nextafter32(%g, %g) = %g want %g", vfnextafter32SC[i][0], vfnextafter32SC[i][1], f, nextafter32SC[i]) } } } func TestPow(t *testing.T) { for i := 0; i < len(vf); i++ { if f := Pow(10, vf[i]); !close(pow[i], f) { t.Errorf("Pow(10, %g) = %g, want %g", vf[i], f, pow[i]) } } for i := 0; i < len(vfpowSC); i++ { if f := Pow(vfpowSC[i][0], vfpowSC[i][1]); !alike(powSC[i], f) { t.Errorf("Pow(%g, %g) = %g, want %g", vfpowSC[i][0], vfpowSC[i][1], f, powSC[i]) } } } func TestPow10(t *testing.T) { for i := 0; i < len(vfpow10SC); i++ { if f := Pow10(vfpow10SC[i]); !alike(pow10SC[i], f) { t.Errorf("Pow10(%d) = %g, want %g", vfpow10SC[i], f, pow10SC[i]) } } } func TestRemainder(t *testing.T) { for i := 0; i < len(vf); i++ { if f := Remainder(10, vf[i]); !thisclose(remainder[i], f, 1e-4) { t.Errorf("Remainder(10, %g) = %g, want %g", vf[i], f, remainder[i]) } } for i := 0; i < len(vffmodSC); i++ { if f := Remainder(vffmodSC[i][0], vffmodSC[i][1]); !alike(fmodSC[i], f) { t.Errorf("Remainder(%g, %g) = %g, want %g", vffmodSC[i][0], vffmodSC[i][1], f, fmodSC[i]) } } } func TestSignbit(t *testing.T) { for i := 0; i < len(vf); i++ { if f := Signbit(vf[i]); signbit[i] != f { t.Errorf("Signbit(%g) = %t, want %t", vf[i], f, signbit[i]) } } for i := 0; i < len(vfsignbitSC); i++ { if f := Signbit(vfsignbitSC[i]); signbitSC[i] != f { t.Errorf("Signbit(%g) = %t, want %t", vfsignbitSC[i], f, signbitSC[i]) } } } func TestSin(t *testing.T) { for i := 0; i < len(vf); i++ { if f := Sin(vf[i]); !close(sin[i], f) { t.Errorf("Sin(%g) = %g, want %g", vf[i], f, sin[i]) } } for i := 0; i < len(vfsinSC); i++ { if f := Sin(vfsinSC[i]); !alike(sinSC[i], f) { t.Errorf("Sin(%g) = %g, want %g", vfsinSC[i], f, sinSC[i]) } } } func TestSincos(t *testing.T) { for i := 0; i < len(vf); i++ { if s, c := Sincos(vf[i]); !close(sin[i], s) || !close(cos[i], c) { t.Errorf("Sincos(%g) = %g, %g want %g, %g", vf[i], s, c, sin[i], cos[i]) } } } func TestSinh(t *testing.T) { for i := 0; i < len(vf); i++ { if f := Sinh(vf[i]); !close(sinh[i], f) { t.Errorf("Sinh(%g) = %g, want %g", vf[i], f, sinh[i]) } } for i := 0; i < len(vfsinhSC); i++ { if f := Sinh(vfsinhSC[i]); !alike(sinhSC[i], f) { t.Errorf("Sinh(%g) = %g, want %g", vfsinhSC[i], f, sinhSC[i]) } } } func TestSqrt(t *testing.T) { const tol = 1e-7 for i := 0; i < len(vf); i++ { a := Abs(vf[i]) if f := SqrtGo(a); !thisclose(f, sqrt[i], tol) { t.Errorf("SqrtGo(%g) = %g, want %g", a, f, sqrt[i]) } if f := Sqrt(a); !thisclose(f, sqrt[i], tol) { t.Errorf("Sqrt(%g) = %g, want %g", a, f, sqrt[i]) } } for i := 0; i < len(vfsqrtSC); i++ { if f := SqrtGo(vfsqrtSC[i]); !alike(sqrtSC[i], f) { t.Errorf("SqrtGo(%g) = %g, want %g", vfsqrtSC[i], f, sqrtSC[i]) } if f := Sqrt(vfsqrtSC[i]); !alike(sqrtSC[i], f) { t.Errorf("Sqrt(%g) = %g, want %g", vfsqrtSC[i], f, sqrtSC[i]) } } } func TestTan(t *testing.T) { for i := 0; i < len(vf); i++ { if f := Tan(vf[i]); !close(tan[i], f) { t.Errorf("Tan(%g) = %g, want %g", vf[i], f, tan[i]) } } // same special cases as Sin for i := 0; i < len(vfsinSC); i++ { if f := Tan(vfsinSC[i]); !alike(sinSC[i], f) { t.Errorf("Tan(%g) = %g, want %g", vfsinSC[i], f, sinSC[i]) } } } func TestTanh(t *testing.T) { for i := 0; i < len(vf); i++ { if f := Tanh(vf[i]); !veryclose(tanh[i], f) { t.Errorf("Tanh(%g) = %g, want %g", vf[i], f, tanh[i]) } } for i := 0; i < len(vftanhSC); i++ { if f := Tanh(vftanhSC[i]); !alike(tanhSC[i], f) { t.Errorf("Tanh(%g) = %g, want %g", vftanhSC[i], f, tanhSC[i]) } } } func TestTrunc(t *testing.T) { for i := 0; i < len(vf); i++ { if f := Trunc(vf[i]); trunc[i] != f { t.Errorf("Trunc(%g) = %g, want %g", vf[i], f, trunc[i]) } } for i := 0; i < len(vfceilSC); i++ { if f := Trunc(vfceilSC[i]); !alike(ceilSC[i], f) { t.Errorf("Trunc(%g) = %g, want %g", vfceilSC[i], f, ceilSC[i]) } } } func TestY0(t *testing.T) { for i := 0; i < len(vf); i++ { a := Abs(vf[i]) if f := Y0(a); !close(y0[i], f) { t.Errorf("Y0(%g) = %g, want %g", a, f, y0[i]) } } for i := 0; i < len(vfy0SC); i++ { if f := Y0(vfy0SC[i]); !alike(y0SC[i], f) { t.Errorf("Y0(%g) = %g, want %g", vfy0SC[i], f, y0SC[i]) } } } func TestY1(t *testing.T) { for i := 0; i < len(vf); i++ { a := Abs(vf[i]) if f := Y1(a); !close(y1[i], f) { t.Errorf("Y1(%g) = %g, want %g", a, f, y1[i]) } } for i := 0; i < len(vfy0SC); i++ { if f := Y1(vfy0SC[i]); !alike(y1SC[i], f) { t.Errorf("Y1(%g) = %g, want %g", vfy0SC[i], f, y1SC[i]) } } } func TestYn(t *testing.T) { for i := 0; i < len(vf); i++ { a := Abs(vf[i]) if f := Yn(2, a); !close(y2[i], f) { t.Errorf("Yn(2, %g) = %g, want %g", a, f, y2[i]) } if f := Yn(-3, a); !close(yM3[i], f) { t.Errorf("Yn(-3, %g) = %g, want %g", a, f, yM3[i]) } } for i := 0; i < len(vfy0SC); i++ { if f := Yn(2, vfy0SC[i]); !alike(y2SC[i], f) { t.Errorf("Yn(2, %g) = %g, want %g", vfy0SC[i], f, y2SC[i]) } if f := Yn(-3, vfy0SC[i]); !alike(yM3SC[i], f) { t.Errorf("Yn(-3, %g) = %g, want %g", vfy0SC[i], f, yM3SC[i]) } } } // Check that math functions of high angle values // return accurate results. [Since (vf[i] + large) - large != vf[i], // testing for Trig(vf[i] + large) == Trig(vf[i]), where large is // a multiple of 2*Pi, is misleading.] func TestLargeCos(t *testing.T) { large := float32(100000 * Pi) for i := 0; i < len(vf); i++ { f1 := cosLarge[i] f2 := Cos(vf[i] + large) if !nearby(f1, f2) { t.Errorf("Cos(%g) = %g, want %g", vf[i]+large, f2, f1) } } } func TestLargeSin(t *testing.T) { large := float32(100000 * Pi) for i := 0; i < len(vf); i++ { f1 := sinLarge[i] f2 := Sin(vf[i] + large) if !nearby(f1, f2) { t.Errorf("Sin(%g) = %g, want %g", vf[i]+large, f2, f1) } } } func TestLargeSincos(t *testing.T) { large := float32(100000 * Pi) for i := 0; i < len(vf); i++ { f1, g1 := sinLarge[i], cosLarge[i] f2, g2 := Sincos(vf[i] + large) if !nearby(f1, f2) || !nearby(g1, g2) { t.Errorf("Sincos(%g) = %g, %g, want %g, %g", vf[i]+large, f2, g2, f1, g1) } } } func TestLargeTan(t *testing.T) { large := float32(100000 * Pi) for i := 0; i < len(vf); i++ { f1 := tanLarge[i] f2 := Tan(vf[i] + large) if !nearby(f1, f2) { t.Errorf("Tan(%g) = %g, want %g", vf[i]+large, f2, f1) } } } // Check that math constants are accepted by compiler // and have right value (assumes strconv.ParseFloat works). // https://golang.org/issue/201 type floatTest struct { val interface{} name string str string } var floatTests = []floatTest{ {float32(MaxFloat32), "MaxFloat32", "3.4028235e+38"}, {float32(SmallestNonzeroFloat32), "SmallestNonzeroFloat32", "1e-45"}, } func TestFloatMinMax(t *testing.T) { for _, tt := range floatTests { s := fmt.Sprint(tt.val) if s != tt.str { t.Errorf("Sprint(%v) = %s, want %s", tt.name, s, tt.str) } } } // Benchmarks func BenchmarkAcos(b *testing.B) { for i := 0; i < b.N; i++ { Acos(.5) } } func BenchmarkAcosh(b *testing.B) { for i := 0; i < b.N; i++ { Acosh(1.5) } } func BenchmarkAsin(b *testing.B) { for i := 0; i < b.N; i++ { Asin(.5) } } func BenchmarkAsinh(b *testing.B) { for i := 0; i < b.N; i++ { Asinh(.5) } } func BenchmarkAtan(b *testing.B) { for i := 0; i < b.N; i++ { Atan(.5) } } func BenchmarkAtanh(b *testing.B) { for i := 0; i < b.N; i++ { Atanh(.5) } } func BenchmarkAtan2(b *testing.B) { for i := 0; i < b.N; i++ { Atan2(.5, 1) } } func BenchmarkCbrt(b *testing.B) { for i := 0; i < b.N; i++ { Cbrt(10) } } func BenchmarkCeil(b *testing.B) { for i := 0; i < b.N; i++ { Ceil(.5) } } func BenchmarkCopysign(b *testing.B) { for i := 0; i < b.N; i++ { Copysign(.5, -1) } } func BenchmarkCos(b *testing.B) { for i := 0; i < b.N; i++ { Cos(.5) } } func BenchmarkCosh(b *testing.B) { for i := 0; i < b.N; i++ { Cosh(2.5) } } func BenchmarkErf(b *testing.B) { for i := 0; i < b.N; i++ { Erf(.5) } } func BenchmarkErfc(b *testing.B) { for i := 0; i < b.N; i++ { Erfc(.5) } } func BenchmarkExp(b *testing.B) { for i := 0; i < b.N; i++ { Exp(.5) } } // func BenchmarkExpGo(b *testing.B) { // for i := 0; i < b.N; i++ { // ExpGo(.5) // } // } func BenchmarkExpm1(b *testing.B) { for i := 0; i < b.N; i++ { Expm1(.5) } } func BenchmarkExp2(b *testing.B) { for i := 0; i < b.N; i++ { Exp2(.5) } } // func BenchmarkExp2Go(b *testing.B) { // for i := 0; i < b.N; i++ { // Exp2Go(.5) // } // } func BenchmarkAbs(b *testing.B) { for i := 0; i < b.N; i++ { Abs(.5) } } func BenchmarkDim(b *testing.B) { for i := 0; i < b.N; i++ { Dim(10, 3) } } func BenchmarkFloor(b *testing.B) { for i := 0; i < b.N; i++ { Floor(.5) } } func BenchmarkMax(b *testing.B) { for i := 0; i < b.N; i++ { Max(10, 3) } } func BenchmarkMin(b *testing.B) { for i := 0; i < b.N; i++ { Min(10, 3) } } func BenchmarkMod(b *testing.B) { for i := 0; i < b.N; i++ { Mod(10, 3) } } func BenchmarkFrexp(b *testing.B) { for i := 0; i < b.N; i++ { Frexp(8) } } func BenchmarkGamma(b *testing.B) { for i := 0; i < b.N; i++ { Gamma(2.5) } } func BenchmarkHypot(b *testing.B) { for i := 0; i < b.N; i++ { Hypot(3, 4) } } func BenchmarkIlogb(b *testing.B) { for i := 0; i < b.N; i++ { Ilogb(.5) } } func BenchmarkJ0(b *testing.B) { for i := 0; i < b.N; i++ { J0(2.5) } } func BenchmarkJ1(b *testing.B) { for i := 0; i < b.N; i++ { J1(2.5) } } func BenchmarkJn(b *testing.B) { for i := 0; i < b.N; i++ { Jn(2, 2.5) } } func BenchmarkLdexp(b *testing.B) { for i := 0; i < b.N; i++ { Ldexp(.5, 2) } } func BenchmarkLgamma(b *testing.B) { for i := 0; i < b.N; i++ { Lgamma(2.5) } } func BenchmarkLog(b *testing.B) { for i := 0; i < b.N; i++ { Log(.5) } } func BenchmarkLogb(b *testing.B) { for i := 0; i < b.N; i++ { Logb(.5) } } func BenchmarkLog1p(b *testing.B) { for i := 0; i < b.N; i++ { Log1p(.5) } } func BenchmarkLog10(b *testing.B) { for i := 0; i < b.N; i++ { Log10(.5) } } func BenchmarkLog2(b *testing.B) { for i := 0; i < b.N; i++ { Log2(.5) } } func BenchmarkModf(b *testing.B) { for i := 0; i < b.N; i++ { Modf(1.5) } } func BenchmarkNextafter(b *testing.B) { for i := 0; i < b.N; i++ { Nextafter(.5, 1) } } func BenchmarkPowInt(b *testing.B) { for i := 0; i < b.N; i++ { Pow(2, 2) } } func BenchmarkPowFrac(b *testing.B) { for i := 0; i < b.N; i++ { Pow(2.5, 1.5) } } func BenchmarkPow10Pos(b *testing.B) { for i := 0; i < b.N; i++ { Pow10(300) } } func BenchmarkPow10Neg(b *testing.B) { for i := 0; i < b.N; i++ { Pow10(-300) } } func BenchmarkRemainder(b *testing.B) { for i := 0; i < b.N; i++ { Remainder(10, 3) } } func BenchmarkSignbit(b *testing.B) { for i := 0; i < b.N; i++ { Signbit(2.5) } } func BenchmarkSin(b *testing.B) { for i := 0; i < b.N; i++ { Sin(.5) } } func BenchmarkSincos(b *testing.B) { for i := 0; i < b.N; i++ { Sincos(.5) } } func BenchmarkSinh(b *testing.B) { for i := 0; i < b.N; i++ { Sinh(2.5) } } var Global float32 func BenchmarkSqrt(b *testing.B) { var x, y float32 x, y = 0.0, 10.0 for i := 0; i < b.N; i++ { x += Sqrt(y) } Global = x } func BenchmarkSqrtIndirect(b *testing.B) { var x, y float32 x, y = 0.0, 10.0 f := Sqrt for i := 0; i < b.N; i++ { x += f(y) } Global = x } // func BenchmarkSqrtGo(b *testing.B) { // var x, y float32 // x, y = 0.0, 10.0 // for i := 0; i < b.N; i++ { // x += SqrtGo(y) // } // Global = x // } func isPrime(i int) bool { // Yes, this is a dumb way to write this code, // but calling Sqrt repeatedly in this way demonstrates // the benefit of using a direct SQRT instruction on systems // that have one, whereas the obvious loop seems not to // demonstrate such a benefit. for j := 2; float32(j) <= Sqrt(float32(i)); j++ { if i%j == 0 { return false } } return true } func BenchmarkSqrtPrime(b *testing.B) { any := false for i := 0; i < b.N; i++ { if isPrime(100003) { any = true } } if any { Global = 1 } } func BenchmarkTan(b *testing.B) { for i := 0; i < b.N; i++ { Tan(.5) } } func BenchmarkTanh(b *testing.B) { for i := 0; i < b.N; i++ { Tanh(2.5) } } func BenchmarkTrunc(b *testing.B) { for i := 0; i < b.N; i++ { Trunc(.5) } } func BenchmarkY0(b *testing.B) { for i := 0; i < b.N; i++ { Y0(2.5) } } func BenchmarkY1(b *testing.B) { for i := 0; i < b.N; i++ { Y1(2.5) } } func BenchmarkYn(b *testing.B) { for i := 0; i < b.N; i++ { Yn(2, 2.5) } } math32-1.11.1/asin.go000066400000000000000000000005241467305561300141650ustar00rootroot00000000000000package math32 func Asin(x float32) float32 { if x == 0 { return x // special case } sign := false if x < 0 { x = -x sign = true } if x > 1 { return NaN() // special case } temp := Sqrt(1 - x*x) if x > 0.7 { temp = Pi/2 - satan(temp/x) } else { temp = satan(x / temp) } if sign { temp = -temp } return temp } math32-1.11.1/asinh.go000066400000000000000000000032561467305561300143420ustar00rootroot00000000000000package math32 // The original C code, the long comment, and the constants // below are from FreeBSD's /usr/src/lib/msun/src/s_asinh.c // and came with this notice. The go code is a simplified // version of the original C. // // ==================================================== // Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. // // Developed at SunPro, a Sun Microsystems, Inc. business. // Permission to use, copy, modify, and distribute this // software is freely granted, provided that this notice // is preserved. // ==================================================== // // // asinh(x) // Method : // Based on // asinh(x) = sign(x) * log [ |x| + sqrt(x*x+1) ] // we have // asinh(x) := x if 1+x*x=1, // := sign(x)*(log(x)+ln2)) for large |x|, else // := sign(x)*log(2|x|+1/(|x|+sqrt(x*x+1))) if|x|>2, else // := sign(x)*log1p(|x| + x**2/(1 + sqrt(1+x**2))) // // Asinh returns the inverse hyperbolic sine of x. // // Special cases are: // Asinh(±0) = ±0 // Asinh(±Inf) = ±Inf // Asinh(NaN) = NaN func Asinh(x float32) float32 { const ( Ln2 = 6.93147180559945286227e-01 // 0x3FE62E42FEFA39EF NearZero = 1.0 / (1 << 28) // 2**-28 Large = 1 << 28 // 2**28 ) // special cases if IsNaN(x) || IsInf(x, 0) { return x } sign := false if x < 0 { x = -x sign = true } var temp float32 switch { case x > Large: temp = Log(x) + Ln2 // |x| > 2**28 case x > 2: temp = Log(2*x + 1/(Sqrt(x*x+1)+x)) // 2**28 > |x| > 2.0 case x < NearZero: temp = x // |x| < 2**-28 default: temp = Log1p(x + x*x/(1+Sqrt(1+x*x))) // 2.0 > |x| > 2**-28 } if sign { temp = -temp } return temp } math32-1.11.1/atan.go000066400000000000000000000052241467305561300141600ustar00rootroot00000000000000package math32 func Atan(x float32) float32 { if x == 0 { return x } if x > 0 { return satan(x) } return -satan(-x) } // The original C code, the long comment, and the constants below were // from http://netlib.sandia.gov/cephes/cmath/atan.c, available from // http://www.netlib.org/cephes/cmath.tgz. // The go code is a version of the original C. // // atan.c // Inverse circular tangent (arctangent) // // SYNOPSIS: // double x, y, atan(); // y = atan( x ); // // DESCRIPTION: // Returns radian angle between -pi/2 and +pi/2 whose tangent is x. // // Range reduction is from three intervals into the interval from zero to 0.66. // The approximant uses a rational function of degree 4/5 of the form // x + x**3 P(x)/Q(x). // // ACCURACY: // Relative error: // arithmetic domain # trials peak rms // DEC -10, 10 50000 2.4e-17 8.3e-18 // IEEE -10, 10 10^6 1.8e-16 5.0e-17 // // Cephes Math Library Release 2.8: June, 2000 // Copyright 1984, 1987, 1989, 1992, 2000 by Stephen L. Moshier // // The readme file at http://netlib.sandia.gov/cephes/ says: // Some software in this archive may be from the book _Methods and // Programs for Mathematical Functions_ (Prentice-Hall or Simon & Schuster // International, 1989) or from the Cephes Mathematical Library, a // commercial product. In either event, it is copyrighted by the author. // What you see here may be used freely but it comes with no support or // guarantee. // // The two known misprints in the book are repaired here in the // source listings for the gamma function and the incomplete beta // integral. // // Stephen L. Moshier // moshier@na-net.ornl.gov // xatan evaluates a series valid in the range [0, 0.66]. func xatan(x float32) float32 { const ( P0 = -8.750608600031904122785e-01 P1 = -1.615753718733365076637e+01 P2 = -7.500855792314704667340e+01 P3 = -1.228866684490136173410e+02 P4 = -6.485021904942025371773e+01 Q0 = +2.485846490142306297962e+01 Q1 = +1.650270098316988542046e+02 Q2 = +4.328810604912902668951e+02 Q3 = +4.853903996359136964868e+02 Q4 = +1.945506571482613964425e+02 ) z := x * x z = z * ((((P0*z+P1)*z+P2)*z+P3)*z + P4) / (((((z+Q0)*z+Q1)*z+Q2)*z+Q3)*z + Q4) z = x*z + x return z } // satan reduces its argument (known to be positive) // to the range [0, 0.66] and calls xatan. func satan(x float32) float32 { const ( Morebits float32 = 6.123233995736765886130e-17 // pi/2 = PIO2 + Morebits Tan3pio8 float32 = 2.41421356237309504880 // tan(3*pi/8) ) if x <= 0.66 { return xatan(x) } if x > Tan3pio8 { return Pi/2 - xatan(1/x) + Morebits } return Pi/4 + xatan((x-1)/(x+1)) + 0.5*Morebits } math32-1.11.1/atan2.go000066400000000000000000000024251467305561300142420ustar00rootroot00000000000000package math32 // Atan2 returns the arc tangent of y/x, using the signs of the two to determine the quadrant of the return value. // Special cases are (in order): // Atan2(y, NaN) = NaN // Atan2(NaN, x) = NaN // Atan2(+0, x>=0) = +0 // Atan2(-0, x>=0) = -0 // Atan2(+0, x<=-0) = +Pi // Atan2(-0, x<=-0) = -Pi // Atan2(y>0, 0) = +Pi/2 // Atan2(y<0, 0) = -Pi/2 // Atan2(+Inf, +Inf) = +Pi/4 // Atan2(-Inf, +Inf) = -Pi/4 // Atan2(+Inf, -Inf) = 3Pi/4 // Atan2(-Inf, -Inf) = -3Pi/4 // Atan2(y, +Inf) = 0 // Atan2(y>0, -Inf) = +Pi // Atan2(y<0, -Inf) = -Pi // Atan2(+Inf, x) = +Pi/2 // Atan2(-Inf, x) = -Pi/2 func Atan2(y, x float32) float32 { // special cases switch { case IsNaN(y) || IsNaN(x): return NaN() case y == 0: if x >= 0 && !Signbit(x) { return Copysign(0, y) } return Copysign(Pi, y) case x == 0: return Copysign(Pi/2, y) case IsInf(x, 0): if IsInf(x, 1) { switch { case IsInf(y, 0): return Copysign(Pi/4, y) default: return Copysign(0, y) } } switch { case IsInf(y, 0): return Copysign(3*Pi/4, y) default: return Copysign(Pi, y) } case IsInf(y, 0): return Copysign(Pi/2, y) } // Call atan and determine the quadrant. q := Atan(y / x) if x < 0 { if q <= 0 { return q + Pi } return q - Pi } return q } math32-1.11.1/atanh.go000066400000000000000000000033701467305561300143300ustar00rootroot00000000000000package math32 // The original C code, the long comment, and the constants // below are from FreeBSD's /usr/src/lib/msun/src/e_atanh.c // and came with this notice. The go code is a simplified // version of the original C. // // ==================================================== // Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. // // Developed at SunPro, a Sun Microsystems, Inc. business. // Permission to use, copy, modify, and distribute this // software is freely granted, provided that this notice // is preserved. // ==================================================== // // // __ieee754_atanh(x) // Method : // 1. Reduce x to positive by atanh(-x) = -atanh(x) // 2. For x>=0.5 // 1 2x x // atanh(x) = --- * log(1 + -------) = 0.5 * log1p(2 * --------) // 2 1 - x 1 - x // // For x<0.5 // atanh(x) = 0.5*log1p(2x+2x*x/(1-x)) // // Special cases: // atanh(x) is NaN if |x| > 1 with signal; // atanh(NaN) is that NaN with no signal; // atanh(+-1) is +-INF with signal. // // Atanh returns the inverse hyperbolic tangent of x. // // Special cases are: // Atanh(1) = +Inf // Atanh(±0) = ±0 // Atanh(-1) = -Inf // Atanh(x) = NaN if x < -1 or x > 1 // Atanh(NaN) = NaN func Atanh(x float32) float32 { const NearZero = 1.0 / (1 << 28) // 2**-28 // special cases switch { case x < -1 || x > 1 || IsNaN(x): return NaN() case x == 1: return Inf(1) case x == -1: return Inf(-1) } sign := false if x < 0 { x = -x sign = true } var temp float32 switch { case x < NearZero: temp = x case x < 0.5: temp = x + x temp = 0.5 * Log1p(temp+temp*x/(1-x)) default: temp = 0.5 * Log1p((x+x)/(1-x)) } if sign { temp = -temp } return temp } math32-1.11.1/bits.go000066400000000000000000000033061467305561300141750ustar00rootroot00000000000000package math32 const ( uvnan = 0x7FE00000 uvinf = 0x7F800000 uvone = 0x3f800000 uvneginf = 0xFF800000 mask = 0xFF shift = 32 - 8 - 1 bias = 127 signMask = 1 << 31 fracMask = 1<= 0, negative infinity if sign < 0. func Inf(sign int) float32 { var v uint32 if sign >= 0 { v = uvinf } else { v = uvneginf } return Float32frombits(v) } // NaN returns an IEEE 754 ``not-a-number'' value. func NaN() float32 { return Float32frombits(uvnan) } // IsNaN reports whether f is an IEEE 754 ``not-a-number'' value. func IsNaN(f float32) (is bool) { // IEEE 754 says that only NaNs satisfy f != f. // To avoid the floating-point hardware, could use: // x := Float32bits(f) // return uint32(x>>shift)&mask == mask && x != uvinf && x != uvneginf return f != f } // IsInf reports whether f is an infinity, according to sign. // If sign > 0, IsInf reports whether f is positive infinity. // If sign < 0, IsInf reports whether f is negative infinity. // If sign == 0, IsInf reports whether f is either infinity. func IsInf(f float32, sign int) bool { // Test for infinity by comparing against maximum float. // To avoid the floating-point hardware, could use: // x := Float32bits(f) // return sign >= 0 && x == uvinf || sign <= 0 && x == uvneginf return sign >= 0 && f > MaxFloat32 || sign <= 0 && f < -MaxFloat32 } // normalize returns a normal number y and exponent exp // satisfying x == y × 2**exp. It assumes x is finite and non-zero. func normalize(x float32) (y float32, exp int) { const SmallestNormal = 1.1754943508222875079687365e-38 // 2**-(127 - 1) if Abs(x) < SmallestNormal { return x * (1 << shift), -shift } return x, 0 } math32-1.11.1/cbrt.go000066400000000000000000000001471467305561300141660ustar00rootroot00000000000000package math32 import "math" func Cbrt(x float32) float32 { return float32(math.Cbrt(float64(x))) } math32-1.11.1/const.go000066400000000000000000000034131467305561300143610ustar00rootroot00000000000000package math32 // Mathematical constants. const ( E = float32(2.71828182845904523536028747135266249775724709369995957496696763) // http://oeis.org/A001113 Pi = float32(3.14159265358979323846264338327950288419716939937510582097494459) // http://oeis.org/A000796 Phi = float32(1.61803398874989484820458683436563811772030917980576286213544862) // http://oeis.org/A001622 Sqrt2 = float32(1.41421356237309504880168872420969807856967187537694807317667974) // http://oeis.org/A002193 SqrtE = float32(1.64872127070012814684865078781416357165377610071014801157507931) // http://oeis.org/A019774 SqrtPi = float32(1.77245385090551602729816748334114518279754945612238712821380779) // http://oeis.org/A002161 SqrtPhi = float32(1.27201964951406896425242246173749149171560804184009624861664038) // http://oeis.org/A139339 Ln2 = float32(0.693147180559945309417232121458176568075500134360255254120680009) // http://oeis.org/A002162 Log2E = float32(1 / Ln2) Ln10 = float32(2.30258509299404568401799145468436420760110148862877297603332790) // http://oeis.org/A002392 Log10E = float32(1 / Ln10) ) // Floating-point limit values. // Max is the largest finite value representable by the type. // SmallestNonzero is the smallest positive, non-zero value representable by the type. const ( MaxFloat32 = 3.40282346638528859811704183484516925440e+38 // 2**127 * (2**24 - 1) / 2**23 SmallestNonzeroFloat32 = 1.401298464324817070923729583289916131280e-45 // 1 / 2**(127 - 1 + 23) ) // Integer limit values. const ( MaxInt8 = 1<<7 - 1 MinInt8 = -1 << 7 MaxInt16 = 1<<15 - 1 MinInt16 = -1 << 15 MaxInt32 = 1<<31 - 1 MinInt32 = -1 << 31 MaxInt64 = 1<<63 - 1 MinInt64 = -1 << 63 MaxUint8 = 1<<8 - 1 MaxUint16 = 1<<16 - 1 MaxUint32 = 1<<32 - 1 MaxUint64 = 1<<64 - 1 ) math32-1.11.1/copysign.go000066400000000000000000000002601467305561300150630ustar00rootroot00000000000000package math32 import "math" func Copysign(x, y float32) float32 { const sign = 1 << 31 return math.Float32frombits(math.Float32bits(x)&^sign | math.Float32bits(y)&sign) } math32-1.11.1/cosh.go000066400000000000000000000002131467305561300141620ustar00rootroot00000000000000package math32 func Cosh(x float32) float32 { x = Abs(x) if x > 21 { return Exp(x) * 0.5 } ex := Exp(x) return (ex + 1/ex) * 0.5 } math32-1.11.1/dim.go000066400000000000000000000024101467305561300140000ustar00rootroot00000000000000package math32 // Dim returns the maximum of x-y or 0. // // Special cases are: // // Dim(+Inf, +Inf) = NaN // Dim(-Inf, -Inf) = NaN // Dim(x, NaN) = Dim(NaN, x) = NaN func Dim(x, y float32) float32 { return dim(x, y) } func dim(x, y float32) float32 { return max(x-y, 0) } // Max returns the larger of x or y. // // Special cases are: // // Max(x, +Inf) = Max(+Inf, x) = +Inf // Max(x, NaN) = Max(NaN, x) = NaN // Max(+0, ±0) = Max(±0, +0) = +0 // Max(-0, -0) = -0 func Max(x, y float32) float32 { return max(x, y) } func max(x, y float32) float32 { // special cases switch { case IsInf(x, 1) || IsInf(y, 1): return Inf(1) case IsNaN(x) || IsNaN(y): return NaN() case x == 0 && x == y: if Signbit(x) { return y } return x } if x > y { return x } return y } // Min returns the smaller of x or y. // // Special cases are: // // Min(x, -Inf) = Min(-Inf, x) = -Inf // Min(x, NaN) = Min(NaN, x) = NaN // Min(-0, ±0) = Min(±0, -0) = -0 func Min(x, y float32) float32 { return min(x, y) } func min(x, y float32) float32 { // special cases switch { case IsInf(x, -1) || IsInf(y, -1): return Inf(-1) case IsNaN(x) || IsNaN(y): return NaN() case x == 0 && x == y: if Signbit(x) { return x } return y } if x < y { return x } return y } math32-1.11.1/doc.go000066400000000000000000000007731467305561300140060ustar00rootroot00000000000000/* Package math32 provides basic constants and mathematical functions for float32 types. At its core, it's mostly just a wrapper in form of float32(math.XXX). This applies to the following functions: Acos Acosh Asin Asinh Atan Atan2 Atanh Cbrt Cos Cosh Erfc Gamma J0 J1 Jn Log10 Log1p Log2 Logb Pow10 Sin Sinh Tan Y0 Y1 Everything else is a float32 implementation. Implementation schedule is sporadic an uncertain. But eventually all functions will be replaced */ package math32 math32-1.11.1/erf.go000066400000000000000000000001451467305561300140060ustar00rootroot00000000000000package math32 import "math" func Erf(x float32) float32 { return float32(math.Erf(float64(x))) } math32-1.11.1/erfc.go000066400000000000000000000001471467305561300141530ustar00rootroot00000000000000package math32 import "math" func Erfc(x float32) float32 { return float32(math.Erfc(float64(x))) } math32-1.11.1/exp.go000066400000000000000000000050461467305561300140330ustar00rootroot00000000000000package math32 func Exp(x float32) float32 { if haveArchExp { return archExp(x) } return exp(x) } func exp(x float32) float32 { const ( Ln2Hi = float32(6.9313812256e-01) Ln2Lo = float32(9.0580006145e-06) Log2e = float32(1.4426950216e+00) Overflow = 7.09782712893383973096e+02 Underflow = -7.45133219101941108420e+02 NearZero = 1.0 / (1 << 28) // 2**-28 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. LogMin = 0x42aeac50 // The bitmask of |log(REAL_FLT_MIN)|, rounding down ) // hx := Float32bits(x) & uint32(0x7fffffff) // special cases switch { case IsNaN(x) || IsInf(x, 1): return x case IsInf(x, -1): return 0 case x > Overflow: return Inf(1) case x < Underflow: // case hx > LogMax: // return Inf(1) // case x < 0 && hx > LogMin: return 0 case -NearZero < x && x < NearZero: return 1 + x } // reduce; computed as r = hi - lo for extra precision. var k int switch { case x < 0: k = int(Log2e*x - 0.5) case x > 0: k = int(Log2e*x + 0.5) } hi := x - float32(k)*Ln2Hi lo := float32(k) * Ln2Lo // compute return expmulti(hi, lo, k) } // Exp2 returns 2**x, the base-2 exponential of x. // // Special cases are the same as Exp. func Exp2(x float32) float32 { if haveArchExp2 { return archExp2(x) } return exp2(x) } func exp2(x float32) float32 { const ( Ln2Hi = 6.9313812256e-01 Ln2Lo = 9.0580006145e-06 Overflow = 1.0239999999999999e+03 Underflow = -1.0740e+03 ) // special cases switch { case IsNaN(x) || IsInf(x, 1): return x case IsInf(x, -1): return 0 case x > Overflow: return Inf(1) case x < Underflow: return 0 } // argument reduction; x = r×lg(e) + k with |r| ≤ ln(2)/2. // computed as r = hi - lo for extra precision. var k int switch { case x > 0: k = int(x + 0.5) case x < 0: k = int(x - 0.5) } t := x - float32(k) hi := t * Ln2Hi lo := -t * Ln2Lo // compute return expmulti(hi, lo, k) } // exp1 returns e**r × 2**k where r = hi - lo and |r| ≤ ln(2)/2. func expmulti(hi, lo float32, k int) float32 { const ( P1 = float32(1.6666667163e-01) /* 0x3e2aaaab */ P2 = float32(-2.7777778450e-03) /* 0xbb360b61 */ P3 = float32(6.6137559770e-05) /* 0x388ab355 */ P4 = float32(-1.6533901999e-06) /* 0xb5ddea0e */ P5 = float32(4.1381369442e-08) /* 0x3331bb4c */ ) r := hi - lo t := r * r c := r - t*(P1+t*(P2+t*(P3+t*(P4+t*P5)))) y := 1 - ((lo - (r*c)/(2-c)) - hi) // TODO(rsc): make sure Ldexp can handle boundary k return Ldexp(y, k) } math32-1.11.1/exp2_asm.go000066400000000000000000000005761467305561300147600ustar00rootroot00000000000000// Copyright 2021 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. //go:build !noasm && !tinygo && (amd64 || 386 || arm || ppc64le || wasm) // +build !noasm // +build !tinygo // +build amd64 386 arm ppc64le wasm package math32 const haveArchExp2 = true func archExp2(x float32) float32 math32-1.11.1/exp2_noasm.go000066400000000000000000000006131467305561300153050ustar00rootroot00000000000000// Copyright 2021 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. //go:build noasm || tinygo || !(amd64 || 386 || arm || ppc64le || wasm) // +build noasm tinygo !amd64,!386,!arm,!ppc64le,!wasm package math32 const haveArchExp2 = false func archExp2(x float32) float32 { panic("not implemented") } math32-1.11.1/exp_amd64.s000066400000000000000000000055551467305561300146700ustar00rootroot00000000000000//go:build !tinygo && !noasm // Copyright 2014 Xuanyi Chew. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // // The original code is lifted from the Go standard library which is governed by // a BSD-style licence which can be found here: https://golang.org/LICENSE #include "textflag.h" // The method is based on a paper by Naoki Shibata: "Efficient evaluation // methods of elementary functions suitable for SIMD computation", Proc. // of International Supercomputing Conference 2010 (ISC'10), pp. 25 -- 32 // (May 2010). The paper is available at // http://www.springerlink.com/content/340228x165742104/ // // The original code and the constants below are from the author's // implementation available at http://freshmeat.net/projects/sleef. // The README file says, "The software is in public domain. // You can use the software without any obligation." // // This code is a simplified version of the original. // The magic numbers for the float32 are lifted from the same project #define LN2 0.693147182464599609375 // log_e(2) #define LOG2E 1.44269502162933349609375 // 1/LN2 #define LN2U 0.693145751953125 // upper half LN2 #define LN2L 1.428606765330187045e-06 // lower half LN2 #define T0 1.0 #define T1 0.5 #define T2 0.166665524244308471679688 #define T3 0.0416710823774337768554688 #define T4 0.00836596917361021041870117 #define PosInf 0x7F800000 #define NegInf 0xFF800000 // func archExp(x float32) float32 TEXT ·archExp(SB),NOSPLIT,$0 // test bits for not-finite MOVL x+0(FP), BX MOVQ $~(1<<31), AX // sign bit mask MOVL BX, DX ANDL AX, DX MOVL $PosInf, AX CMPL AX, DX JLE notFinite MOVL BX, X0 MOVSS $LOG2E, X1 MULSS X0, X1 CVTSS2SL X1, BX // BX = exponent CVTSL2SS BX, X1 MOVSS $LN2U, X2 MULSS X1, X2 SUBSS X2, X0 MOVSS $LN2L, X2 MULSS X1, X2 SUBSS X2, X0 // reduce argument MULSS $0.0625, X0 // Taylor series evaluation ADDSS $T4, X1 MULSS X0, X1 ADDSS $T3, X1 MULSS X0, X1 ADDSS $T2, X1 MULSS X0, X1 ADDSS $T1, X1 MULSS X0, X1 ADDSS $T0, X1 MULSS X1, X0 MOVSS $2.0, X1 ADDSS X0, X1 MULSS X1, X0 MOVSS $2.0, X1 ADDSS X0, X1 MULSS X1, X0 MOVSS $2.0, X1 ADDSS X0, X1 MULSS X1, X0 MOVSS $2.0, X1 ADDSS X0, X1 MULSS X1, X0 ADDSS $1.0, X0 // return fr * 2**exponent MOVL $0x7F, AX // bias ADDL AX, BX JLE underflow CMPL BX, $0xFF JGE overflow MOVL $23, CX SHLQ CX, BX MOVL BX, X1 MULSS X1, X0 MOVSS X0, ret+8(FP) RET notFinite: // test bits for -Inf MOVL $NegInf, AX CMPQ AX, BX JNE notNegInf // -Inf, return 0 underflow: // return 0 MOVL $0, AX MOVL AX, ret+8(FP) RET overflow: // return +Inf MOVL $PosInf, BX notNegInf: // NaN or +Inf, return x MOVL BX, ret+8(FP) RET TEXT ·archExp2(SB),NOSPLIT,$0 JMP ·exp2(SB) math32-1.11.1/exp_asm.go000066400000000000000000000006131467305561300146660ustar00rootroot00000000000000// Copyright 2021 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. //go:build !noasm && !tinygo && (amd64 || 386 || arm || ppc64le || wasm || s390x) // +build !noasm // +build !tinygo // +build amd64 386 arm ppc64le wasm s390x package math32 const haveArchExp = true func archExp(x float32) float32 math32-1.11.1/exp_noasm.go000066400000000000000000000006311467305561300152230ustar00rootroot00000000000000// Copyright 2021 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. //go:build noasm || tinygo || !(amd64 || 386 || arm || ppc64le || wasm || s390x) // +build noasm tinygo !amd64,!386,!arm,!ppc64le,!wasm,!s390x package math32 const haveArchExp = false func archExp(x float32) float32 { panic("not implemented") } math32-1.11.1/expm1f.go000066400000000000000000000174111467305561300144360ustar00rootroot00000000000000// Copyright 2010 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package math32 // The original C code, the long comment, and the constants // below are from FreeBSD's /usr/src/lib/msun/src/s_expm1.c // and came with this notice. The go code is a simplified // version of the original C. // // ==================================================== // Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. // // Developed at SunPro, a Sun Microsystems, Inc. business. // Permission to use, copy, modify, and distribute this // software is freely granted, provided that this notice // is preserved. // ==================================================== // // expm1(x) // Returns exp(x)-1, the exponential of x minus 1. // // Method // 1. Argument reduction: // Given x, find r and integer k such that // // x = k*ln2 + r, |r| <= 0.5*ln2 ~ 0.34658 // // Here a correction term c will be computed to compensate // the error in r when rounded to a floating-point number. // // 2. Approximating expm1(r) by a special rational function on // the interval [0,0.34658]: // Since // r*(exp(r)+1)/(exp(r)-1) = 2+ r**2/6 - r**4/360 + ... // we define R1(r*r) by // r*(exp(r)+1)/(exp(r)-1) = 2+ r**2/6 * R1(r*r) // That is, // R1(r**2) = 6/r *((exp(r)+1)/(exp(r)-1) - 2/r) // = 6/r * ( 1 + 2.0*(1/(exp(r)-1) - 1/r)) // = 1 - r**2/60 + r**4/2520 - r**6/100800 + ... // We use a special Reme algorithm on [0,0.347] to generate // a polynomial of degree 5 in r*r to approximate R1. The // maximum error of this polynomial approximation is bounded // by 2**-61. In other words, // R1(z) ~ 1.0 + Q1*z + Q2*z**2 + Q3*z**3 + Q4*z**4 + Q5*z**5 // where Q1 = -1.6666666666666567384E-2, // Q2 = 3.9682539681370365873E-4, // Q3 = -9.9206344733435987357E-6, // Q4 = 2.5051361420808517002E-7, // Q5 = -6.2843505682382617102E-9; // (where z=r*r, and the values of Q1 to Q5 are listed below) // with error bounded by // | 5 | -61 // | 1.0+Q1*z+...+Q5*z - R1(z) | <= 2 // | | // // expm1(r) = exp(r)-1 is then computed by the following // specific way which minimize the accumulation rounding error: // 2 3 // r r [ 3 - (R1 + R1*r/2) ] // expm1(r) = r + --- + --- * [--------------------] // 2 2 [ 6 - r*(3 - R1*r/2) ] // // To compensate the error in the argument reduction, we use // expm1(r+c) = expm1(r) + c + expm1(r)*c // ~ expm1(r) + c + r*c // Thus c+r*c will be added in as the correction terms for // expm1(r+c). Now rearrange the term to avoid optimization // screw up: // ( 2 2 ) // ({ ( r [ R1 - (3 - R1*r/2) ] ) } r ) // expm1(r+c)~r - ({r*(--- * [--------------------]-c)-c} - --- ) // ({ ( 2 [ 6 - r*(3 - R1*r/2) ] ) } 2 ) // ( ) // // = r - E // 3. Scale back to obtain expm1(x): // From step 1, we have // expm1(x) = either 2**k*[expm1(r)+1] - 1 // = or 2**k*[expm1(r) + (1-2**-k)] // 4. Implementation notes: // (A). To save one multiplication, we scale the coefficient Qi // to Qi*2**i, and replace z by (x**2)/2. // (B). To achieve maximum accuracy, we compute expm1(x) by // (i) if x < -56*ln2, return -1.0, (raise inexact if x!=inf) // (ii) if k=0, return r-E // (iii) if k=-1, return 0.5*(r-E)-0.5 // (iv) if k=1 if r < -0.25, return 2*((r+0.5)- E) // else return 1.0+2.0*(r-E); // (v) if (k<-2||k>56) return 2**k(1-(E-r)) - 1 (or exp(x)-1) // (vi) if k <= 20, return 2**k((1-2**-k)-(E-r)), else // (vii) return 2**k(1-((E+2**-k)-r)) // // Special cases: // expm1(INF) is INF, expm1(NaN) is NaN; // expm1(-INF) is -1, and // for finite argument, only expm1(0)=0 is exact. // // Accuracy: // according to an error analysis, the error is always less than // 1 ulp (unit in the last place). // // Misc. info. // For IEEE double // if x > 7.09782712893383973096e+02 then expm1(x) overflow // // Constants: // The hexadecimal values are the intended ones for the following // constants. The decimal values may be used, provided that the // compiler will convert from decimal to binary accurately enough // to produce the hexadecimal values shown. // // Expm1 returns e**x - 1, the base-e exponential of x minus 1. // It is more accurate than Exp(x) - 1 when x is near zero. // // Special cases are: // Expm1(+Inf) = +Inf // Expm1(-Inf) = -1 // Expm1(NaN) = NaN // Very large values overflow to -1 or +Inf. func Expm1(x float32) float32 { return expm1(x) } func expm1(x float32) float32 { const ( Othreshold = 89.415985 // 0x42b2d4fc Ln2X27 = 1.871497344970703125e+01 // 0x4195b844 Ln2HalfX3 = 1.0397207736968994140625 // 0x3F851592 Ln2Half = 3.465735912322998046875e-01 // 0x3eb17218 Ln2Hi = 6.9313812256e-01 // 0x3f317180 Ln2Lo = 9.0580006145e-06 // 0x3717f7d1 InvLn2 = 1.4426950216e+00 // 0x3fb8aa3b Tiny = 1.0 / (1 << 54) // 2**-54 = 0x3c90000000000000 /* scaled coefficients related to expm1 */ Q1 = -3.3333335072e-02 /* 0xbd088889 */ Q2 = 1.5873016091e-03 /* 0x3ad00d01 */ Q3 = -7.9365076090e-05 /* 0xb8a670cd */ Q4 = 4.0082177293e-06 /* 0x36867e54 */ Q5 = -2.0109921195e-07 /* 0xb457edbb */ ) // special cases switch { case IsInf(x, 1) || IsNaN(x): return x case IsInf(x, -1): return -1 } absx := x sign := false if x < 0 { absx = -absx sign = true } // filter out huge argument if absx >= Ln2X27 { // if |x| >= 27 * ln2 if sign { return -1 // x < -56*ln2, return -1 } if absx >= Othreshold { // if |x| >= 89.415985... return Inf(1) } } // argument reduction var c float32 var k int if absx > Ln2Half { // if |x| > 0.5 * ln2 var hi, lo float32 if absx < Ln2HalfX3 { // and |x| < 1.5 * ln2 if !sign { hi = x - Ln2Hi lo = Ln2Lo k = 1 } else { hi = x + Ln2Hi lo = -Ln2Lo k = -1 } } else { if !sign { k = int(InvLn2*x + 0.5) } else { k = int(InvLn2*x - 0.5) } t := float32(k) hi = x - t*Ln2Hi // t * Ln2Hi is exact here lo = t * Ln2Lo } x = hi - lo c = (hi - x) - lo } else if absx < Tiny { // when |x| < 2**-54, return x return x } else { k = 0 } // x is now in primary range hfx := 0.5 * x hxs := x * hfx r1 := 1 + hxs*(Q1+hxs*(Q2+hxs*(Q3+hxs*(Q4+hxs*Q5)))) t := 3 - r1*hfx e := hxs * ((r1 - t) / (6.0 - x*t)) if k != 0 { e = (x*(e-c) - c) e -= hxs switch { case k == -1: return 0.5*(x-e) - 0.5 case k == 1: if x < -0.25 { return -2 * (e - (x + 0.5)) } return 1 + 2*(x-e) case k <= -2 || k > 56: // suffice to return exp(x)-1 y := 1 - (e - x) y = Float32frombits(Float32bits(y) + uint32(k)<<23) // add k to y's exponent return y - 1 } if k < 20 { t := Float32frombits(0x3f800000 - (0x1000000 >> uint(k))) // t=1-2**-k y := t - (e - x) y = Float32frombits(Float32bits(y) + uint32(k)<<23) // add k to y's exponent return y } t := Float32frombits(uint32(0x7f-k) << 23) // 2**-k y := x - (e + t) y += 1 y = Float32frombits(Float32bits(y) + uint32(k)<<23) // add k to y's exponent return y } return x - (x*e - hxs) // c is 0 } math32-1.11.1/export_test.go000066400000000000000000000002061467305561300156100ustar00rootroot00000000000000package math32 // Export internal functions for testing. // var Exp2Go = exp2 var SqrtGo = sqrt var ExpGo = exp var HypotGo = hypot math32-1.11.1/floor.go000066400000000000000000000017271467305561300143620ustar00rootroot00000000000000package math32 // Floor returns the greatest integer value less than or equal to x. // // Special cases are: // Floor(±0) = ±0 // Floor(±Inf) = ±Inf // Floor(NaN) = NaN func Floor(x float32) float32 { return floor(x) } func floor(x float32) float32 { if x == 0 || IsNaN(x) || IsInf(x, 0) { return x } if x < 0 { d, fract := Modf(-x) if fract != 0.0 { d = d + 1 } return -d } d, _ := Modf(x) return d } // Ceil returns the least integer value greater than or equal to x. // // Special cases are: // Ceil(±0) = ±0 // Ceil(±Inf) = ±Inf // Ceil(NaN) = NaN func Ceil(x float32) float32 { return ceil(x) } func ceil(x float32) float32 { return -Floor(-x) } // Trunc returns the integer value of x. // // Special cases are: // Trunc(±0) = ±0 // Trunc(±Inf) = ±Inf // Trunc(NaN) = NaN func Trunc(x float32) float32 { return trunc(x) } func trunc(x float32) float32 { if x == 0 || IsNaN(x) || IsInf(x, 0) { return x } d, _ := Modf(x) return d } math32-1.11.1/frexp.go000066400000000000000000000013231467305561300143550ustar00rootroot00000000000000package math32 // Frexp breaks f into a normalized fraction // and an integral power of two. // It returns frac and exp satisfying f == frac × 2**exp, // with the absolute value of frac in the interval [½, 1). // // Special cases are: // Frexp(±0) = ±0, 0 // Frexp(±Inf) = ±Inf, 0 // Frexp(NaN) = NaN, 0 func Frexp(f float32) (frac float32, exp int) { return frexp(f) } func frexp(f float32) (frac float32, exp int) { // special cases switch { case f == 0: return f, 0 // correctly return -0 case IsInf(f, 0) || IsNaN(f): return f, 0 } f, exp = normalize(f) x := Float32bits(f) exp += int((x>>shift)&mask) - bias + 1 x &^= mask << shift x |= (-1 + bias) << shift frac = Float32frombits(x) return } math32-1.11.1/gamma.go000066400000000000000000000001511467305561300143110ustar00rootroot00000000000000package math32 import "math" func Gamma(x float32) float32 { return float32(math.Gamma(float64(x))) } math32-1.11.1/go.mod000066400000000000000000000000511467305561300140050ustar00rootroot00000000000000module github.com/chewxy/math32 go 1.13 math32-1.11.1/hypot.go000066400000000000000000000012301467305561300143710ustar00rootroot00000000000000package math32 /* Hypot -- sqrt(p*p + q*q), but overflows only if the result does. */ // Hypot returns Sqrt(p*p + q*q), taking care to avoid // unnecessary overflow and underflow. // // Special cases are: // Hypot(±Inf, q) = +Inf // Hypot(p, ±Inf) = +Inf // Hypot(NaN, q) = NaN // Hypot(p, NaN) = NaN func Hypot(p, q float32) float32 { return hypot(p, q) } func hypot(p, q float32) float32 { // special cases switch { case IsInf(p, 0) || IsInf(q, 0): return Inf(1) case IsNaN(p) || IsNaN(q): return NaN() } if p < 0 { p = -p } if q < 0 { q = -q } if p < q { p, q = q, p } if p == 0 { return 0 } q = q / p return p * Sqrt(1+q*q) } math32-1.11.1/j0.go000066400000000000000000000001431467305561300135410ustar00rootroot00000000000000package math32 import "math" func J0(x float32) float32 { return float32(math.J0(float64(x))) } math32-1.11.1/j1.go000066400000000000000000000001431467305561300135420ustar00rootroot00000000000000package math32 import "math" func J1(x float32) float32 { return float32(math.J1(float64(x))) } math32-1.11.1/jn.go000066400000000000000000000002741467305561300136440ustar00rootroot00000000000000package math32 import "math" func Jn(n int, x float32) float32 { return float32(math.Jn(n, float64(x))) } func Yn(n int, x float32) float32 { return float32(math.Yn(n, float64(x))) } math32-1.11.1/ldexp.go000066400000000000000000000015471467305561300143550ustar00rootroot00000000000000package math32 // Ldexp is the inverse of Frexp. // It returns frac × 2**exp. // // Special cases are: // Ldexp(±0, exp) = ±0 // Ldexp(±Inf, exp) = ±Inf // Ldexp(NaN, exp) = NaN func Ldexp(frac float32, exp int) float32 { return ldexp(frac, exp) } func ldexp(frac float32, exp int) float32 { // special cases switch { case frac == 0: return frac // correctly return -0 case IsInf(frac, 0) || IsNaN(frac): return frac } frac, e := normalize(frac) exp += e x := Float32bits(frac) exp += int(x>>shift)&mask - bias if exp < -149 { return Copysign(0, frac) // underflow } if exp > 127 { // overflow if frac < 0 { return Inf(-1) } return Inf(1) } var m float32 = 1 if exp < -(127 - 1) { // denormal exp += shift m = 1.0 / (1 << 23) // 1/(2**-23) } x &^= mask << shift x |= uint32(exp+bias) << shift return m * Float32frombits(x) } math32-1.11.1/lgamma.go000066400000000000000000000002241467305561300144660ustar00rootroot00000000000000package math32 import "math" func Lgamma(x float32) (lgamma float32, sign int) { lg, sign := math.Lgamma(float64(x)) return float32(lg), sign } math32-1.11.1/log.go000066400000000000000000000070671467305561300140250ustar00rootroot00000000000000package math32 /* Floating-point logarithm. */ // The original C code, the long comment, and the constants // below are from FreeBSD's /usr/src/lib/msun/src/e_log.c // and came with this notice. The go code is a simpler // version of the original C. // // ==================================================== // Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. // // Developed at SunPro, a Sun Microsystems, Inc. business. // Permission to use, copy, modify, and distribute this // software is freely granted, provided that this notice // is preserved. // ==================================================== // // __ieee754_log(x) // Return the logarithm of x // // Method : // 1. Argument Reduction: find k and f such that // x = 2**k * (1+f), // where sqrt(2)/2 < 1+f < sqrt(2) . // // 2. Approximation of log(1+f). // Let s = f/(2+f) ; based on log(1+f) = log(1+s) - log(1-s) // = 2s + 2/3 s**3 + 2/5 s**5 + ....., // = 2s + s*R // We use a special Reme algorithm on [0,0.1716] to generate // a polynomial of degree 14 to approximate R. The maximum error // of this polynomial approximation is bounded by 2**-58.45. In // other words, // 2 4 6 8 10 12 14 // R(z) ~ L1*s +L2*s +L3*s +L4*s +L5*s +L6*s +L7*s // (the values of L1 to L7 are listed in the program) and // | 2 14 | -58.45 // | L1*s +...+L7*s - R(z) | <= 2 // | | // Note that 2s = f - s*f = f - hfsq + s*hfsq, where hfsq = f*f/2. // In order to guarantee error in log below 1ulp, we compute log by // log(1+f) = f - s*(f - R) (if f is not too large) // log(1+f) = f - (hfsq - s*(hfsq+R)). (better accuracy) // // 3. Finally, log(x) = k*Ln2 + log(1+f). // = k*Ln2_hi+(f-(hfsq-(s*(hfsq+R)+k*Ln2_lo))) // Here Ln2 is split into two floating point number: // Ln2_hi + Ln2_lo, // where n*Ln2_hi is always exact for |n| < 2000. // // Special cases: // log(x) is NaN with signal if x < 0 (including -INF) ; // log(+INF) is +INF; log(0) is -INF with signal; // log(NaN) is that NaN with no signal. // // Accuracy: // according to an error analysis, the error is always less than // 1 ulp (unit in the last place). // // Constants: // The hexadecimal values are the intended ones for the following // constants. The decimal values may be used, provided that the // compiler will convert from decimal to binary accurately enough // to produce the hexadecimal values shown. // Log returns the natural logarithm of x. // // Special cases are: // Log(+Inf) = +Inf // Log(0) = -Inf // Log(x < 0) = NaN // Log(NaN) = NaN func Log(x float32) float32 { if haveArchLog { return archLog(x) } return log(x) } func log(x float32) float32 { const ( Ln2Hi = 6.9313812256e-01 /* 0x3f317180 */ Ln2Lo = 9.0580006145e-06 /* 0x3717f7d1 */ L1 = 6.6666668653e-01 /* 0x3f2aaaab */ L2 = 4.0000000596e-01 /* 0x3ecccccd */ L3 = 2.8571429849e-01 /* 0x3e924925 */ L4 = 2.2222198546e-01 /* 0x3e638e29 */ L5 = 1.8183572590e-01 /* 0x3e3a3325 */ L6 = 1.5313838422e-01 /* 0x3e1cd04f */ L7 = 1.4798198640e-01 /* 0x3e178897 */ ) // special cases switch { case IsNaN(x) || IsInf(x, 1): return x case x < 0: return NaN() case x == 0: return Inf(-1) } // reduce f1, ki := Frexp(x) if f1 < Sqrt2/2 { f1 *= 2 ki-- } f := f1 - 1 k := float32(ki) // compute s := f / (2 + f) s2 := s * s s4 := s2 * s2 t1 := s2 * (L1 + s4*(L3+s4*(L5+s4*L7))) t2 := s4 * (L2 + s4*(L4+s4*L6)) R := t1 + t2 hfsq := 0.5 * f * f return k*Ln2Hi - ((hfsq - (s*(hfsq+R) + k*Ln2Lo)) - f) } math32-1.11.1/log10.go000066400000000000000000000001511467305561300141510ustar00rootroot00000000000000package math32 import "math" func Log10(x float32) float32 { return float32(math.Log10(float64(x))) } math32-1.11.1/log1p.go000066400000000000000000000001511467305561300142510ustar00rootroot00000000000000package math32 import "math" func Log1p(x float32) float32 { return float32(math.Log1p(float64(x))) } math32-1.11.1/log2.go000066400000000000000000000001471467305561300140770ustar00rootroot00000000000000package math32 import "math" func Log2(x float32) float32 { return float32(math.Log2(float64(x))) } math32-1.11.1/log_amd64.s000066400000000000000000000067471467305561300146610ustar00rootroot00000000000000//go:build !tinygo && !noasm // Copyright 2010 The Go Authors. All rights reserved. // Use of this source code is governed by a BSS-style // license that can be found in the LICENSE file. #include "textflag.h" #define HSqrt2 7.07106781186547524401e-01 // sqrt(2)/2 #define Ln2Hi 6.9313812256e-01 // 0x3f317180 #define Ln2Lo 9.0580006145e-06 // 0x3717f7d1 #define L1 6.6666668653e-01 // 0x3f2aaaab #define L2 4.0000000596e-01 // 0x3ecccccd #define L3 2.8571429849e-01 // 0x3e924925 #define L4 2.2222198546e-01 // 0x3e638e29 #define L5 1.8183572590e-01 // 0x3e3a3325 #define L6 1.5313838422e-01 // 0x3e1cd04f #define L7 1.4798198640e-01 // 0x3e178897 #define NaN 0x7FE00000 #define PosInf 0x7F800000 #define NegInf 0xFF800000 // func archLog(x float64) float64 TEXT ·archLog(SB),NOSPLIT,$0 // test bits for special cases MOVL x+0(FP), BX MOVQ $~(1<<31), AX // sign bit mask ANDQ BX, AX JEQ isZero MOVL $0, AX CMPL AX, BX JGT isNegative MOVL $PosInf, AX CMPQ AX, BX JLE isInfOrNaN // f1, ki := math.Frexp(x); k := float64(ki) MOVL BX, X0 MOVL $0x007FFFFF, AX MOVL AX, X2 ANDPS X0, X2 MOVSS $0.5, X0 // 0x3FE0000000000000 ORPS X0, X2 // X2= f1 SHRQ $23, BX ANDL $0xFF, BX SUBL $0x7E, BX CVTSL2SS BX, X1 // x1= k, x2= f1 // if f1 < math.Sqrt2/2 { k -= 1; f1 *= 2 } MOVSS $HSqrt2, X0 // x0= 0.7071, x1= k, x2= f1 CMPSS X2, X0, 5 // cmpnlt; x0= 0 or ^0, x1= k, x2 = f1 MOVSS $1.0, X3 // x0= 0 or ^0, x1= k, x2 = f1, x3= 1 ANDPS X0, X3 // x0= 0 or ^0, x1= k, x2 = f1, x3= 0 or 1 SUBSS X3, X1 // x0= 0 or ^0, x1= k, x2 = f1, x3= 0 or 1 MOVSS $1.0, X0 // x0= 1, x1= k, x2= f1, x3= 0 or 1 ADDSS X0, X3 // x0= 1, x1= k, x2= f1, x3= 1 or 2 MULSS X3, X2 // x0= 1, x1= k, x2= f1 // f := f1 - 1 SUBSS X0, X2 // x1= k, x2= f // s := f / (2 + f) MOVSS $2.0, X0 ADDSS X2, X0 MOVUPS X2, X3 DIVSS X0, X3 // x1=k, x2= f, x3= s // s2 := s * s MOVUPS X3, X4 // x1= k, x2= f, x3= s MULSS X4, X4 // x1= k, x2= f, x3= s, x4= s2 // s4 := s2 * s2 MOVUPS X4, X5 // x1= k, x2= f, x3= s, x4= s2 MULSS X5, X5 // x1= k, x2= f, x3= s, x4= s2, x5= s4 // t1 := s2 * (L1 + s4*(L3+s4*(L5+s4*L7))) MOVSS $L7, X6 MULSS X5, X6 ADDSS $L5, X6 MULSS X5, X6 ADDSS $L3, X6 MULSS X5, X6 ADDSS $L1, X6 MULSS X6, X4 // x1= k, x2= f, x3= s, x4= t1, x5= s4 // t2 := s4 * (L2 + s4*(L4+s4*L6)) MOVSS $L6, X6 MULSS X5, X6 ADDSS $L4, X6 MULSS X5, X6 ADDSS $L2, X6 MULSS X6, X5 // x1= k, x2= f, x3= s, x4= t1, x5= t2 // R := t1 + t2 ADDSS X5, X4 // x1= k, x2= f, x3= s, x4= R // hfsq := 0.5 * f * f MOVSS $0.5, X0 MULSS X2, X0 MULSS X2, X0 // x0= hfsq, x1= k, x2= f, x3= s, x4= R // return k*Ln2Hi - ((hfsq - (s*(hfsq+R) + k*Ln2Lo)) - f) ADDSS X0, X4 // x0= hfsq, x1= k, x2= f, x3= s, x4= hfsq+R MULSS X4, X3 // x0= hfsq, x1= k, x2= f, x3= s*(hfsq+R) MOVSS $Ln2Lo, X4 MULSS X1, X4 // x4= k*Ln2Lo ADDSS X4, X3 // x0= hfsq, x1= k, x2= f, x3= s*(hfsq+R)+k*Ln2Lo SUBSS X3, X0 // x0= hfsq-(s*(hfsq+R)+k*Ln2Lo), x1= k, x2= f SUBSS X2, X0 // x0= (hfsq-(s*(hfsq+R)+k*Ln2Lo))-f, x1= k MULSS $Ln2Hi, X1 // x0= (hfsq-(s*(hfsq+R)+k*Ln2Lo))-f, x1= k*Ln2Hi SUBSS X0, X1 // x1= k*Ln2Hi-((hfsq-(s*(hfsq+R)+k*Ln2Lo))-f) MOVSS X1, ret+8(FP) RET isInfOrNaN: MOVL BX, ret+8(FP) // +Inf or NaN, return x RET isNegative: MOVL $NaN, AX MOVL AX, ret+8(FP) // return NaN RET isZero: MOVL $NegInf, AX MOVL AX, ret+8(FP) // return -Inf RET math32-1.11.1/log_asm.go000066400000000000000000000006321467305561300146540ustar00rootroot00000000000000// Copyright 2021 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. //go:build !noasm && !tinygo && (amd64 || arm || s390x || 386 || arm64 || ppc64le || wasm) // +build !noasm // +build !tinygo // +build amd64 arm s390x 386 arm64 ppc64le wasm package math32 const haveArchLog = true func archLog(x float32) float32 math32-1.11.1/log_noasm.go000066400000000000000000000006571467305561300152200ustar00rootroot00000000000000// Copyright 2021 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. //go:build noasm || tinygo || (!amd64 && !arm && !s390x && !386 && !arm64 && !ppc64le && !wasm) // +build noasm tinygo !amd64,!arm,!s390x,!386,!arm64,!ppc64le,!wasm package math32 const haveArchLog = false func archLog(x float32) float32 { panic("not implemented") } math32-1.11.1/logb.go000066400000000000000000000002451467305561300141560ustar00rootroot00000000000000package math32 import "math" func Logb(x float32) float32 { return float32(math.Logb(float64(x))) } func Ilogb(x float32) int { return math.Ilogb(float64(x)) } math32-1.11.1/math32_test.go000066400000000000000000000024561467305561300153760ustar00rootroot00000000000000//go:build !tinygo // +build !tinygo package math32 import ( "fmt" "os" "os/exec" "testing" ) func TestVetMath32(t *testing.T) { linuxArches := []string{"amd64", "arm", "arm64", "s390x", "ppc64le", "riscv64", "386", "mips", "mips64", "mipsle", "mips64le"} // Linux architectures for _, GOARCH := range linuxArches { GOOS := "linux" t.Run(fmt.Sprintf("GOOS=%s GOARCH=%s", GOOS, GOARCH), func(t *testing.T) { goVet(t, GOOS, GOARCH) goBuildVet(t, GOOS, GOARCH) }) } // WASM t.Run("GOOS=js GOARCH=wasm", func(t *testing.T) { goVet(t, "js", "wasm") goBuildVet(t, "js", "wasm") }) // AIX t.Run("GOOS=aix GOARCH=ppc64", func(t *testing.T) { goVet(t, "aix", "ppc64") goBuildVet(t, "aix", "ppc64") }) } func goVet(t *testing.T, GOOS, GOARCH string) { env := append(os.Environ(), "GOOS="+GOOS, "GOARCH="+GOARCH) cmd := exec.Command("go", "vet", ".") cmd.Env = env output, err := cmd.CombinedOutput() if err != nil { t.Error(string(output), err) } } func goBuildVet(t *testing.T, GOOS, GOARCH string) { env := append(os.Environ(), "GOOS="+GOOS, "GOARCH="+GOARCH) const buildname = "math32.test" defer os.Remove(buildname) cmd := exec.Command("go", "test", "-c", "-o="+buildname) cmd.Env = env output, err := cmd.CombinedOutput() if err != nil { t.Error(string(output), err) } } math32-1.11.1/mod.go000066400000000000000000000012701467305561300140110ustar00rootroot00000000000000package math32 // Mod returns the floating-point remainder of x/y. // The magnitude of the result is less than y and its // sign agrees with that of x. // // Special cases are: // Mod(±Inf, y) = NaN // Mod(NaN, y) = NaN // Mod(x, 0) = NaN // Mod(x, ±Inf) = x // Mod(x, NaN) = NaN func Mod(x, y float32) float32 { return mod(x, y) } func mod(x, y float32) float32 { if y == 0 || IsInf(x, 0) || IsNaN(x) || IsNaN(y) { return NaN() } if y < 0 { y = -y } yfr, yexp := Frexp(y) sign := false r := x if x < 0 { r = -x sign = true } for r >= y { rfr, rexp := Frexp(r) if rfr < yfr { rexp = rexp - 1 } r = r - Ldexp(y, rexp-yexp) } if sign { r = -r } return r } math32-1.11.1/modf.go000066400000000000000000000013021467305561300141530ustar00rootroot00000000000000package math32 // Modf returns integer and fractional floating-point numbers // that sum to f. Both values have the same sign as f. // // Special cases are: // Modf(±Inf) = ±Inf, NaN // Modf(NaN) = NaN, NaN func Modf(f float32) (int float32, frac float32) { return modf(f) } func modf(f float32) (int float32, frac float32) { if f < 1 { switch { case f < 0: int, frac = Modf(-f) return -int, -frac case f == 0: return f, f // Return -0, -0 when f == -0 } return 0, f } x := Float32bits(f) e := uint(x>>shift)&mask - bias // Keep the top 9+e bits, the integer part; clear the rest. if e < 32-9 { x &^= 1<<(32-9-e) - 1 } int = Float32frombits(x) frac = f - int return } math32-1.11.1/nextafter.go000066400000000000000000000012741467305561300152360ustar00rootroot00000000000000// Copyright 2010 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package math32 // Nextafter returns the next representable float32 value after x towards y. // // Special cases are: // // Nextafter32(x, x) = x // Nextafter32(NaN, y) = NaN // Nextafter32(x, NaN) = NaN func Nextafter(x, y float32) (r float32) { switch { case IsNaN(x) || IsNaN(y): // special case r = float32(NaN()) case x == y: r = x case x == 0: r = float32(Copysign(Float32frombits(1), y)) case (y > x) == (x > 0): r = Float32frombits(Float32bits(x) + 1) default: r = Float32frombits(Float32bits(x) - 1) } return } math32-1.11.1/pow.go000066400000000000000000000050301467305561300140350ustar00rootroot00000000000000package math32 import "math" func isOddInt(x float32) bool { xi, xf := Modf(x) return xf == 0 && int32(xi)&1 == 1 } // Special cases taken from FreeBSD's /usr/src/lib/msun/src/e_pow.c // updated by IEEE Std. 754-2008 "Section 9.2.1 Special values". // Pow returns x**y, the base-x exponential of y. // // Special cases are (in order): // Pow(x, ±0) = 1 for any x // Pow(1, y) = 1 for any y // Pow(x, 1) = x for any x // Pow(NaN, y) = NaN // Pow(x, NaN) = NaN // Pow(±0, y) = ±Inf for y an odd integer < 0 // Pow(±0, -Inf) = +Inf // Pow(±0, +Inf) = +0 // Pow(±0, y) = +Inf for finite y < 0 and not an odd integer // Pow(±0, y) = ±0 for y an odd integer > 0 // Pow(±0, y) = +0 for finite y > 0 and not an odd integer // Pow(-1, ±Inf) = 1 // Pow(x, +Inf) = +Inf for |x| > 1 // Pow(x, -Inf) = +0 for |x| > 1 // Pow(x, +Inf) = +0 for |x| < 1 // Pow(x, -Inf) = +Inf for |x| < 1 // Pow(+Inf, y) = +Inf for y > 0 // Pow(+Inf, y) = +0 for y < 0 // Pow(-Inf, y) = Pow(-0, -y) // Pow(x, y) = NaN for finite x < 0 and finite non-integer y func Pow(x, y float32) float32 { switch { case y == 0 || x == 1: return 1 case y == 1: return x case y == 0.5: return Sqrt(x) case y == -0.5: return 1 / Sqrt(x) case IsNaN(x) || IsNaN(y): return NaN() case x == 0: switch { case y < 0: if isOddInt(y) { return Copysign(Inf(1), x) } return Inf(1) case y > 0: if isOddInt(y) { return x } return 0 } case IsInf(y, 0): switch { case x == -1: return 1 case (Abs(x) < 1) == IsInf(y, 1): return 0 default: return Inf(1) } case IsInf(x, 0): if IsInf(x, -1) { return Pow(1/x, -y) // Pow(-0, -y) } switch { case y < 0: return 0 case y > 0: return Inf(1) } } absy := y flip := false if absy < 0 { absy = -absy flip = true } yi, yf := Modf(absy) if yf != 0 && x < 0 { return NaN() } if yi >= 1<<31 { return Exp(y * Log(x)) } // ans = a1 * 2**ae (= 1 for now). a1 := float32(1.0) ae := 0 // ans *= x**yf if yf != 0 { if yf > 0.5 { yf-- yi++ } a1 = Exp(yf * Log(x)) } // ans *= x**yi // by multiplying in successive squarings // of x according to bits of yi. // accumulate powers of two into exp. x1, xe := Frexp(x) for i := int32(yi); i != 0; i >>= 1 { if i&1 == 1 { a1 *= x1 ae += xe } x1 *= x1 xe <<= 1 if x1 < .5 { x1 += x1 xe-- } } // ans = a1*2**ae // if flip { ans = 1 / ans } // but in the opposite order if flip { a1 = 1 / a1 ae = -ae } return Ldexp(a1, ae) } func Pow10(e int) float32 { return float32(math.Pow10(e)) } math32-1.11.1/remainder.go000066400000000000000000000035371467305561300152100ustar00rootroot00000000000000package math32 // The original C code and the comment below are from // FreeBSD's /usr/src/lib/msun/src/e_remainder.c and came // with this notice. The go code is a simplified version of // the original C. // // ==================================================== // Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. // // Developed at SunPro, a Sun Microsystems, Inc. business. // Permission to use, copy, modify, and distribute this // software is freely granted, provided that this notice // is preserved. // ==================================================== // // __ieee754_remainder(x,y) // Return : // returns x REM y = x - [x/y]*y as if in infinite // precision arithmetic, where [x/y] is the (infinite bit) // integer nearest x/y (in half way cases, choose the even one). // Method : // Based on Mod() returning x - [x/y]chopped * y exactly. // Remainder returns the IEEE 754 floating-point remainder of x/y. // // Special cases are: // Remainder(±Inf, y) = NaN // Remainder(NaN, y) = NaN // Remainder(x, 0) = NaN // Remainder(x, ±Inf) = x // Remainder(x, NaN) = NaN func Remainder(x, y float32) float32 { if haveArchRemainder { return archRemainder(x, y) } return remainder(x, y) } func remainder(x, y float32) float32 { // special cases switch { case IsNaN(x) || IsNaN(y) || IsInf(x, 0) || y == 0: return NaN() case IsInf(y, 0): return x } hx := Float32bits(x) hy := Float32bits(y) hy &= 0x7fffffff hx &= 0x7fffffff if hy <= 0x7effffff { x = Mod(x, y+y) // now x < 2y } if hx-hy == 0 { return 0 } sign := false if x < 0 { x = -x sign = true } if y < 0 { y = -y } if hy < 0x01000000 { if x+x > y { x -= y if x+x >= y { x -= y } } } else { yHalf := 0.5 * y if x > yHalf { x -= y if x >= yHalf { x -= y } } } if sign { x = -x } return x } math32-1.11.1/remainder_amd64.s000066400000000000000000000004151467305561300160300ustar00rootroot00000000000000//go:build !tinygo && !noasm // Copyright 2011 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. #include "textflag.h" TEXT ·archRemainder(SB),NOSPLIT,$0 JMP ·remainder(SB) math32-1.11.1/remainder_asm.go000066400000000000000000000003721467305561300160420ustar00rootroot00000000000000//go:build !noasm && !tinygo && (amd64 || s390x || arm || ppc64le || 386 || wasm) // +build !noasm // +build !tinygo // +build amd64 s390x arm ppc64le 386 wasm package math32 const haveArchRemainder = true func archRemainder(x, y float32) float32 math32-1.11.1/remainder_noasm.go000066400000000000000000000004151467305561300163750ustar00rootroot00000000000000//go:build noasm || tinygo || (!amd64 && !s390x && !arm && !ppc64le && !386 && !wasm) // +build noasm tinygo !amd64,!s390x,!arm,!ppc64le,!386,!wasm package math32 const haveArchRemainder = false func archRemainder(x, y float32) float32 { panic("not implemented") } math32-1.11.1/round.go000066400000000000000000000040601467305561300143610ustar00rootroot00000000000000package math32 // Round returns the nearest integer, rounding half away from zero. // // Special cases are: // Round(±0) = ±0 // Round(±Inf) = ±Inf // Round(NaN) = NaN func Round(x float32) float32 { // Round is a faster implementation of: // // func Round(x float64) float64 { // t := Trunc(x) // if Abs(x-t) >= 0.5 { // return t + Copysign(1, x) // } // return t // } bits := Float32bits(x) e := uint(bits>>shift) & mask if e < bias { // Round abs(x) < 1 including denormals. bits &= signMask // +-0 if e == bias-1 { bits |= uvone // +-1 } } else if e < bias+shift { // Round any abs(x) >= 1 containing a fractional component [0,1). // // Numbers with larger exponents are returned unchanged since they // must be either an integer, infinity, or NaN. const half = 1 << (shift - 1) e -= bias bits += half >> e bits &^= fracMask >> e } return Float32frombits(bits) } // RoundToEven returns the nearest integer, rounding ties to even. // // Special cases are: // RoundToEven(±0) = ±0 // RoundToEven(±Inf) = ±Inf // RoundToEven(NaN) = NaN func RoundToEven(x float32) float32 { // RoundToEven is a faster implementation of: // // func RoundToEven(x float64) float64 { // t := math.Trunc(x) // odd := math.Remainder(t, 2) != 0 // if d := math.Abs(x - t); d > 0.5 || (d == 0.5 && odd) { // return t + math.Copysign(1, x) // } // return t // } bits := Float32bits(x) e := uint(bits>>shift) & mask if e >= bias { // Round abs(x) >= 1. // - Large numbers without fractional components, infinity, and NaN are unchanged. // - Add 0.499.. or 0.5 before truncating depending on whether the truncated // number is even or odd (respectively). const halfMinusULP = (1 << (shift - 1)) - 1 e -= bias bits += (halfMinusULP + (bits>>(shift-e))&1) >> e bits &^= fracMask >> e } else if e == bias-1 && bits&fracMask != 0 { // Round 0.5 < abs(x) < 1. bits = bits&signMask | uvone // +-1 } else { // Round abs(x) <= 0.5 including denormals. bits &= signMask // +-0 } return Float32frombits(bits) } math32-1.11.1/signbit.go000066400000000000000000000002201467305561300146630ustar00rootroot00000000000000package math32 // Signbit returns true if x is negative or negative zero. func Signbit(x float32) bool { return Float32bits(x)&(1<<31) != 0 } math32-1.11.1/sincos.go000066400000000000000000000257221467305561300145400ustar00rootroot00000000000000// Copyright 2011 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package math32 import "math/bits" /* Floating-point sine and cosine. */ // The original C code, the long comment, and the constants // below were from http://netlib.sandia.gov/cephes/cmath/sin.c, // available from http://www.netlib.org/cephes/cmath.tgz. // The go code is a simplified version of the original C. // // sin.c // // Circular sine // // SYNOPSIS: // // double x, y, sin(); // y = sin( x ); // // DESCRIPTION: // // Range reduction is into intervals of pi/4. The reduction error is nearly // eliminated by contriving an extended precision modular arithmetic. // // Two polynomial approximating functions are employed. // Between 0 and pi/4 the sine is approximated by // x + x**3 P(x**2). // Between pi/4 and pi/2 the cosine is represented as // 1 - x**2 Q(x**2). // // ACCURACY: // // Relative error: // arithmetic domain # trials peak rms // DEC 0, 10 150000 3.0e-17 7.8e-18 // IEEE -1.07e9,+1.07e9 130000 2.1e-16 5.4e-17 // // Partial loss of accuracy begins to occur at x = 2**30 = 1.074e9. The loss // is not gradual, but jumps suddenly to about 1 part in 10e7. Results may // be meaningless for x > 2**49 = 5.6e14. // // cos.c // // Circular cosine // // SYNOPSIS: // // double x, y, cos(); // y = cos( x ); // // DESCRIPTION: // // Range reduction is into intervals of pi/4. The reduction error is nearly // eliminated by contriving an extended precision modular arithmetic. // // Two polynomial approximating functions are employed. // Between 0 and pi/4 the cosine is approximated by // 1 - x**2 Q(x**2). // Between pi/4 and pi/2 the sine is represented as // x + x**3 P(x**2). // // ACCURACY: // // Relative error: // arithmetic domain # trials peak rms // IEEE -1.07e9,+1.07e9 130000 2.1e-16 5.4e-17 // DEC 0,+1.07e9 17000 3.0e-17 7.2e-18 // // Cephes Math Library Release 2.8: June, 2000 // Copyright 1984, 1987, 1989, 1992, 2000 by Stephen L. Moshier // // The readme file at http://netlib.sandia.gov/cephes/ says: // Some software in this archive may be from the book _Methods and // Programs for Mathematical Functions_ (Prentice-Hall or Simon & Schuster // International, 1989) or from the Cephes Mathematical Library, a // commercial product. In either event, it is copyrighted by the author. // What you see here may be used freely but it comes with no support or // guarantee. // // The two known misprints in the book are repaired here in the // source listings for the gamma function and the incomplete beta // integral. // // Stephen L. Moshier // moshier@na-net.ornl.gov // sin coefficients var _sin = [...]float32{ 1.58962301576546568060e-10, // 0x3de5d8fd1fd19ccd -2.50507477628578072866e-8, // 0xbe5ae5e5a9291f5d 2.75573136213857245213e-6, // 0x3ec71de3567d48a1 -1.98412698295895385996e-4, // 0xbf2a01a019bfdf03 8.33333333332211858878e-3, // 0x3f8111111110f7d0 -1.66666666666666307295e-1, // 0xbfc5555555555548 } // cos coefficients var _cos = [...]float32{ -1.13585365213876817300e-11, // 0xbda8fa49a0861a9b 2.08757008419747316778e-9, // 0x3e21ee9d7b4e3f05 -2.75573141792967388112e-7, // 0xbe927e4f7eac4bc6 2.48015872888517045348e-5, // 0x3efa01a019c844f5 -1.38888888888730564116e-3, // 0xbf56c16c16c14f91 4.16666666666665929218e-2, // 0x3fa555555555554b } // Sincos returns Sin(x), Cos(x). // // Special cases are: // Sincos(±0) = ±0, 1 // Sincos(±Inf) = NaN, NaN // Sincos(NaN) = NaN, NaN func Sincos(x float32) (sin, cos float32) { const ( PI4A = 7.85398125648498535156e-1 // 0x3fe921fb40000000, Pi/4 split into three parts PI4B = 3.77489470793079817668e-8 // 0x3e64442d00000000, PI4C = 2.69515142907905952645e-15 // 0x3ce8469898cc5170, ) // special cases switch { case x == 0: return x, 1 // return ±0.0, 1.0 case IsNaN(x) || IsInf(x, 0): return NaN(), NaN() } // make argument positive sinSign, cosSign := false, false if x < 0 { x = -x sinSign = true } var j uint64 var y, z float32 if x >= reduceThreshold { j, z = trigReduce(x) } else { j = uint64(x * (4 / Pi)) // integer part of x/(Pi/4), as integer for tests on the phase angle y = float32(j) // integer part of x/(Pi/4), as float if j&1 == 1 { // map zeros to origin j++ y++ } j &= 7 // octant modulo 2Pi radians (360 degrees) z = ((x - y*PI4A) - y*PI4B) - y*PI4C // Extended precision modular arithmetic } if j > 3 { // reflect in x axis j -= 4 sinSign, cosSign = !sinSign, !cosSign } if j > 1 { cosSign = !cosSign } zz := z * z 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]) sin = z + z*zz*((((((_sin[0]*zz)+_sin[1])*zz+_sin[2])*zz+_sin[3])*zz+_sin[4])*zz+_sin[5]) if j == 1 || j == 2 { sin, cos = cos, sin } if cosSign { cos = -cos } if sinSign { sin = -sin } return } // Sin returns the sine of the radian argument x. // // Special cases are: // Sin(±0) = ±0 // Sin(±Inf) = NaN // Sin(NaN) = NaN func Sin(x float32) float32 { const ( PI4A = 7.85398125648498535156e-1 // 0x3fe921fb40000000, Pi/4 split into three parts PI4B = 3.77489470793079817668e-8 // 0x3e64442d00000000, PI4C = 2.69515142907905952645e-15 // 0x3ce8469898cc5170, ) // special cases switch { case x == 0 || IsNaN(x): return x // return ±0 || NaN() case IsInf(x, 0): return NaN() } // make argument positive but save the sign sign := false if x < 0 { x = -x sign = true } var j uint64 var y, z float32 if x >= reduceThreshold { j, z = trigReduce(x) } else { j = uint64(x * (4 / Pi)) // integer part of x/(Pi/4), as integer for tests on the phase angle y = float32(j) // integer part of x/(Pi/4), as float // map zeros to origin if j&1 == 1 { j++ y++ } j &= 7 // octant modulo 2Pi radians (360 degrees) z = ((x - y*PI4A) - y*PI4B) - y*PI4C // Extended precision modular arithmetic } // reflect in x axis if j > 3 { sign = !sign j -= 4 } zz := z * z if j == 1 || j == 2 { 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]) } else { y = z + z*zz*((((((_sin[0]*zz)+_sin[1])*zz+_sin[2])*zz+_sin[3])*zz+_sin[4])*zz+_sin[5]) } if sign { y = -y } return y } // Cos returns the cosine of the radian argument x. // // Special cases are: // Cos(±Inf) = NaN // Cos(NaN) = NaN func Cos(x float32) float32 { const ( PI4A = 7.85398125648498535156e-1 // 0x3fe921fb40000000, Pi/4 split into three parts PI4B = 3.77489470793079817668e-8 // 0x3e64442d00000000, PI4C = 2.69515142907905952645e-15 // 0x3ce8469898cc5170, ) // special cases switch { case IsNaN(x) || IsInf(x, 0): return NaN() } // make argument positive sign := false x = Abs(x) var j uint64 var y, z float32 if x >= reduceThreshold { j, z = trigReduce(x) } else { j = uint64(x * (4 / Pi)) // integer part of x/(Pi/4), as integer for tests on the phase angle y = float32(j) // integer part of x/(Pi/4), as float // map zeros to origin if j&1 == 1 { j++ y++ } j &= 7 // octant modulo 2Pi radians (360 degrees) z = ((x - y*PI4A) - y*PI4B) - y*PI4C // Extended precision modular arithmetic } if j > 3 { j -= 4 sign = !sign } if j > 1 { sign = !sign } zz := z * z if j == 1 || j == 2 { y = z + z*zz*((((((_sin[0]*zz)+_sin[1])*zz+_sin[2])*zz+_sin[3])*zz+_sin[4])*zz+_sin[5]) } else { 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]) } if sign { y = -y } return y } // reduceThreshold is the maximum value of x where the reduction using Pi/4 // in 3 float64 parts still gives accurate results. This threshold // is set by y*C being representable as a float64 without error // where y is given by y = floor(x * (4 / Pi)) and C is the leading partial // terms of 4/Pi. Since the leading terms (PI4A and PI4B in sin.go) have 30 // and 32 trailing zero bits, y should have less than 30 significant bits. // y < 1<<30 -> floor(x*4/Pi) < 1<<30 -> x < (1<<30 - 1) * Pi/4 // So, conservatively we can take x < 1<<29. // Above this threshold Payne-Hanek range reduction must be used. const reduceThreshold = 1 << 29 // trigReduce implements Payne-Hanek range reduction by Pi/4 // for x > 0. It returns the integer part mod 8 (j) and // the fractional part (z) of x / (Pi/4). // The implementation is based on: // "ARGUMENT REDUCTION FOR HUGE ARGUMENTS: Good to the Last Bit" // K. C. Ng et al, March 24, 1992 // The simulated multi-precision calculation of x*B uses 64-bit integer arithmetic. func trigReduce(x float32) (j uint64, z float32) { const PI4 = Pi / 4 if x < PI4 { return 0, x } // Extract out the integer and exponent such that, // x = ix * 2 ** exp. ix := Float32bits(x) exp := int(ix>>shift&mask) - bias - shift ix &^= mask << shift ix |= 1 << shift // Use the exponent to extract the 3 appropriate uint64 digits from mPi4, // B ~ (z0, z1, z2), such that the product leading digit has the exponent -61. // Note, exp >= -53 since x >= PI4 and exp < 971 for maximum float64. const floatingbits = 32 - 3 digit, bitshift := uint(exp+floatingbits)/32, uint(exp+floatingbits)%32 z0 := (mPi4[digit] << bitshift) | (mPi4[digit+1] >> (32 - bitshift)) z1 := (mPi4[digit+1] << bitshift) | (mPi4[digit+2] >> (32 - bitshift)) z2 := (mPi4[digit+2] << bitshift) | (mPi4[digit+3] >> (32 - bitshift)) // Multiply mantissa by the digits and extract the upper two digits (hi, lo). z2hi, _ := bits.Mul64(z2, uint64(ix)) z1hi, z1lo := bits.Mul64(z1, uint64(ix)) z0lo := z0 * uint64(ix) lo, c := bits.Add64(z1lo, z2hi, 0) hi, _ := bits.Add64(z0lo, z1hi, c) // The top 3 bits are j. j = hi >> floatingbits // Extract the fraction and find its magnitude. hi = hi<<3 | lo>>floatingbits lz := uint(bits.LeadingZeros64(hi)) e := uint64(bias - (lz + 1)) // Clear implicit mantissa bit and shift into place. hi = (hi << (lz + 1)) | (lo >> (32 - (lz + 1))) hi >>= 43 - shift // Include the exponent and convert to a float. hi |= e << shift z = Float32frombits(uint32(hi)) // Map zeros to origin. if j&1 == 1 { j++ j &= 7 z-- } // Multiply the fractional part by pi/4. return j, z * PI4 } // mPi4 is the binary digits of 4/pi as a uint64 array, // that is, 4/pi = Sum mPi4[i]*2^(-64*i) // 19 64-bit digits and the leading one bit give 1217 bits // of precision to handle the largest possible float64 exponent. var mPi4 = [...]uint64{ 0x0000000000000001, 0x45f306dc9c882a53, 0xf84eafa3ea69bb81, 0xb6c52b3278872083, 0xfca2c757bd778ac3, 0x6e48dc74849ba5c0, 0x0c925dd413a32439, 0xfc3bd63962534e7d, 0xd1046bea5d768909, 0xd338e04d68befc82, 0x7323ac7306a673e9, 0x3908bf177bf25076, 0x3ff12fffbc0b301f, 0xde5e2316b414da3e, 0xda6cfd9e4f96136e, 0x9e8c7ecd3cbfd45a, 0xea4f758fd7cbe2f6, 0x7a0e73ef14a525d4, 0xd7f6bf623f1aba10, 0xac06608df8f6d757, } math32-1.11.1/sinhf.go000066400000000000000000000013461467305561300143450ustar00rootroot00000000000000package math32 func Sinh(x float32) float32 { // The coefficients are #2029 from Hart & Cheney. (20.36D) const ( P0 = -0.6307673640497716991184787251e+6 P1 = -0.8991272022039509355398013511e+5 P2 = -0.2894211355989563807284660366e+4 P3 = -0.2630563213397497062819489e+2 Q0 = -0.6307673640497716991212077277e+6 Q1 = 0.1521517378790019070696485176e+5 Q2 = -0.173678953558233699533450911e+3 ) sign := false if x < 0 { x = -x sign = true } var temp float32 switch { case x > 21: temp = Exp(x) * 0.5 case x > 0.5: ex := Exp(x) temp = (ex - 1/ex) * 0.5 default: sq := x * x temp = (((P3*sq+P2)*sq+P1)*sq + P0) * x temp = temp / (((sq+Q2)*sq+Q1)*sq + Q0) } if sign { temp = -temp } return temp } math32-1.11.1/sqrt.go000066400000000000000000000023601467305561300142240ustar00rootroot00000000000000package math32 // Sqrt returns the square root of x. // Special cases are: // Sqrt(+Inf) = +Inf // Sqrt(±0) = ±0 // Sqrt(x < 0) = NaN // Sqrt(NaN) = NaN func Sqrt(x float32) float32 { if haveArchSqrt { return archSqrt(x) } return sqrt(x) } // TODO: add assembly for !build noasm func sqrt(x float32) float32 { // special cases switch { case x == 0 || IsNaN(x) || IsInf(x, 1): return x case x < 0: return NaN() } ix := Float32bits(x) // normalize x exp := int((ix >> shift) & mask) if exp == 0 { // subnormal x for ix&(1<>= 1 // exp = exp/2, exponent of square root // generate sqrt(x) bit by bit ix <<= 1 var q, s uint32 // q = sqrt(x) r := uint32(1 << (shift + 1)) // r = moving bit from MSB to LSB for r != 0 { t := s + r if t <= ix { s = t + r ix -= t q += r } ix <<= 1 r >>= 1 } // final rounding if ix != 0 { // remainder, result not exact q += q & 1 // round according to extra bit } ix = q>>1 + uint32(exp-1+bias)< 2**49 = 5.6e14. // [Accuracy loss statement from sin.go comments.] // // Cephes Math Library Release 2.8: June, 2000 // Copyright 1984, 1987, 1989, 1992, 2000 by Stephen L. Moshier // // The readme file at http://netlib.sandia.gov/cephes/ says: // Some software in this archive may be from the book _Methods and // Programs for Mathematical Functions_ (Prentice-Hall or Simon & Schuster // International, 1989) or from the Cephes Mathematical Library, a // commercial product. In either event, it is copyrighted by the author. // What you see here may be used freely but it comes with no support or // guarantee. // // The two known misprints in the book are repaired here in the // source listings for the gamma function and the incomplete beta // integral. // // Stephen L. Moshier // moshier@na-net.ornl.gov // tan coefficients var _tanP = [...]float32{ -1.30936939181383777646e4, // 0xc0c992d8d24f3f38 1.15351664838587416140e6, // 0x413199eca5fc9ddd -1.79565251976484877988e7, // 0xc1711fead3299176 } var _tanQ = [...]float32{ 1.00000000000000000000e0, 1.36812963470692954678e4, //0x40cab8a5eeb36572 -1.32089234440210967447e6, //0xc13427bc582abc96 2.50083801823357915839e7, //0x4177d98fc2ead8ef -5.38695755929454629881e7, //0xc189afe03cbe5a31 } func Tan(x float32) float32 { return tan(x) } func tan(x float32) float32 { const ( PI4A = 7.85398125648498535156e-1 // 0x3fe921fb40000000, Pi/4 split into three parts PI4B = 3.77489470793079817668e-8 // 0x3e64442d00000000, PI4C = 2.69515142907905952645e-15 // 0x3ce8469898cc5170, ) // special cases switch { case x == 0 || IsNaN(x): return x // return ±0 || NaN() case IsInf(x, 0): return NaN() } // make argument positive but save the sign sign := false if x < 0 { x = -x sign = true } var j uint64 var y, z float32 if x >= reduceThreshold { j, z = trigReduce(x) } else { j = uint64(x * (4 / Pi)) // integer part of x/(Pi/4), as integer for tests on the phase angle y = float32(j) // integer part of x/(Pi/4), as float /* map zeros and singularities to origin */ if j&1 == 1 { j++ y++ } z = ((x - y*PI4A) - y*PI4B) - y*PI4C } zz := z * z if zz > 1e-14 { y = z + z*(zz*(((_tanP[0]*zz)+_tanP[1])*zz+_tanP[2])/((((zz+_tanQ[1])*zz+_tanQ[2])*zz+_tanQ[3])*zz+_tanQ[4])) } else { y = z } if j&2 == 2 { y = -1 / y } if sign { y = -y } return y } math32-1.11.1/tanh.go000066400000000000000000000027341467305561300141720ustar00rootroot00000000000000package math32 // The original C code, the long comment, and the constants // below were from http://netlib.sandia.gov/cephes/cmath/tanh.c, // available from http://www.netlib.org/cephes/single.tgz. // The go code is a simplified version of the original C. // tanhf.c // // Hyperbolic tangent // // // // SYNOPSIS: // // float x, y, tanhf(); // // y = tanhf( x ); // // // // DESCRIPTION: // // Returns hyperbolic tangent of argument in the range MINLOG to // MAXLOG. // // A polynomial approximation is used for |x| < 0.625. // Otherwise, // // tanh(x) = sinh(x)/cosh(x) = 1 - 2/(exp(2x) + 1). // // // // ACCURACY: // // Relative error: // arithmetic domain # trials peak rms // IEEE -2,2 100000 1.3e-7 2.6e-8 // // /* Cephes Math Library Release 2.2: June, 1992 Copyright 1984, 1987, 1989, 1992 by Stephen L. Moshier Direct inquiries to 30 Frost Street, Cambridge, MA 02140 */ /* Single precision hyperbolic tangent * test interval: [-0.625, +0.625] * trials: 10000 * peak relative error: 7.2e-8 * rms relative error: 2.6e-8 */ func Tanh(x float32) float32 { const MAXLOG = 88.02969187150841 z := Abs(x) switch { case z > 0.5*MAXLOG: if x < 0 { return -1 } return 1 case z >= 0.625: s := Exp(z + z) z = 1 - 2/(s+1) if x < 0 { z = -z } default: if x == 0 { return x } s := x * x z = ((((-5.70498872745E-3*s+2.06390887954E-2)*s-5.37397155531E-2)*s+1.33314422036E-1)*s-3.33332819422E-1)*s*x + x } return z } math32-1.11.1/unsafe.go000066400000000000000000000015351467305561300145170ustar00rootroot00000000000000package math32 import "unsafe" // Float32bits returns the IEEE 754 binary representation of f. func Float32bits(f float32) uint32 { return *(*uint32)(unsafe.Pointer(&f)) } // Float32frombits returns the floating point number corresponding // to the IEEE 754 binary representation b. func Float32frombits(b uint32) float32 { return *(*float32)(unsafe.Pointer(&b)) } // Float64bits returns the IEEE 754 binary representation of f. func Float64bits(f float64) uint64 { return *(*uint64)(unsafe.Pointer(&f)) } // Float64frombits returns the floating point number corresponding // the IEEE 754 binary representation b. func Float64frombits(b uint64) float64 { return *(*float64)(unsafe.Pointer(&b)) } func float32ibits(f float32) int32 { return *(*int32)(unsafe.Pointer(&f)) } func float32fromibits(b int32) float32 { return *(*float32)(unsafe.Pointer(&b)) } math32-1.11.1/y0.go000066400000000000000000000001431467305561300135600ustar00rootroot00000000000000package math32 import "math" func Y0(x float32) float32 { return float32(math.Y0(float64(x))) } math32-1.11.1/y1.go000066400000000000000000000001431467305561300135610ustar00rootroot00000000000000package math32 import "math" func Y1(x float32) float32 { return float32(math.Y1(float64(x))) }