gonum.org/v1/gonum@v0.14.0/num/quat/exp_test.go (about) 1 // Copyright ©2018 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 quat 6 7 import ( 8 "math" 9 "testing" 10 ) 11 12 var expTests = []struct { 13 q Number 14 want Number 15 }{ 16 {q: Number{}, want: Number{Real: 1}}, 17 // Expected velues below are from pyquaternion. 18 { 19 q: Number{Real: 1, Imag: 1, Jmag: 1, Kmag: 1}, 20 want: Number{Real: -0.43643792124786496, Imag: 1.549040352371697, Jmag: 1.549040352371697, Kmag: 1.549040352371697}, 21 }, 22 { 23 q: Number{Real: 1, Imag: 0, Jmag: 1, Kmag: 1}, 24 want: Number{Real: 0.42389891174348104, Imag: 0, Jmag: 1.8986002490721081, Kmag: 1.8986002490721081}, 25 }, 26 { 27 q: Number{Real: 1, Imag: 0, Jmag: 0, Kmag: 1}, 28 want: Number{Real: 1.4686939399158851, Imag: 0, Jmag: 0, Kmag: 2.2873552871788423}, 29 }, 30 { 31 q: Number{Real: 0, Imag: 1, Jmag: 1, Kmag: 1}, 32 want: Number{Real: -0.16055653857469052, Imag: 0.569860099182514, Jmag: 0.569860099182514, Kmag: 0.569860099182514}, 33 }, 34 { 35 q: Number{Real: 0, Imag: 0, Jmag: 1, Kmag: 1}, 36 want: Number{Real: 0.15594369476537437, Imag: 0, Jmag: 0.6984559986366083, Kmag: 0.6984559986366083}, 37 }, 38 { 39 q: Number{Real: 0, Imag: 0, Jmag: 0, Kmag: 1}, 40 want: Number{Real: 0.5403023058681398, Imag: 0, Jmag: 0, Kmag: 0.8414709848078965}, 41 }, 42 } 43 44 func TestExp(t *testing.T) { 45 t.Parallel() 46 const tol = 1e-14 47 for _, test := range expTests { 48 got := Exp(test.q) 49 if !equalApprox(got, test.want, tol) { 50 t.Errorf("unexpected result for Exp(%v): got:%v want:%v", test.q, got, test.want) 51 } 52 } 53 } 54 55 var logTests = []struct { 56 q Number 57 want Number 58 }{ 59 {q: Number{}, want: Number{Real: -inf}}, 60 // Expected velues below are from pyquaternion. 61 { 62 q: Number{Real: 1, Imag: 1, Jmag: 1, Kmag: 1}, 63 want: Number{Real: 0.6931471805599453, Imag: 0.6045997880780728, Jmag: 0.6045997880780728, Kmag: 0.6045997880780728}, 64 }, 65 { 66 q: Number{Real: 1, Imag: 0, Jmag: 1, Kmag: 1}, 67 want: Number{Real: 0.5493061443340548, Imag: 0, Jmag: 0.6755108588560398, Kmag: 0.6755108588560398}, 68 }, 69 { 70 q: Number{Real: 1, Imag: 0, Jmag: 0, Kmag: 1}, 71 want: Number{Real: 0.3465735902799727, Imag: 0, Jmag: 0, Kmag: 0.7853981633974484}, 72 }, 73 { 74 q: Number{Real: 0, Imag: 1, Jmag: 1, Kmag: 1}, 75 want: Number{Real: 0.5493061443340548, Imag: 0.906899682117109, Jmag: 0.906899682117109, Kmag: 0.906899682117109}, 76 }, 77 { 78 q: Number{Real: 0, Imag: 0, Jmag: 1, Kmag: 1}, 79 want: Number{Real: 0.3465735902799727, Imag: 0, Jmag: 1.1107207345395915, Kmag: 1.1107207345395915}, 80 }, 81 { 82 q: Number{Real: 0, Imag: 0, Jmag: 0, Kmag: 1}, 83 want: Number{Real: 0, Imag: 0, Jmag: 0, Kmag: 1.5707963267948966}, 84 }, 85 } 86 87 func TestLog(t *testing.T) { 88 t.Parallel() 89 const tol = 1e-14 90 for _, test := range logTests { 91 got := Log(test.q) 92 if !equalApprox(got, test.want, tol) { 93 t.Errorf("unexpected result for Log(%v): got:%v want:%v", test.q, got, test.want) 94 } 95 } 96 } 97 98 var powTests = []struct { 99 q, r Number 100 want Number 101 }{ 102 {q: Number{}, r: Number{}, want: Number{Real: 1}}, 103 // Expected velues below are from pyquaternion. 104 // pyquaternion does not support quaternion powers. 105 // TODO(kortschak): Add non-real r cases. 106 { 107 q: Number{Real: 1, Imag: 1, Jmag: 1, Kmag: 1}, r: Number{Real: 2}, 108 want: Number{Real: -2, Imag: 2, Jmag: 2, Kmag: 2}, 109 }, 110 { 111 q: Number{Real: 1, Imag: 0, Jmag: 1, Kmag: 1}, r: Number{Real: 2}, 112 want: Number{Real: -1, Imag: 0, Jmag: 2, Kmag: 2}, 113 }, 114 { 115 q: Number{Real: 1, Imag: 0, Jmag: 0, Kmag: 1}, r: Number{Real: 2}, 116 want: Number{Real: 0, Imag: 0, Jmag: 0, Kmag: 2}, 117 }, 118 { 119 q: Number{Real: 0, Imag: 1, Jmag: 1, Kmag: 1}, r: Number{Real: 2}, 120 want: Number{Real: -3, Imag: 0, Jmag: 0, Kmag: 0}, 121 }, 122 { 123 q: Number{Real: 0, Imag: 0, Jmag: 1, Kmag: 1}, r: Number{Real: 2}, 124 want: Number{Real: -2, Imag: 0, Jmag: 0, Kmag: 0}, 125 }, 126 { 127 q: Number{Real: 0, Imag: 0, Jmag: 0, Kmag: 1}, r: Number{Real: 2}, 128 want: Number{Real: -1, Imag: 0, Jmag: 0, Kmag: 0}, 129 }, 130 131 { 132 q: Number{Real: 1, Imag: 1, Jmag: 1, Kmag: 1}, r: Number{Real: math.Pi}, 133 want: Number{Real: -8.728144138959564, Imag: -0.7527136547040768, Jmag: -0.7527136547040768, Kmag: -0.7527136547040768}, 134 }, 135 { 136 q: Number{Real: 1, Imag: 0, Jmag: 1, Kmag: 1}, r: Number{Real: math.Pi}, 137 want: Number{Real: -5.561182514695044, Imag: 0, Jmag: 0.5556661490713818, Kmag: 0.5556661490713818}, 138 }, 139 { 140 q: Number{Real: 1, Imag: 0, Jmag: 0, Kmag: 1}, r: Number{Real: math.Pi}, 141 want: Number{Real: -2.320735561810013, Imag: 0, Jmag: 0, Kmag: 1.8544983901925216}, 142 }, 143 { 144 q: Number{Real: 0, Imag: 1, Jmag: 1, Kmag: 1}, r: Number{Real: math.Pi}, 145 want: Number{Real: 1.2388947209955585, Imag: -3.162774128856231, Jmag: -3.162774128856231, Kmag: -3.162774128856231}, 146 }, 147 { 148 q: Number{Real: 0, Imag: 0, Jmag: 1, Kmag: 1}, r: Number{Real: math.Pi}, 149 want: Number{Real: 0.6552860151073727, Imag: 0, Jmag: -2.0488506614051922, Kmag: -2.0488506614051922}, 150 }, 151 { 152 q: Number{Real: 0, Imag: 0, Jmag: 0, Kmag: 1}, r: Number{Real: math.Pi}, 153 want: Number{Real: 0.22058404074969779, Imag: 0, Jmag: 0, Kmag: -0.9753679720836315}, 154 }, 155 156 { 157 q: Number{Real: 1, Imag: 1, Jmag: 1, Kmag: 1}, r: Number{Real: 3}, 158 want: Number{Real: -8, Imag: 0, Jmag: 0, Kmag: 0}, 159 }, 160 { 161 q: Number{Real: 1, Imag: 0, Jmag: 1, Kmag: 1}, r: Number{Real: 3}, 162 want: Number{Real: -5, Imag: 0, Jmag: 1, Kmag: 1}, 163 }, 164 { 165 q: Number{Real: 1, Imag: 0, Jmag: 0, Kmag: 1}, r: Number{Real: 3}, 166 want: Number{Real: -2, Imag: 0, Jmag: 0, Kmag: 2}, 167 }, 168 { 169 q: Number{Real: 0, Imag: 1, Jmag: 1, Kmag: 1}, r: Number{Real: 3}, 170 want: Number{Real: 0, Imag: -3, Jmag: -3, Kmag: -3}, 171 }, 172 { 173 q: Number{Real: 0, Imag: 0, Jmag: 1, Kmag: 1}, r: Number{Real: 3}, 174 want: Number{Real: 0, Imag: 0, Jmag: -2, Kmag: -2}, 175 }, 176 { 177 q: Number{Real: 0, Imag: 0, Jmag: 0, Kmag: 1}, r: Number{Real: 3}, 178 want: Number{Real: 0, Imag: 0, Jmag: 0, Kmag: -1}, 179 }, 180 } 181 182 func TestPow(t *testing.T) { 183 t.Parallel() 184 const tol = 1e-14 185 for _, test := range powTests { 186 got := Pow(test.q, test.r) 187 if !equalApprox(got, test.want, tol) { 188 t.Errorf("unexpected result for Pow(%v, %v): got:%v want:%v", test.q, test.r, got, test.want) 189 } 190 } 191 } 192 193 var powRealTests = []struct { 194 q Number 195 r float64 196 want Number 197 }{ 198 {q: Number{}, r: 0, want: Number{Real: 1}}, 199 { 200 q: Number{Real: 1, Imag: 1, Jmag: 1, Kmag: 1}, r: 2, 201 want: Number{Real: -2, Imag: 2, Jmag: 2, Kmag: 2}, 202 }, 203 { 204 q: Number{Real: 1, Imag: 0, Jmag: 1, Kmag: 1}, r: 2, 205 want: Number{Real: -1, Imag: 0, Jmag: 2, Kmag: 2}, 206 }, 207 { 208 q: Number{Real: 1, Imag: 0, Jmag: 0, Kmag: 1}, r: 2, 209 want: Number{Real: 0, Imag: 0, Jmag: 0, Kmag: 2}, 210 }, 211 { 212 q: Number{Real: 0, Imag: 1, Jmag: 1, Kmag: 1}, r: 2, 213 want: Number{Real: -3, Imag: 0, Jmag: 0, Kmag: 0}, 214 }, 215 { 216 q: Number{Real: 0, Imag: 0, Jmag: 1, Kmag: 1}, r: 2, 217 want: Number{Real: -2, Imag: 0, Jmag: 0, Kmag: 0}, 218 }, 219 { 220 q: Number{Real: 0, Imag: 0, Jmag: 0, Kmag: 1}, r: 2, 221 want: Number{Real: -1, Imag: 0, Jmag: 0, Kmag: 0}, 222 }, 223 224 { 225 q: Number{Real: 1, Imag: 1, Jmag: 1, Kmag: 1}, r: math.Pi, 226 want: Number{Real: -8.728144138959564, Imag: -0.7527136547040768, Jmag: -0.7527136547040768, Kmag: -0.7527136547040768}, 227 }, 228 { 229 q: Number{Real: 1, Imag: 0, Jmag: 1, Kmag: 1}, r: math.Pi, 230 want: Number{Real: -5.561182514695044, Imag: 0, Jmag: 0.5556661490713818, Kmag: 0.5556661490713818}, 231 }, 232 { 233 q: Number{Real: 1, Imag: 0, Jmag: 0, Kmag: 1}, r: math.Pi, 234 want: Number{Real: -2.320735561810013, Imag: 0, Jmag: 0, Kmag: 1.8544983901925216}, 235 }, 236 { 237 q: Number{Real: 0, Imag: 1, Jmag: 1, Kmag: 1}, r: math.Pi, 238 want: Number{Real: 1.2388947209955585, Imag: -3.162774128856231, Jmag: -3.162774128856231, Kmag: -3.162774128856231}, 239 }, 240 { 241 q: Number{Real: 0, Imag: 0, Jmag: 1, Kmag: 1}, r: math.Pi, 242 want: Number{Real: 0.6552860151073727, Imag: 0, Jmag: -2.0488506614051922, Kmag: -2.0488506614051922}, 243 }, 244 { 245 q: Number{Real: 0, Imag: 0, Jmag: 0, Kmag: 1}, r: math.Pi, 246 want: Number{Real: 0.22058404074969779, Imag: 0, Jmag: 0, Kmag: -0.9753679720836315}, 247 }, 248 249 { 250 q: Number{Real: 1, Imag: 1, Jmag: 1, Kmag: 1}, r: 3, 251 want: Number{Real: -8, Imag: 0, Jmag: 0, Kmag: 0}, 252 }, 253 { 254 q: Number{Real: 1, Imag: 0, Jmag: 1, Kmag: 1}, r: 3, 255 want: Number{Real: -5, Imag: 0, Jmag: 1, Kmag: 1}, 256 }, 257 { 258 q: Number{Real: 1, Imag: 0, Jmag: 0, Kmag: 1}, r: 3, 259 want: Number{Real: -2, Imag: 0, Jmag: 0, Kmag: 2}, 260 }, 261 { 262 q: Number{Real: 0, Imag: 1, Jmag: 1, Kmag: 1}, r: 3, 263 want: Number{Real: 0, Imag: -3, Jmag: -3, Kmag: -3}, 264 }, 265 { 266 q: Number{Real: 0, Imag: 0, Jmag: 1, Kmag: 1}, r: 3, 267 want: Number{Real: 0, Imag: 0, Jmag: -2, Kmag: -2}, 268 }, 269 { 270 q: Number{Real: 0, Imag: 0, Jmag: 0, Kmag: 1}, r: 3, 271 want: Number{Real: 0, Imag: 0, Jmag: 0, Kmag: -1}, 272 }, 273 } 274 275 func TestRealPow(t *testing.T) { 276 t.Parallel() 277 const tol = 1e-14 278 for _, test := range powRealTests { 279 got := PowReal(test.q, test.r) 280 if !equalApprox(got, test.want, tol) { 281 t.Errorf("unexpected result for Pow(%v, %v): got:%v want:%v", test.q, test.r, got, test.want) 282 } 283 } 284 } 285 286 var sqrtTests = []struct { 287 q Number 288 want Number 289 }{ 290 {q: Number{}, want: Number{}}, 291 // Expected velues below are from pyquaternion. 292 { 293 q: Number{Real: 1, Imag: 1, Jmag: 1, Kmag: 1}, 294 want: Number{Real: 1.2247448713915892, Imag: 0.4082482904638631, Jmag: 0.4082482904638631, Kmag: 0.4082482904638631}, 295 }, 296 { 297 q: Number{Real: 1, Imag: 0, Jmag: 1, Kmag: 1}, 298 want: Number{Real: 1.1687708944803676, Imag: 0, Jmag: 0.42779983858367593, Kmag: 0.42779983858367593}, 299 }, 300 { 301 q: Number{Real: 1, Imag: 0, Jmag: 0, Kmag: 1}, 302 want: Number{Real: 1.0986841134678098, Imag: 0, Jmag: 0, Kmag: 0.45508986056222733}, 303 }, 304 { 305 q: Number{Real: 0, Imag: 1, Jmag: 1, Kmag: 1}, 306 want: Number{Real: 0.9306048591020996, Imag: 0.5372849659117709, Jmag: 0.5372849659117709, Kmag: 0.5372849659117709}, 307 }, 308 { 309 q: Number{Real: 0, Imag: 0, Jmag: 1, Kmag: 1}, 310 want: Number{Real: 0.8408964152537146, Imag: 0, Jmag: 0.5946035575013604, Kmag: 0.5946035575013604}, 311 }, 312 { 313 q: Number{Real: 0, Imag: 0, Jmag: 0, Kmag: 1}, 314 want: Number{Real: 0.7071067811865476, Imag: 0, Jmag: 0, Kmag: 0.7071067811865475}, 315 }, 316 } 317 318 func TestSqrt(t *testing.T) { 319 t.Parallel() 320 const tol = 1e-14 321 for _, test := range sqrtTests { 322 got := Sqrt(test.q) 323 if !equalApprox(got, test.want, tol) { 324 t.Errorf("unexpected result for Sqrt(%v): got:%v want:%v", test.q, got, test.want) 325 } 326 } 327 }