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  }