gonum.org/v1/gonum@v0.14.0/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 "gonum.org/v1/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 // ----------------------------------------- 183 // | Use the hardware sqrt if you have one | 184 // ----------------------------------------- 185 // 186 // Method: 187 // 188 // Bit by bit method using integer arithmetic. (Slow, but portable) 189 // 1. Normalization 190 // Scale x to y in [1,4) with even powers of 2: 191 // find an integer k such that 1 <= (y=x*2**(2k)) < 4, then 192 // sqrt(x) = 2**k * sqrt(y) 193 // 2. Bit by bit computation 194 // Let q = sqrt(y) truncated to i bit after binary point (q = 1), 195 // i 0 196 // i+1 2 197 // s = 2*q , and y = 2 * ( y - q ). (1) 198 // i i i i 199 // 200 // To compute q from q , one checks whether 201 // i+1 i 202 // 203 // -(i+1) 2 204 // (q + 2 ) <= y. (2) 205 // i 206 // -(i+1) 207 // If (2) is false, then q = q ; otherwise q = q + 2 . 208 // i+1 i i+1 i 209 // 210 // With some algebraic manipulation, it is not difficult to see 211 // that (2) is equivalent to 212 // -(i+1) 213 // s + 2 <= y (3) 214 // i i 215 // 216 // The advantage of (3) is that s and y can be computed by 217 // i i 218 // the following recurrence formula: 219 // if (3) is false 220 // 221 // s = s , y = y ; (4) 222 // i+1 i i+1 i 223 // 224 // otherwise, 225 // -i -(i+1) 226 // s = s + 2 , y = y - s - 2 (5) 227 // i+1 i i+1 i i 228 // 229 // One may easily use induction to prove (4) and (5). 230 // Note. Since the left hand side of (3) contain only i+2 bits, 231 // it does not necessary to do a full (53-bit) comparison 232 // in (3). 233 // 3. Final rounding 234 // After generating the 53 bits result, we compute one more bit. 235 // Together with the remainder, we can decide whether the 236 // result is exact, bigger than 1/2ulp, or less than 1/2ulp 237 // (it will never equal to 1/2ulp). 238 // The rounding mode can be detected by checking whether 239 // huge + tiny is equal to huge, and whether huge - tiny is 240 // equal to huge for some floating point number "huge" and "tiny". 241 func sqrt(x float32) float32 { 242 // special cases 243 switch { 244 case x == 0 || IsNaN(x) || IsInf(x, 1): 245 return x 246 case x < 0: 247 return NaN() 248 } 249 ix := math.Float32bits(x) 250 // normalize x 251 exp := int((ix >> shift) & mask) 252 if exp == 0 { // subnormal x 253 for ix&1<<shift == 0 { 254 ix <<= 1 255 exp-- 256 } 257 exp++ 258 } 259 exp -= bias // unbias exponent 260 ix &^= mask << shift 261 ix |= 1 << shift 262 if exp&1 == 1 { // odd exp, double x to make it even 263 ix <<= 1 264 } 265 exp >>= 1 // exp = exp/2, exponent of square root 266 // generate sqrt(x) bit by bit 267 ix <<= 1 268 var q, s uint32 // q = sqrt(x) 269 r := uint32(1 << (shift + 1)) // r = moving bit from MSB to LSB 270 for r != 0 { 271 t := s + r 272 if t <= ix { 273 s = t + r 274 ix -= t 275 q += r 276 } 277 ix <<= 1 278 r >>= 1 279 } 280 // final rounding 281 if ix != 0 { // remainder, result not exact 282 q += q & 1 // round according to extra bit 283 } 284 ix = q>>1 + uint32(exp-1+bias)<<shift // significand + biased exponent 285 return math.Float32frombits(ix) 286 } 287 288 func alike(a, b float32) bool { 289 switch { 290 case IsNaN(a) && IsNaN(b): 291 return true 292 case a == b: 293 return Signbit(a) == Signbit(b) 294 } 295 return false 296 }