1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package r3
16
17 import (
18 "math/big"
19 "testing"
20 )
21
22
23 func preciseEq(a, b *big.Float) bool {
24 return a.SetPrec(prec).Cmp(b.SetPrec(prec)) == 0
25 }
26
27 func TestPreciseRoundtrip(t *testing.T) {
28 tests := []struct {
29 v Vector
30 }{
31 {Vector{0, 0, 0}},
32 {Vector{1, 2, 3}},
33 {Vector{3, -4, 12}},
34 {Vector{1, 1e-16, 1e-32}},
35 }
36
37 for _, test := range tests {
38 if got, want := PreciseVectorFromVector(test.v).Vector(), test.v.Normalize(); !got.ApproxEqual(want) {
39 t.Errorf("PreciseVectorFromVector(%v).Vector() = %v, want %v", test.v, got, want)
40 }
41 }
42 }
43
44 func TestPreciseIsUnit(t *testing.T) {
45 const epsilon = 1e-14
46 tests := []struct {
47 v PreciseVector
48 want bool
49 }{
50 {
51 v: NewPreciseVector(0, 0, 0),
52 want: false,
53 },
54 {
55 v: NewPreciseVector(1, 0, 0),
56 want: true,
57 },
58 {
59 v: NewPreciseVector(0, 1, 0),
60 want: true,
61 },
62 {
63 v: NewPreciseVector(0, 0, 1),
64 want: true,
65 },
66 {
67 v: NewPreciseVector(1+2*epsilon, 0, 0),
68 want: false,
69 },
70 {
71 v: NewPreciseVector(0*(1+epsilon), 0, 0),
72 want: false,
73 },
74 {
75 v: NewPreciseVector(1, 1, 1),
76 want: false,
77 },
78 }
79
80 for _, test := range tests {
81 if got := test.v.IsUnit(); got != test.want {
82 t.Errorf("%v.IsUnit() = %v, want %v", test.v, got, test.want)
83 }
84 }
85 }
86
87 func TestPreciseNorm2(t *testing.T) {
88 tests := []struct {
89 v PreciseVector
90 want *big.Float
91 }{
92 {
93 v: NewPreciseVector(0, 0, 0),
94 want: precise0,
95 },
96 {
97 v: NewPreciseVector(0, 1, 0),
98 want: precise1,
99 },
100 {
101 v: NewPreciseVector(1, 1, 1),
102 want: precStr("3"),
103 },
104 {
105 v: NewPreciseVector(1, 2, 3),
106 want: precStr("14"),
107 },
108 {
109 v: NewPreciseVector(3, -4, 12),
110 want: precStr("169"),
111 },
112 }
113
114 for _, test := range tests {
115 if got := test.v.Norm2(); !preciseEq(got, test.want) {
116 t.Errorf("%v.Norm2() = %v, want %v", test.v, test.v.Norm2(), test.want)
117 }
118 }
119 }
120
121 func TestPreciseAdd(t *testing.T) {
122 tests := []struct {
123 v1, v2, want PreciseVector
124 }{
125 {
126 v1: NewPreciseVector(0, 0, 0),
127 v2: NewPreciseVector(0, 0, 0),
128 want: NewPreciseVector(0, 0, 0),
129 },
130 {
131 v1: NewPreciseVector(1, 0, 0),
132 v2: NewPreciseVector(0, 0, 0),
133 want: NewPreciseVector(1, 0, 0),
134 },
135 {
136 v1: NewPreciseVector(1, 2, 3),
137 v2: NewPreciseVector(4, 5, 7),
138 want: NewPreciseVector(5, 7, 10),
139 },
140 {
141 v1: NewPreciseVector(1, -3, 5),
142 v2: NewPreciseVector(1, -6, -6),
143 want: NewPreciseVector(2, -9, -1),
144 },
145 }
146
147 for _, test := range tests {
148 if got := test.v1.Add(test.v2); !got.Equal(test.want) {
149 t.Errorf("%v + %v = %v, want %v", test.v1, test.v2, got, test.want)
150 }
151 }
152 }
153
154 func TestPreciseSub(t *testing.T) {
155 tests := []struct {
156 v1, v2, want PreciseVector
157 }{
158 {
159 v1: NewPreciseVector(0, 0, 0),
160 v2: NewPreciseVector(0, 0, 0),
161 want: NewPreciseVector(0, 0, 0),
162 },
163 {
164 v1: NewPreciseVector(1, 0, 0),
165 v2: NewPreciseVector(0, 0, 0),
166 want: NewPreciseVector(1, 0, 0),
167 },
168 {
169 v1: NewPreciseVector(1, 2, 3),
170 v2: NewPreciseVector(4, 5, 7),
171 want: NewPreciseVector(-3, -3, -4),
172 },
173 {
174 v1: NewPreciseVector(1, -3, 5),
175 v2: NewPreciseVector(1, -6, -6),
176 want: NewPreciseVector(0, 3, 11),
177 },
178 }
179
180 for _, test := range tests {
181 if got := test.v1.Sub(test.v2); !got.Equal(test.want) {
182 t.Errorf("%v - %v = %v, want %v", test.v1, test.v2, got, test.want)
183 }
184 }
185 }
186
187 func TestPreciseMul(t *testing.T) {
188 tests := []struct {
189 v PreciseVector
190 f *big.Float
191 want PreciseVector
192 }{
193 {
194 v: NewPreciseVector(0, 0, 0),
195 f: precFloat(3),
196 want: NewPreciseVector(0, 0, 0),
197 },
198 {
199 v: NewPreciseVector(1, 0, 0),
200 f: precFloat(1),
201 want: NewPreciseVector(1, 0, 0),
202 },
203 {
204 v: NewPreciseVector(1, 0, 0),
205 f: precFloat(0),
206 want: NewPreciseVector(0, 0, 0),
207 },
208 {
209 v: NewPreciseVector(1, 0, 0),
210 f: precFloat(3),
211 want: NewPreciseVector(3, 0, 0),
212 },
213 {
214 v: NewPreciseVector(1, -3, 5),
215 f: precFloat(-1),
216 want: NewPreciseVector(-1, 3, -5),
217 },
218 {
219 v: NewPreciseVector(1, -3, 5),
220 f: precFloat(2),
221 want: NewPreciseVector(2, -6, 10),
222 },
223 }
224
225 for _, test := range tests {
226 if got := test.v.Mul(test.f); !got.Equal(test.want) {
227 t.Errorf("%v.Mul(%v) = %v, want %v", test.v, test.f, got, test.want)
228 }
229 }
230 }
231
232 func TestPreciseMulByFloat64(t *testing.T) {
233 tests := []struct {
234 v PreciseVector
235 f float64
236 want PreciseVector
237 }{
238 {
239 v: NewPreciseVector(0, 0, 0),
240 f: 3,
241 want: NewPreciseVector(0, 0, 0),
242 },
243 {
244 v: NewPreciseVector(1, 0, 0),
245 f: 1,
246 want: NewPreciseVector(1, 0, 0),
247 },
248 {
249 v: NewPreciseVector(1, 0, 0),
250 f: 0,
251 want: NewPreciseVector(0, 0, 0),
252 },
253 {
254 v: NewPreciseVector(1, 0, 0),
255 f: 3,
256 want: NewPreciseVector(3, 0, 0),
257 },
258 {
259 v: NewPreciseVector(1, -3, 5),
260 f: -1,
261 want: NewPreciseVector(-1, 3, -5),
262 },
263 {
264 v: NewPreciseVector(1, -3, 5),
265 f: 2,
266 want: NewPreciseVector(2, -6, 10),
267 },
268 }
269
270 for _, test := range tests {
271 if got := test.v.MulByFloat64(test.f); !got.Equal(test.want) {
272 t.Errorf("%v.MulByFloat64(%v) = %v, want %v", test.v, test.f, got, test.want)
273 }
274 }
275 }
276
277 func TestPreciseDot(t *testing.T) {
278 tests := []struct {
279 v1, v2 PreciseVector
280 want *big.Float
281 }{
282 {
283
284 v1: NewPreciseVector(1, 0, 0),
285 v2: NewPreciseVector(1, 0, 0),
286 want: precise1,
287 },
288 {
289
290 v1: NewPreciseVector(0, 1, 0),
291 v2: NewPreciseVector(0, 1, 0),
292 want: precise1,
293 },
294 {
295
296 v1: NewPreciseVector(0, 0, 1),
297 v2: NewPreciseVector(0, 0, 1),
298 want: precise1,
299 },
300 {
301
302 v1: NewPreciseVector(1, 0, 0),
303 v2: NewPreciseVector(0, 1, 0),
304 want: precise0,
305 },
306 {
307
308 v1: NewPreciseVector(1, 0, 0),
309 v2: NewPreciseVector(0, 1, 1),
310 want: precise0,
311 },
312 {
313 v1: NewPreciseVector(1, 1, 1),
314 v2: NewPreciseVector(-1, -1, -1),
315 want: precStr("-3"),
316 },
317 }
318
319 for _, test := range tests {
320 if got := test.v1.Dot(test.v2); !preciseEq(got, test.want) {
321 t.Errorf("%v · %v = %v, want %v", test.v1, test.v2, got, test.want)
322 }
323 if got := test.v2.Dot(test.v1); !preciseEq(got, test.want) {
324 t.Errorf("%v · %v = %v, want %v", test.v2, test.v1, got, test.want)
325 }
326 }
327 }
328
329 func TestPreciseCross(t *testing.T) {
330 tests := []struct {
331 v1, v2, want PreciseVector
332 }{
333 {
334
335 v1: NewPreciseVector(1, 0, 0),
336 v2: NewPreciseVector(1, 0, 0),
337 want: NewPreciseVector(0, 0, 0),
338 },
339 {
340
341 v1: NewPreciseVector(1, 0, 0),
342 v2: NewPreciseVector(0, 1, 0),
343 want: NewPreciseVector(0, 0, 1),
344 },
345 {
346
347 v1: NewPreciseVector(0, 1, 0),
348 v2: NewPreciseVector(0, 0, 1),
349 want: NewPreciseVector(1, 0, 0),
350 },
351 {
352
353 v1: NewPreciseVector(0, 0, 1),
354 v2: NewPreciseVector(1, 0, 0),
355 want: NewPreciseVector(0, 1, 0),
356 },
357 {
358 v1: NewPreciseVector(0, 1, 0),
359 v2: NewPreciseVector(1, 0, 0),
360 want: NewPreciseVector(0, 0, -1),
361 },
362 {
363 v1: NewPreciseVector(1, 2, 3),
364 v2: NewPreciseVector(-4, 5, -6),
365 want: NewPreciseVector(-27, -6, 13),
366 },
367 }
368
369 for _, test := range tests {
370 if got := test.v1.Cross(test.v2); !got.Equal(test.want) {
371 t.Errorf("%v ⨯ %v = %v, want %v", test.v1, test.v2, got, test.want)
372 }
373 }
374 }
375
376 func TestPreciseIdentities(t *testing.T) {
377 tests := []struct {
378 v1, v2 PreciseVector
379 }{
380 {
381 v1: NewPreciseVector(0, 0, 0),
382 v2: NewPreciseVector(0, 0, 0),
383 },
384 {
385 v1: NewPreciseVector(0, 0, 0),
386 v2: NewPreciseVector(0, 1, 2),
387 },
388 {
389 v1: NewPreciseVector(1, 0, 0),
390 v2: NewPreciseVector(0, 1, 0),
391 },
392 {
393 v1: NewPreciseVector(1, 0, 0),
394 v2: NewPreciseVector(0, 1, 1),
395 },
396 {
397 v1: NewPreciseVector(1, 1, 1),
398 v2: NewPreciseVector(-1, -1, -1),
399 },
400 {
401 v1: NewPreciseVector(1, 2, 2),
402 v2: NewPreciseVector(-0.3, 0.4, -1.2),
403 },
404 }
405
406 for _, test := range tests {
407 c1 := test.v1.Cross(test.v2)
408 c2 := test.v2.Cross(test.v1)
409 d1 := test.v1.Dot(test.v2)
410 d2 := test.v2.Dot(test.v1)
411
412
413 if !preciseEq(d1, d2) {
414 t.Errorf("%v = %v · %v != %v · %v = %v", d1, test.v1, test.v2, test.v2, test.v1, d2)
415 }
416
417 if !c1.Equal(c2.MulByFloat64(-1.0)) {
418 t.Errorf("%v = %v ⨯ %v != -(%v ⨯ %v) = -%v", c1, test.v1, test.v2, test.v2, test.v1, c2)
419 }
420
421 if got := test.v1.Dot(c1); !preciseEq(got, precise0) {
422 t.Errorf("%v · (%v ⨯ %v) = %v, want %v", test.v1, test.v1, test.v2, got, precise0)
423 }
424 if got := test.v2.Dot(c1); !preciseEq(got, precise0) {
425 t.Errorf("%v · (%v ⨯ %v) = %v, want %v", test.v2, test.v1, test.v2, got, precise0)
426 }
427 }
428 }
429
430 func TestPreciseLargestSmallestComponents(t *testing.T) {
431 tests := []struct {
432 v PreciseVector
433 largest, smallest Axis
434 }{
435 {
436 v: NewPreciseVector(0, 0, 0),
437 largest: ZAxis,
438 smallest: ZAxis,
439 },
440 {
441 v: NewPreciseVector(1, 0, 0),
442 largest: XAxis,
443 smallest: ZAxis,
444 },
445 {
446 v: NewPreciseVector(1, -1, 0),
447 largest: YAxis,
448 smallest: ZAxis,
449 },
450 {
451 v: NewPreciseVector(-1, -1.1, -1.1),
452 largest: ZAxis,
453 smallest: XAxis,
454 },
455 {
456 v: NewPreciseVector(0.5, -0.4, -0.5),
457 largest: ZAxis,
458 smallest: YAxis,
459 },
460 {
461 v: NewPreciseVector(1e-15, 1e-14, 1e-13),
462 largest: ZAxis,
463 smallest: XAxis,
464 },
465 }
466
467 for _, test := range tests {
468 if got := test.v.LargestComponent(); got != test.largest {
469 t.Errorf("%v.LargestComponent() = %v, want %v", test.v, got, test.largest)
470 }
471 if got := test.v.SmallestComponent(); got != test.smallest {
472 t.Errorf("%v.SmallestComponent() = %v, want %v", test.v, got, test.smallest)
473 }
474 }
475 }
476
477 func TestPreciseVectorIsZero(t *testing.T) {
478
479 x := NewPreciseVector(1e20, 0, 0)
480 y := NewPreciseVector(1, 0, 0)
481 xy := x.Add(y)
482
483 tests := []struct {
484 have PreciseVector
485 want bool
486 }{
487 {
488 have: NewPreciseVector(0, 0, 0),
489 want: true,
490 },
491 {
492
493 have: NewPreciseVector(0, -0, 0),
494 want: true,
495 },
496 {
497
498 have: NewPreciseVector(0, 0, 1),
499 want: false,
500 },
501 {
502
503
504
505 have: x.Add(y).Add(x.Mul(precFloat(-1))),
506 want: false,
507 },
508 {
509
510
511 have: xy.Sub(xy),
512 want: true,
513 },
514 }
515
516 for _, test := range tests {
517 if got := test.have.IsZero(); got != test.want {
518 t.Errorf("%s.IsZero() = %v, want %v", test.have, got, test.want)
519 }
520 }
521 }
522
View as plain text