github.com/gopherd/gonum@v0.0.4/internal/math32/math_test.go (about) 1 // Copyright ©2015 The Gonum Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package math32 6 7 import ( 8 "math" 9 "testing" 10 "testing/quick" 11 12 "github.com/gopherd/gonum/floats/scalar" 13 ) 14 15 const tol = 1e-7 16 17 func TestAbs(t *testing.T) { 18 f := func(x float32) bool { 19 y := Abs(x) 20 return y == float32(math.Abs(float64(x))) 21 } 22 if err := quick.Check(f, nil); err != nil { 23 t.Error(err) 24 } 25 } 26 27 func TestCopySign(t *testing.T) { 28 f := func(x struct{ X, Y float32 }) bool { 29 y := Copysign(x.X, x.Y) 30 return y == float32(math.Copysign(float64(x.X), float64(x.Y))) 31 } 32 if err := quick.Check(f, nil); err != nil { 33 t.Error(err) 34 } 35 } 36 37 func TestHypot(t *testing.T) { 38 // tol is increased for Hypot to avoid failures 39 // related to https://github.com/gonum/gonum/issues/110. 40 const tol = 1e-6 41 f := func(x struct{ X, Y float32 }) bool { 42 y := Hypot(x.X, x.Y) 43 if math.Hypot(float64(x.X), float64(x.Y)) > math.MaxFloat32 { 44 return true 45 } 46 return scalar.EqualWithinRel(float64(y), math.Hypot(float64(x.X), float64(x.Y)), tol) 47 } 48 if err := quick.Check(f, nil); err != nil { 49 t.Error(err) 50 } 51 } 52 53 func TestInf(t *testing.T) { 54 if float64(Inf(1)) != math.Inf(1) || float64(Inf(-1)) != math.Inf(-1) { 55 t.Error("float32(inf) not infinite") 56 } 57 } 58 59 func TestIsInf(t *testing.T) { 60 posInf := float32(math.Inf(1)) 61 negInf := float32(math.Inf(-1)) 62 if !IsInf(posInf, 0) || !IsInf(negInf, 0) || !IsInf(posInf, 1) || !IsInf(negInf, -1) || IsInf(posInf, -1) || IsInf(negInf, 1) { 63 t.Error("unexpected isInf value") 64 } 65 f := func(x struct { 66 F float32 67 Sign int 68 }) bool { 69 y := IsInf(x.F, x.Sign) 70 return y == math.IsInf(float64(x.F), x.Sign) 71 } 72 if err := quick.Check(f, nil); err != nil { 73 t.Error(err) 74 } 75 } 76 77 func TestIsNaN(t *testing.T) { 78 f := func(x float32) bool { 79 y := IsNaN(x) 80 return y == math.IsNaN(float64(x)) 81 } 82 if err := quick.Check(f, nil); err != nil { 83 t.Error(err) 84 } 85 } 86 87 func TestMax(t *testing.T) { 88 values := []float32{ 89 Inf(-1), 90 -12.34, 91 -1, 92 Copysign(0, -1), 93 0, 94 1, 95 12.34, 96 Inf(1), 97 NaN(), 98 } 99 for _, v1 := range values { 100 for _, v2 := range values { 101 got := Max(v1, v2) 102 want := float32(math.Max(float64(v1), float64(v2))) 103 if !alike(got, want) { 104 t.Errorf("Max(%v, %v) = %v, want %v", v1, v2, got, want) 105 } 106 } 107 } 108 } 109 110 func TestMin(t *testing.T) { 111 values := []float32{ 112 Inf(-1), 113 -12.34, 114 -1, 115 Copysign(0, -1), 116 0, 117 1, 118 12.34, 119 Inf(1), 120 NaN(), 121 } 122 for _, v1 := range values { 123 for _, v2 := range values { 124 got := Min(v1, v2) 125 want := float32(math.Min(float64(v1), float64(v2))) 126 if !alike(got, want) { 127 t.Errorf("Min(%v, %v) = %v, want %v", v1, v2, got, want) 128 } 129 } 130 } 131 } 132 133 func TestNaN(t *testing.T) { 134 if !math.IsNaN(float64(NaN())) { 135 t.Errorf("float32(nan) is a number: %f", NaN()) 136 } 137 } 138 139 func TestSignbit(t *testing.T) { 140 f := func(x float32) bool { 141 return Signbit(x) == math.Signbit(float64(x)) 142 } 143 if err := quick.Check(f, nil); err != nil { 144 t.Error(err) 145 } 146 } 147 148 func TestSqrt(t *testing.T) { 149 f := func(x float32) bool { 150 y := Sqrt(x) 151 if IsNaN(y) && IsNaN(sqrt(x)) { 152 return true 153 } 154 return scalar.EqualWithinRel(float64(y), float64(sqrt(x)), tol) 155 } 156 if err := quick.Check(f, nil); err != nil { 157 t.Error(err) 158 } 159 } 160 161 // Copyright 2009 The Go Authors. All rights reserved. 162 // Use of this source code is governed by a BSD-style 163 // license that can be found in the LICENSE file. 164 165 // The original C code and the long comment below are 166 // from FreeBSD's /usr/src/lib/msun/src/e_sqrt.c and 167 // came with this notice. The go code is a simplified 168 // version of the original C. 169 // 170 // ==================================================== 171 // Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. 172 // 173 // Developed at SunPro, a Sun Microsystems, Inc. business. 174 // Permission to use, copy, modify, and distribute this 175 // software is freely granted, provided that this notice 176 // is preserved. 177 // ==================================================== 178 // 179 // __ieee754_sqrt(x) 180 // Return correctly rounded sqrt. 181 // ----------------------------------------- 182 // | Use the hardware sqrt if you have one | 183 // ----------------------------------------- 184 // Method: 185 // Bit by bit method using integer arithmetic. (Slow, but portable) 186 // 1. Normalization 187 // Scale x to y in [1,4) with even powers of 2: 188 // find an integer k such that 1 <= (y=x*2**(2k)) < 4, then 189 // sqrt(x) = 2**k * sqrt(y) 190 // 2. Bit by bit computation 191 // Let q = sqrt(y) truncated to i bit after binary point (q = 1), 192 // i 0 193 // i+1 2 194 // s = 2*q , and y = 2 * ( y - q ). (1) 195 // i i i i 196 // 197 // To compute q from q , one checks whether 198 // i+1 i 199 // 200 // -(i+1) 2 201 // (q + 2 ) <= y. (2) 202 // i 203 // -(i+1) 204 // If (2) is false, then q = q ; otherwise q = q + 2 . 205 // i+1 i i+1 i 206 // 207 // With some algebraic manipulation, it is not difficult to see 208 // that (2) is equivalent to 209 // -(i+1) 210 // s + 2 <= y (3) 211 // i i 212 // 213 // The advantage of (3) is that s and y can be computed by 214 // i i 215 // the following recurrence formula: 216 // if (3) is false 217 // 218 // s = s , y = y ; (4) 219 // i+1 i i+1 i 220 // 221 // otherwise, 222 // -i -(i+1) 223 // s = s + 2 , y = y - s - 2 (5) 224 // i+1 i i+1 i i 225 // 226 // One may easily use induction to prove (4) and (5). 227 // Note. Since the left hand side of (3) contain only i+2 bits, 228 // it does not necessary to do a full (53-bit) comparison 229 // in (3). 230 // 3. Final rounding 231 // After generating the 53 bits result, we compute one more bit. 232 // Together with the remainder, we can decide whether the 233 // result is exact, bigger than 1/2ulp, or less than 1/2ulp 234 // (it will never equal to 1/2ulp). 235 // The rounding mode can be detected by checking whether 236 // huge + tiny is equal to huge, and whether huge - tiny is 237 // equal to huge for some floating point number "huge" and "tiny". 238 // 239 func sqrt(x float32) float32 { 240 // special cases 241 switch { 242 case x == 0 || IsNaN(x) || IsInf(x, 1): 243 return x 244 case x < 0: 245 return NaN() 246 } 247 ix := math.Float32bits(x) 248 // normalize x 249 exp := int((ix >> shift) & mask) 250 if exp == 0 { // subnormal x 251 for ix&1<<shift == 0 { 252 ix <<= 1 253 exp-- 254 } 255 exp++ 256 } 257 exp -= bias // unbias exponent 258 ix &^= mask << shift 259 ix |= 1 << shift 260 if exp&1 == 1 { // odd exp, double x to make it even 261 ix <<= 1 262 } 263 exp >>= 1 // exp = exp/2, exponent of square root 264 // generate sqrt(x) bit by bit 265 ix <<= 1 266 var q, s uint32 // q = sqrt(x) 267 r := uint32(1 << (shift + 1)) // r = moving bit from MSB to LSB 268 for r != 0 { 269 t := s + r 270 if t <= ix { 271 s = t + r 272 ix -= t 273 q += r 274 } 275 ix <<= 1 276 r >>= 1 277 } 278 // final rounding 279 if ix != 0 { // remainder, result not exact 280 q += q & 1 // round according to extra bit 281 } 282 ix = q>>1 + uint32(exp-1+bias)<<shift // significand + biased exponent 283 return math.Float32frombits(ix) 284 } 285 286 func alike(a, b float32) bool { 287 switch { 288 case IsNaN(a) && IsNaN(b): 289 return true 290 case a == b: 291 return Signbit(a) == Signbit(b) 292 } 293 return false 294 }