1 /**
2  * Contains the definition of a Vector comprising 3 doubles and associated
3  * transformations.
4  *
5  * @author Richard Greenlees
6  * @author Kai Burjack
7  * @author F. Neurath
8  */
9 module doml.vector_3d;
10 
11 import Math = doml.math;
12 
13 import doml.vector_2i;
14 import doml.vector_2d;
15 import doml.vector_3i;
16 import doml.vector_3d;
17 
18 import doml.matrix_4d;
19 import doml.matrix_3d;
20 import doml.matrix_3x2d;
21 import doml.matrix_4x3d;
22 
23 import doml.axis_angle_4d;
24 import doml.quaternion_d;
25 /*
26  * The MIT License
27  *
28  * Copyright (c) 2015-2021 Richard Greenlees
29  @#$%# Translated by jordan4ibanez
30  *
31  * Permission is hereby granted, free of charge, to any person obtaining a copy
32  * of this software and associated documentation files (the "Software"), to deal
33  * in the Software without restriction, including without limitation the rights
34  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
35  * copies of the Software, and to permit persons to whom the Software is
36  * furnished to do so, subject to the following conditions:
37  *
38  * The above copyright notice and this permission notice shall be included in
39  * all copies or substantial portions of the Software.
40  *
41  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
42  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
43  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
44  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
45  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
46  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
47  * THE SOFTWARE.
48  */
49 
50 /**
51  * Contains the definition of a Vector comprising 3 doubles and associated
52  * transformations.
53  *
54  * @author Richard Greenlees
55  * @author Kai Burjack
56  * @author F. Neurath
57  */
58 struct Vector3d {
59 
60     /**
61      * The x component of the vector.
62      */
63     public double x = 0.0;
64     /**
65      * The y component of the vector.
66      */
67     public double y = 0.0;
68     /**
69      * The z component of the vector.
70      */
71     public double z = 0.0;
72 
73     /**
74      * Create a new {@link Vector3d} and initialize all three components with the given value.
75      *
76      * @param d
77      *          the value of all three components
78      */
79     this(double d) {
80         this.x = d;
81         this.y = d;
82         this.z = d;
83     }
84 
85     /**
86      * Create a new {@link Vector3d} with the given component values.
87      * 
88      * @param x
89      *          the value of x
90      * @param y
91      *          the value of y
92      * @param z
93      *          the value of z
94      */
95     this(double x, double y, double z) {
96         this.x = x;
97         this.y = y;
98         this.z = z;
99     }
100 
101 
102     /**
103      * Create a new {@link Vector3d} whose values will be copied from the given vector.
104      * 
105      * @param v
106      *          provides the initial values for the new vector
107      */
108     this(Vector3i v) {
109         this.x = v.x;
110         this.y = v.y;
111         this.z = v.z;
112     }
113 
114     /**
115      * Create a new {@link Vector3d} with the first two components from the
116      * given <code>v</code> and the given <code>z</code>
117      *
118      * @param v
119      *          the {@link Vector2i} to copy the values from
120      * @param z
121      *          the z component
122      */
123     this(Vector2i v, double z) {
124         this.x = v.x;
125         this.y = v.y;
126         this.z = z;
127     }
128 
129     /**
130      * Create a new {@link Vector3d} whose values will be copied from the given vector.
131      * 
132      * @param v
133      *          provides the initial values for the new vector
134      */
135     this(Vector3d v) {
136         this.x = v.x;
137         this.y = v.y;
138         this.z = v.z;
139     }
140 
141     /**
142      * Create a new {@link Vector3d} with the first two components from the
143      * given <code>v</code> and the given <code>z</code>
144      *
145      * @param v
146      *          the {@link Vector2d} to copy the values from
147      * @param z
148      *          the z component
149      */
150     this(Vector2d v, double z) {
151         this.x = v.x;
152         this.y = v.y;
153         this.z = z;
154     }
155 
156     /**
157      * Create a new {@link Vector3d} and initialize its three components from the first
158      * three elements of the given array.
159      * 
160      * @param xyz
161      *          the array containing at least three elements
162      */
163     this(double[] xyz) {
164         this.x = xyz[0];
165         this.y = xyz[1];
166         this.z = xyz[2];
167     }
168 
169 
170     /**
171      * Set the x, y and z components to match the supplied vector.
172      * 
173      * @param v
174      *          the vector to set this vector's components from
175      * @return this
176      */
177     ref public Vector3d set(Vector3d v) return {
178         this.x = v.x;
179         this.y = v.y;
180         this.z = v.z;
181         return this;
182     }
183 
184     /**
185      * Set the x, y and z components to match the supplied vector.
186      * 
187      * @param v
188      *          the vector to set this vector's components from
189      * @return this
190      */
191     ref public Vector3d set(Vector3i v) return {
192         this.x = v.x;
193         this.y = v.y;
194         this.z = v.z;
195         return this;
196     }
197 
198     /**
199      * Set the first two components from the given <code>v</code>
200      * and the z component from the given <code>z</code>
201      *
202      * @param v
203      *          the {@link Vector2d} to copy the values from
204      * @param z
205      *          the z component
206      * @return this
207      */
208     ref public Vector3d set(Vector2d v, double z) return {
209         this.x = v.x;
210         this.y = v.y;
211         this.z = z;
212         return this;
213     }
214 
215     /**
216      * Set the first two components from the given <code>v</code>
217      * and the z component from the given <code>z</code>
218      *
219      * @param v
220      *          the {@link Vector2i} to copy the values from
221      * @param z
222      *          the z component
223      * @return this
224      */
225     ref public Vector3d set(Vector2i v, double z) return {
226         this.x = v.x;
227         this.y = v.y;
228         this.z = z;
229         return this;
230     }
231 
232     /**
233      * Set the x, y, and z components to the supplied value.
234      *
235      * @param d
236      *          the value of all three components
237      * @return this
238      */
239     ref public Vector3d set(double d) return {
240         this.x = d;
241         this.y = d;
242         this.z = d;
243         return this;
244     }
245 
246     /**
247      * Set the x, y and z components to the supplied values.
248      * 
249      * @param x
250      *          the x component
251      * @param y
252      *          the y component
253      * @param z
254      *          the z component
255      * @return this
256      */
257     ref public Vector3d set(double x, double y, double z) return {
258         this.x = x;
259         this.y = y;
260         this.z = z;
261         return this;
262     }
263 
264     /**
265      * Set the three components of this vector to the first three elements of the given array.
266      * 
267      * @param xyz
268      *          the array containing at least three elements
269      * @return this
270      */
271     ref public Vector3d set(double[] xyz) return {
272         this.x = xyz[0];
273         this.y = xyz[1];
274         this.z = xyz[2];
275         return this;
276     }
277 
278     /**
279      * Set the value of the specified component of this vector.
280      *
281      * @param component
282      *          the component whose value to set, within <code>[0..2]</code>
283      * @param value
284      *          the value to set
285      * @return this
286      * @throws IllegalArgumentException if <code>component</code> is not within <code>[0..2]</code>
287      */
288     ref public Vector3d setComponent(int component, double value) return {
289         switch (component) {
290             case 0:
291                 x = value;
292                 break;
293             case 1:
294                 y = value;
295                 break;
296             case 2:
297                 z = value;
298                 break;
299             default: {}
300         }
301         return this;
302     }
303 
304     /**
305      * Subtract the supplied vector from this one.
306      * 
307      * @param v
308      *          the vector to subtract from this
309      * @return this
310      */
311     ref public Vector3d sub(Vector3d v) return {
312         this.x = x - v.x;
313         this.y = y - v.y;
314         this.z = z - v.z;
315         return this;
316     }
317 
318     public Vector3d sub(Vector3d v, ref Vector3d dest) {
319         dest.x = x - v.x;
320         dest.y = y - v.y;
321         dest.z = z - v.z;
322         return dest;
323     }
324 
325 
326     /**
327      * Subtract <code>(x, y, z)</code> from this vector.
328      * 
329      * @param x
330      *          the x component to subtract
331      * @param y
332      *          the y component to subtract
333      * @param z
334      *          the z component to subtract
335      * @return this
336      */
337     ref public Vector3d sub(double x, double y, double z) return {
338         this.x = this.x - x;
339         this.y = this.y - y;
340         this.z = this.z - z;
341         return this;
342     }
343 
344     public Vector3d sub(double x, double y, double z, ref Vector3d dest) {
345         dest.x = this.x - x;
346         dest.y = this.y - y;
347         dest.z = this.z - z;
348         return dest;
349     }
350 
351     /**
352      * Add the supplied vector to this one.
353      * 
354      * @param v
355      *          the vector to add
356      * @return this
357      */
358     ref public Vector3d add(Vector3d v) return {
359         this.x = x + v.x;
360         this.y = y + v.y;
361         this.z = z + v.z;
362         return this;
363     }
364 
365     public Vector3d add(Vector3d v, ref Vector3d dest) {
366         dest.x = x + v.x;
367         dest.y = y + v.y;
368         dest.z = z + v.z;
369         return dest;
370     }
371 
372 
373     /**
374      * Increment the components of this vector by the given values.
375      * 
376      * @param x
377      *          the x component to add
378      * @param y
379      *          the y component to add
380      * @param z
381      *          the z component to add
382      * @return this
383      */
384     ref public Vector3d add(double x, double y, double z) return {
385         this.x = this.x + x;
386         this.y = this.y + y;
387         this.z = this.z + z;
388         return this;
389     }
390 
391     public Vector3d add(double x, double y, double z, ref Vector3d dest) {
392         dest.x = this.x + x;
393         dest.y = this.y + y;
394         dest.z = this.z + z;
395         return dest;
396     }
397 
398     /**
399      * Add the component-wise multiplication of <code>a * b</code> to this vector.
400      * 
401      * @param a
402      *          the first multiplicand
403      * @param b
404      *          the second multiplicand
405      * @return this
406      */
407     ref public Vector3d fma(Vector3d a, Vector3d b) return {
408         this.x = Math.fma(a.x, b.x, x);
409         this.y = Math.fma(a.y, b.y, y);
410         this.z = Math.fma(a.z, b.z, z);
411         return this;
412     }
413 
414     /**
415      * Add the component-wise multiplication of <code>a * b</code> to this vector.
416      * 
417      * @param a
418      *          the first multiplicand
419      * @param b
420      *          the second multiplicand
421      * @return this
422      */
423     ref public Vector3d fma(double a, Vector3d b) return {
424         this.x = Math.fma(a, b.x, x);
425         this.y = Math.fma(a, b.y, y);
426         this.z = Math.fma(a, b.z, z);
427         return this;
428     }
429 
430     public Vector3d fma(Vector3d a, Vector3d b, ref Vector3d dest) {
431         dest.x = Math.fma(a.x, b.x, x);
432         dest.y = Math.fma(a.y, b.y, y);
433         dest.z = Math.fma(a.z, b.z, z);
434         return dest;
435     }
436 
437     public Vector3d fma(double a, Vector3d b, ref Vector3d dest) {
438         dest.x = Math.fma(a, b.x, x);
439         dest.y = Math.fma(a, b.y, y);
440         dest.z = Math.fma(a, b.z, z);
441         return dest;
442     }
443 
444     /**
445      * Add the component-wise multiplication of <code>this * a</code> to <code>b</code>
446      * and store the result in <code>this</code>.
447      * 
448      * @param a
449      *          the multiplicand
450      * @param b
451      *          the addend
452      * @return this
453      */
454     ref public Vector3d mulAdd(Vector3d a, Vector3d b) return {
455         this.x = Math.fma(x, a.x, b.x);
456         this.y = Math.fma(y, a.y, b.y);
457         this.z = Math.fma(z, a.z, b.z);
458         return this;
459     }
460 
461     /**
462      * Add the component-wise multiplication of <code>this * a</code> to <code>b</code>
463      * and store the result in <code>this</code>.
464      * 
465      * @param a
466      *          the multiplicand
467      * @param b
468      *          the addend
469      * @return this
470      */
471     ref public Vector3d mulAdd(double a, Vector3d b) return {
472         this.x = Math.fma(x, a, b.x);
473         this.y = Math.fma(y, a, b.y);
474         this.z = Math.fma(z, a, b.z);
475         return this;
476     }
477 
478     public Vector3d mulAdd(Vector3d a, Vector3d b, ref Vector3d dest) {
479         dest.x = Math.fma(x, a.x, b.x);
480         dest.y = Math.fma(y, a.y, b.y);
481         dest.z = Math.fma(z, a.z, b.z);
482         return dest;
483     }
484 
485     public Vector3d mulAdd(double a, Vector3d b, ref Vector3d dest) {
486         dest.x = Math.fma(x, a, b.x);
487         dest.y = Math.fma(y, a, b.y);
488         dest.z = Math.fma(z, a, b.z);
489         return dest;
490     }
491 
492     /**
493      * Multiply this Vector3d component-wise by another Vector3d.
494      * 
495      * @param v
496      *          the vector to multiply by
497      * @return this
498      */
499     ref public Vector3d mul(Vector3d v) return {
500         this.x = x * v.x;
501         this.y = y * v.y;
502         this.z = z * v.z;
503         return this;
504     }
505 
506     public Vector3d mul(Vector3d v, ref Vector3d dest) {
507         dest.x = x * v.x;
508         dest.y = y * v.y;
509         dest.z = z * v.z;
510         return dest;
511     }
512 
513     /**
514      * Divide this Vector3d component-wise by another Vector3d.
515      * 
516      * @param v
517      *          the vector to divide by
518      * @return this
519      */
520     ref public Vector3d div(Vector3d v) return {
521         this.x = x / v.x;
522         this.y = y / v.y;
523         this.z = z / v.z;
524         return this;
525     }
526 
527 
528     public Vector3d div(Vector3d v, ref Vector3d dest) {
529         dest.x = x / v.x;
530         dest.y = y / v.y;
531         dest.z = z / v.z;
532         return dest;
533     }
534 
535     public Vector3d mulProject(Matrix4d mat, double w, ref Vector3d dest) {
536         double invW = 1.0 / Math.fma(mat.m03, x, Math.fma(mat.m13, y, Math.fma(mat.m23, z, mat.m33 * w)));
537         double rx = Math.fma(mat.m00, x, Math.fma(mat.m10, y, Math.fma(mat.m20, z, mat.m30 * w))) * invW;
538         double ry = Math.fma(mat.m01, x, Math.fma(mat.m11, y, Math.fma(mat.m21, z, mat.m31 * w))) * invW;
539         double rz = Math.fma(mat.m02, x, Math.fma(mat.m12, y, Math.fma(mat.m22, z, mat.m32 * w))) * invW;
540         dest.x = rx;
541         dest.y = ry;
542         dest.z = rz;
543         return dest;
544     }
545 
546     public Vector3d mulProject(Matrix4d mat, ref Vector3d dest) {
547         double invW = 1.0 / Math.fma(mat.m03, x, Math.fma(mat.m13, y, Math.fma(mat.m23, z, mat.m33)));
548         double rx = Math.fma(mat.m00, x, Math.fma(mat.m10, y, Math.fma(mat.m20, z, mat.m30))) * invW;
549         double ry = Math.fma(mat.m01, x, Math.fma(mat.m11, y, Math.fma(mat.m21, z, mat.m31))) * invW;
550         double rz = Math.fma(mat.m02, x, Math.fma(mat.m12, y, Math.fma(mat.m22, z, mat.m32))) * invW;
551         dest.x = rx;
552         dest.y = ry;
553         dest.z = rz;
554         return dest;
555     }
556 
557     /**
558      * Multiply the given matrix <code>mat</code> this Vector3d, perform perspective division.
559      * <p>
560      * This method uses <code>w=1.0</code> as the fourth vector component.
561      * 
562      * @param mat
563      *          the matrix to multiply this vector by
564      * @return this
565      */
566     ref public Vector3d mulProject(Matrix4d mat) return {
567         double invW = 1.0 / Math.fma(mat.m03, x, Math.fma(mat.m13, y, Math.fma(mat.m23, z, mat.m33)));
568         double rx = Math.fma(mat.m00, x, Math.fma(mat.m10, y, Math.fma(mat.m20, z, mat.m30))) * invW;
569         double ry = Math.fma(mat.m01, x, Math.fma(mat.m11, y, Math.fma(mat.m21, z, mat.m31))) * invW;
570         double rz = Math.fma(mat.m02, x, Math.fma(mat.m12, y, Math.fma(mat.m22, z, mat.m32))) * invW;
571         this.x = rx;
572         this.y = ry;
573         this.z = rz;
574         return this;
575     }
576 
577 
578     /**
579      * Multiply the given matrix <code>mat</code> with this Vector3d.
580      * 
581      * @param mat
582      *          the matrix to multiply this vector by
583      * @return this
584      */
585     ref public Vector3d mul(Matrix3d mat) return {
586         double rx = Math.fma(mat.m00, x, Math.fma(mat.m10, y, mat.m20 * z));
587         double ry = Math.fma(mat.m01, x, Math.fma(mat.m11, y, mat.m21 * z));
588         double rz = Math.fma(mat.m02, x, Math.fma(mat.m12, y, mat.m22 * z));
589         this.x = rx;
590         this.y = ry;
591         this.z = rz;
592         return this;
593     }
594 
595     public Vector3d mul(Matrix3d mat, ref Vector3d dest) {
596         double rx = Math.fma(mat.m00, x, Math.fma(mat.m10, y, mat.m20 * z));
597         double ry = Math.fma(mat.m01, x, Math.fma(mat.m11, y, mat.m21 * z));
598         double rz = Math.fma(mat.m02, x, Math.fma(mat.m12, y, mat.m22 * z));
599         dest.x = rx;
600         dest.y = ry;
601         dest.z = rz;
602         return dest;
603     }
604 
605     /**
606      * Multiply the given matrix with this Vector3d by assuming a third row in the matrix of <code>(0, 0, 1)</code>
607      * and store the result in <code>this</code>.
608      * 
609      * @param mat
610      *          the matrix
611      * @return this
612      */
613     ref public Vector3d mul(Matrix3x2d mat) return {
614         double rx = Math.fma(mat.m00, x, Math.fma(mat.m10, y, mat.m20 * z));
615         double ry = Math.fma(mat.m01, x, Math.fma(mat.m11, y, mat.m21 * z));
616         this.x = rx;
617         this.y = ry;
618         return this;
619     }
620 
621     public Vector3d mul(Matrix3x2d mat, ref Vector3d dest) {
622         double rx = Math.fma(mat.m00, x, Math.fma(mat.m10, y, mat.m20 * z));
623         double ry = Math.fma(mat.m01, x, Math.fma(mat.m11, y, mat.m21 * z));
624         dest.x = rx;
625         dest.y = ry;
626         dest.z = z;
627         return dest;
628     }
629 
630 
631     /**
632      * Multiply the transpose of the given matrix with this Vector3d and store the result in <code>this</code>.
633      * 
634      * @param mat
635      *          the matrix
636      * @return this
637      */
638     ref public Vector3d mulTranspose(Matrix3d mat) return {
639         double rx = Math.fma(mat.m00, x, Math.fma(mat.m01, y, mat.m02 * z));
640         double ry = Math.fma(mat.m10, x, Math.fma(mat.m11, y, mat.m12 * z));
641         double rz = Math.fma(mat.m20, x, Math.fma(mat.m21, y, mat.m22 * z));
642         this.x = rx;
643         this.y = ry;
644         this.z = rz;
645         return this;
646     }
647 
648     public Vector3d mulTranspose(Matrix3d mat, ref Vector3d dest) {
649         double rx = Math.fma(mat.m00, x, Math.fma(mat.m01, y, mat.m02 * z));
650         double ry = Math.fma(mat.m10, x, Math.fma(mat.m11, y, mat.m12 * z));
651         double rz = Math.fma(mat.m20, x, Math.fma(mat.m21, y, mat.m22 * z));
652         dest.x = rx;
653         dest.y = ry;
654         dest.z = rz;
655         return dest;
656     }
657 
658     /**
659      * Multiply the given 4x4 matrix <code>mat</code> with <code>this</code>.
660      * <p>
661      * This method assumes the <code>w</code> component of <code>this</code> to be <code>1.0</code>.
662      * 
663      * @param mat
664      *          the matrix to multiply this vector by
665      * @return this
666      */
667     ref public Vector3d mulPosition(Matrix4d mat) return {
668         double rx = Math.fma(mat.m00, x, Math.fma(mat.m10, y, Math.fma(mat.m20, z, mat.m30)));
669         double ry = Math.fma(mat.m01, x, Math.fma(mat.m11, y, Math.fma(mat.m21, z, mat.m31)));
670         double rz = Math.fma(mat.m02, x, Math.fma(mat.m12, y, Math.fma(mat.m22, z, mat.m32)));
671         this.x = rx;
672         this.y = ry;
673         this.z = rz;
674         return this;
675     }
676 
677     /**
678      * Multiply the given 4x3 matrix <code>mat</code> with <code>this</code>.
679      * <p>
680      * This method assumes the <code>w</code> component of <code>this</code> to be <code>1.0</code>.
681      * 
682      * @param mat
683      *          the matrix to multiply this vector by
684      * @return this
685      */
686     ref public Vector3d mulPosition(Matrix4x3d mat) return {
687         double rx = Math.fma(mat.m00, x, Math.fma(mat.m10, y, Math.fma(mat.m20, z, mat.m30)));
688         double ry = Math.fma(mat.m01, x, Math.fma(mat.m11, y, Math.fma(mat.m21, z, mat.m31)));
689         double rz = Math.fma(mat.m02, x, Math.fma(mat.m12, y, Math.fma(mat.m22, z, mat.m32)));
690         this.x = rx;
691         this.y = ry;
692         this.z = rz;
693         return this;
694     }
695 
696 
697     public Vector3d mulPosition(Matrix4d mat, ref Vector3d dest) {
698         double rx = Math.fma(mat.m00, x, Math.fma(mat.m10, y, Math.fma(mat.m20, z, mat.m30)));
699         double ry = Math.fma(mat.m01, x, Math.fma(mat.m11, y, Math.fma(mat.m21, z, mat.m31)));
700         double rz = Math.fma(mat.m02, x, Math.fma(mat.m12, y, Math.fma(mat.m22, z, mat.m32)));
701         dest.x = rx;
702         dest.y = ry;
703         dest.z = rz;
704         return dest;
705     }
706 
707     public Vector3d mulPosition(Matrix4x3d mat, ref Vector3d dest) {
708         double rx = Math.fma(mat.m00, x, Math.fma(mat.m10, y, Math.fma(mat.m20, z, mat.m30)));
709         double ry = Math.fma(mat.m01, x, Math.fma(mat.m11, y, Math.fma(mat.m21, z, mat.m31)));
710         double rz = Math.fma(mat.m02, x, Math.fma(mat.m12, y, Math.fma(mat.m22, z, mat.m32)));
711         dest.x = rx;
712         dest.y = ry;
713         dest.z = rz;
714         return dest;
715     }
716 
717     /**
718      * Multiply the transpose of the given 4x4 matrix <code>mat</code> with <code>this</code>.
719      * <p>
720      * This method assumes the <code>w</code> component of <code>this</code> to be <code>1.0</code>.
721      * 
722      * @param mat
723      *          the matrix whose transpose to multiply this vector by
724      * @return this
725      */
726     ref public Vector3d mulTransposePosition(Matrix4d mat) return {
727         double rx = Math.fma(mat.m00, x, Math.fma(mat.m01, y, Math.fma(mat.m02, z, mat.m03)));
728         double ry = Math.fma(mat.m10, x, Math.fma(mat.m11, y, Math.fma(mat.m12, z, mat.m13)));
729         double rz = Math.fma(mat.m20, x, Math.fma(mat.m21, y, Math.fma(mat.m22, z, mat.m23)));
730         this.x = rx;
731         this.y = ry;
732         this.z = rz;
733         return this;
734     }
735 
736     public Vector3d mulTransposePosition(Matrix4d mat, ref Vector3d dest) {
737         double rx = Math.fma(mat.m00, x, Math.fma(mat.m01, y, Math.fma(mat.m02, z, mat.m03)));
738         double ry = Math.fma(mat.m10, x, Math.fma(mat.m11, y, Math.fma(mat.m12, z, mat.m13)));
739         double rz = Math.fma(mat.m20, x, Math.fma(mat.m21, y, Math.fma(mat.m22, z, mat.m23)));
740         dest.x = rx;
741         dest.y = ry;
742         dest.z = rz;
743         return dest;
744     }
745 
746 
747 
748 
749     /**
750      * Multiply the given 4x4 matrix <code>mat</code> with <code>this</code> and return the <i>w</i> component
751      * of the resulting 4D vector.
752      * <p>
753      * This method assumes the <code>w</code> component of <code>this</code> to be <code>1.0</code>.
754      * 
755      * @param mat
756      *          the matrix to multiply this vector by
757      * @return the <i>w</i> component of the resulting 4D vector after multiplication
758      */
759     public double mulPositionW(Matrix4d mat) {
760         double w = Math.fma(mat.m03, x, Math.fma(mat.m13, y, Math.fma(mat.m23, z, mat.m33)));
761         double rx = Math.fma(mat.m00, x, Math.fma(mat.m10, y, Math.fma(mat.m20, z, mat.m30)));
762         double ry = Math.fma(mat.m01, x, Math.fma(mat.m11, y, Math.fma(mat.m21, z, mat.m31)));
763         double rz = Math.fma(mat.m02, x, Math.fma(mat.m12, y, Math.fma(mat.m22, z, mat.m32)));
764         this.x = rx;
765         this.y = ry;
766         this.z = rz;
767         return w;
768     }
769 
770     public double mulPositionW(Matrix4d mat, ref Vector3d dest) {
771         double w = Math.fma(mat.m03, x, Math.fma(mat.m13, y, Math.fma(mat.m23, z, mat.m33)));
772         double rx = Math.fma(mat.m00, x, Math.fma(mat.m10, y, Math.fma(mat.m20, z, mat.m30)));
773         double ry = Math.fma(mat.m01, x, Math.fma(mat.m11, y, Math.fma(mat.m21, z, mat.m31)));
774         double rz = Math.fma(mat.m02, x, Math.fma(mat.m12, y, Math.fma(mat.m22, z, mat.m32)));
775         dest.x = rx;
776         dest.y = ry;
777         dest.z = rz;
778         return w;
779     }
780 
781 
782     /**
783      * Multiply the given 4x4 matrix <code>mat</code> with <code>this</code>.
784      * <p>
785      * This method assumes the <code>w</code> component of <code>this</code> to be <code>0.0</code>.
786      * 
787      * @param mat
788      *          the matrix to multiply this vector by
789      * @return this
790      */
791     ref public Vector3d mulDirection(Matrix4d mat) return {
792         double rx = Math.fma(mat.m00, x, Math.fma(mat.m10, y, mat.m20 * z));
793         double ry = Math.fma(mat.m01, x, Math.fma(mat.m11, y, mat.m21 * z));
794         double rz = Math.fma(mat.m02, x, Math.fma(mat.m12, y, mat.m22 * z));
795         this.x = rx;
796         this.y = ry;
797         this.z = rz;
798         return this;
799     }
800 
801     /**
802      * Multiply the given 4x3 matrix <code>mat</code> with <code>this</code>.
803      * <p>
804      * This method assumes the <code>w</code> component of <code>this</code> to be <code>0.0</code>.
805      * 
806      * @param mat
807      *          the matrix to multiply this vector by
808      * @return this
809      */
810     ref public Vector3d mulDirection(Matrix4x3d mat) return {
811         double rx = Math.fma(mat.m00, x, Math.fma(mat.m10, y, mat.m20 * z));
812         double ry = Math.fma(mat.m01, x, Math.fma(mat.m11, y, mat.m21 * z));
813         double rz = Math.fma(mat.m02, x, Math.fma(mat.m12, y, mat.m22 * z));
814         this.x = rx;
815         this.y = ry;
816         this.z = rz;
817         return this;
818     }
819 
820 
821     public Vector3d mulDirection(Matrix4d mat, Vector3d dest) {
822         double rx = Math.fma(mat.m00, x, Math.fma(mat.m10, y, mat.m20 * z));
823         double ry = Math.fma(mat.m01, x, Math.fma(mat.m11, y, mat.m21 * z));
824         double rz = Math.fma(mat.m02, x, Math.fma(mat.m12, y, mat.m22 * z));
825         dest.x = rx;
826         dest.y = ry;
827         dest.z = rz;
828         return dest;
829     }
830 
831     public Vector3d mulDirection(Matrix4x3d mat, ref Vector3d dest) {
832         double rx = Math.fma(mat.m00, x, Math.fma(mat.m10, y, mat.m20 * z));
833         double ry = Math.fma(mat.m01, x, Math.fma(mat.m11, y, mat.m21 * z));
834         double rz = Math.fma(mat.m02, x, Math.fma(mat.m12, y, mat.m22 * z));
835         dest.x = rx;
836         dest.y = ry;
837         dest.z = rz;
838         return dest;
839     }
840 
841 
842     /**
843      * Multiply the transpose of the given 4x4 matrix <code>mat</code> with <code>this</code>.
844      * <p>
845      * This method assumes the <code>w</code> component of <code>this</code> to be <code>0.0</code>.
846      * 
847      * @param mat
848      *          the matrix whose transpose to multiply this vector by
849      * @return this
850      */
851     ref public Vector3d mulTransposeDirection(Matrix4d mat) return {
852         double rx = Math.fma(mat.m00, x, Math.fma(mat.m01, y, mat.m02 * z));
853         double ry = Math.fma(mat.m10, x, Math.fma(mat.m11, y, mat.m12 * z));
854         double rz = Math.fma(mat.m20, x, Math.fma(mat.m21, y, mat.m22 * z));
855         this.x = rx;
856         this.y = ry;
857         this.z = rz;
858         return this;
859     }
860 
861     public Vector3d mulTransposeDirection(Matrix4d mat, ref Vector3d dest) {
862         double rx = Math.fma(mat.m00, x, Math.fma(mat.m01, y, mat.m02 * z));
863         double ry = Math.fma(mat.m10, x, Math.fma(mat.m11, y, mat.m12 * z));
864         double rz = Math.fma(mat.m20, x, Math.fma(mat.m21, y, mat.m22 * z));
865         dest.x = rx;
866         dest.y = ry;
867         dest.z = rz;
868         return dest;
869     }
870 
871     /**
872      * Multiply this Vector3d by the given scalar value.
873      * 
874      * @param scalar
875      *          the scalar to multiply this vector by
876      * @return this
877      */
878     ref public Vector3d mul(double scalar) return {
879         this.x = x * scalar;
880         this.y = y * scalar;
881         this.z = z * scalar;
882         return this;
883     }
884 
885     public Vector3d mul(double scalar, ref Vector3d dest) {
886         dest.x = x * scalar;
887         dest.y = y * scalar;
888         dest.z = z * scalar;
889         return dest;
890     }
891 
892     /**
893      * Multiply the components of this Vector3d by the given scalar values and store the result in <code>this</code>.
894      * 
895      * @param x
896      *          the x component to multiply this vector by
897      * @param y
898      *          the y component to multiply this vector by
899      * @param z
900      *          the z component to multiply this vector by
901      * @return this
902      */
903     ref public Vector3d mul(double x, double y, double z) return {
904         this.x = this.x * x;
905         this.y = this.y * y;
906         this.z = this.z * z;
907         return this;
908     }
909 
910     public Vector3d mul(double x, double y, double z, ref Vector3d dest) {
911         dest.x = this.x * x;
912         dest.y = this.y * y;
913         dest.z = this.z * z;
914         return dest;
915     }
916 
917     /**
918      * Rotate this vector by the given quaternion <code>quat</code> and store the result in <code>this</code>.
919      * 
920      * @see Quaterniond#transform(Vector3d)
921      * 
922      * @param quat
923      *          the quaternion to rotate this vector
924      * @return this
925      */
926     ref public Vector3d rotate(Quaterniond quat) return {
927         quat.transform(this, this);
928         return this;
929     }
930 
931     public Vector3d rotate(Quaterniond quat, ref Vector3d dest) {
932         return quat.transform(this, dest);
933     }
934 
935     public Quaterniond rotationTo(Vector3d toDir, ref Quaterniond dest) {
936         return dest.rotationTo(this, toDir);
937     }
938 
939     public Quaterniond rotationTo(double toDirX, double toDirY, double toDirZ, ref Quaterniond dest) {
940         return dest.rotationTo(x, y, z, toDirX, toDirY, toDirZ);
941     }
942 
943     /**
944      * Rotate this vector the specified radians around the given rotation axis.
945      * 
946      * @param angle
947      *          the angle in radians
948      * @param x
949      *          the x component of the rotation axis
950      * @param y
951      *          the y component of the rotation axis
952      * @param z
953      *          the z component of the rotation axis
954      * @return this
955      */
956     ref public Vector3d rotateAxis(double angle, double x, double y, double z) return {
957         if (y == 0.0 && z == 0.0 && Math.absEqualsOne(x))
958             rotateX(x * angle, this);
959         else if (x == 0.0 && z == 0.0 && Math.absEqualsOne(y))
960             rotateY(y * angle, this);
961         else if (x == 0.0 && y == 0.0 && Math.absEqualsOne(z))
962             rotateZ(z * angle, this);
963         else
964             rotateAxisInternal(angle, x, y, z, this);
965 
966         return this;
967     }
968 
969     public Vector3d rotateAxis(double angle, double aX, double aY, double aZ, ref Vector3d dest) {
970         if (aY == 0.0 && aZ == 0.0 && Math.absEqualsOne(aX))
971             return rotateX(aX * angle, dest);
972         else if (aX == 0.0 && aZ == 0.0 && Math.absEqualsOne(aY))
973             return rotateY(aY * angle, dest);
974         else if (aX == 0.0 && aY == 0.0 && Math.absEqualsOne(aZ))
975             return rotateZ(aZ * angle, dest);
976         return rotateAxisInternal(angle, aX, aY, aZ, dest);
977     }
978 
979     private Vector3d rotateAxisInternal(double angle, double aX, double aY, double aZ, ref Vector3d dest) {
980         double hangle = angle * 0.5;
981         double sinAngle = Math.sin(hangle);
982         double qx = aX * sinAngle, qy = aY * sinAngle, qz = aZ * sinAngle;
983         double qw = Math.cosFromSin(sinAngle, hangle);
984         double w2 = qw * qw, x2 = qx * qx, y2 = qy * qy, z2 = qz * qz, zw = qz * qw;
985         double xy = qx * qy, xz = qx * qz, yw = qy * qw, yz = qy * qz, xw = qx * qw;
986         double nx = (w2 + x2 - z2 - y2) * x + (-zw + xy - zw + xy) * y + (yw + xz + xz + yw) * z;
987         double ny = (xy + zw + zw + xy) * x + ( y2 - z2 + w2 - x2) * y + (yz + yz - xw - xw) * z;
988         double nz = (xz - yw + xz - yw) * x + ( yz + yz + xw + xw) * y + (z2 - y2 - x2 + w2) * z;
989         dest.x = nx;
990         dest.y = ny;
991         dest.z = nz;
992         return dest;
993     }
994 
995     /**
996      * Rotate this vector the specified radians around the X axis.
997      * 
998      * @param angle
999      *          the angle in radians
1000      * @return this
1001      */
1002     ref public Vector3d rotateX(double angle) return {
1003         double sin = Math.sin(angle), cos = Math.cosFromSin(sin, angle);
1004         double y = this.y * cos - this.z * sin;
1005         double z = this.y * sin + this.z * cos;
1006         this.y = y;
1007         this.z = z;
1008         return this;
1009     }
1010 
1011     public Vector3d rotateX(double angle, ref Vector3d dest) {
1012         double sin = Math.sin(angle), cos = Math.cosFromSin(sin, angle);
1013         double y = this.y * cos - this.z * sin;
1014         double z = this.y * sin + this.z * cos;
1015         dest.x = this.x;
1016         dest.y = y;
1017         dest.z = z;
1018         return dest;
1019     }
1020 
1021     /**
1022      * Rotate this vector the specified radians around the Y axis.
1023      * 
1024      * @param angle
1025      *          the angle in radians
1026      * @return this
1027      */
1028     ref public Vector3d rotateY(double angle) return {
1029         double sin = Math.sin(angle), cos = Math.cosFromSin(sin, angle);
1030         double x =  this.x * cos + this.z * sin;
1031         double z = -this.x * sin + this.z * cos;
1032         this.x = x;
1033         this.z = z;
1034         return this;
1035     }
1036 
1037     public Vector3d rotateY(double angle, ref Vector3d dest) {
1038         double sin = Math.sin(angle), cos = Math.cosFromSin(sin, angle);
1039         double x =  this.x * cos + this.z * sin;
1040         double z = -this.x * sin + this.z * cos;
1041         dest.x = x;
1042         dest.y = this.y;
1043         dest.z = z;
1044         return dest;
1045     }
1046 
1047     /**
1048      * Rotate this vector the specified radians around the Z axis.
1049      * 
1050      * @param angle
1051      *          the angle in radians
1052      * @return this
1053      */
1054     ref public Vector3d rotateZ(double angle) return {
1055         double sin = Math.sin(angle), cos = Math.cosFromSin(sin, angle);
1056         double x = this.x * cos - this.y * sin;
1057         double y = this.x * sin + this.y * cos;
1058         this.x = x;
1059         this.y = y;
1060         return this;
1061     }
1062 
1063     public Vector3d rotateZ(double angle, ref Vector3d dest) {
1064         double sin = Math.sin(angle), cos = Math.cosFromSin(sin, angle);
1065         double x = this.x * cos - this.y * sin;
1066         double y = this.x * sin + this.y * cos;
1067         dest.x = x;
1068         dest.y = y;
1069         dest.z = this.z;
1070         return dest;
1071     }
1072 
1073     /**
1074      * Divide this Vector3d by the given scalar value.
1075      * 
1076      * @param scalar
1077      *          the scalar to divide this vector by
1078      * @return this
1079      */
1080     ref public Vector3d div(double scalar) return {
1081         double inv = 1.0 / scalar;
1082         this.x = x * inv;
1083         this.y = y * inv;
1084         this.z = z * inv;
1085         return this;
1086     }
1087 
1088     public Vector3d div(double scalar, ref Vector3d dest) {
1089         double inv = 1.0 / scalar;
1090         dest.x = x * inv;
1091         dest.y = y * inv;
1092         dest.z = z * inv;
1093         return dest;
1094     }
1095 
1096     /**
1097      * Divide the components of this Vector3d by the given scalar values and store the result in <code>this</code>.
1098      * 
1099      * @param x
1100      *          the x component to divide this vector by
1101      * @param y
1102      *          the y component to divide this vector by
1103      * @param z
1104      *          the z component to divide this vector by
1105      * @return this
1106      */
1107     ref public Vector3d div(double x, double y, double z) return {
1108         this.x = this.x / x;
1109         this.y = this.y / y;
1110         this.z = this.z / z;
1111         return this;
1112     }
1113 
1114     public Vector3d div(double x, double y, double z, ref Vector3d dest) {
1115         dest.x = this.x / x;
1116         dest.y = this.y / y;
1117         dest.z = this.z / z;
1118         return dest;
1119     }
1120 
1121     public double lengthSquared() {
1122         return Math.fma(x, x, Math.fma(y, y, z * z));
1123     }
1124 
1125     /**
1126      * Get the length squared of a 3-dimensional double-precision vector.
1127      *
1128      * @param x The vector's x component
1129      * @param y The vector's y component
1130      * @param z The vector's z component
1131      *
1132      * @return the length squared of the given vector
1133      *
1134      * @author F. Neurath
1135      */
1136     public static double lengthSquared(double x, double y, double z) {
1137         return Math.fma(x, x, Math.fma(y, y, z * z));
1138     }
1139 
1140     public double length() {
1141         return Math.sqrt(Math.fma(x, x, Math.fma(y, y, z * z)));
1142     }
1143 
1144     /**
1145      * Get the length of a 3-dimensional double-precision vector.
1146      *
1147      * @param x The vector's x component
1148      * @param y The vector's y component
1149      * @param z The vector's z component
1150      *
1151      * @return the length of the given vector
1152      *
1153      * @author F. Neurath
1154      */
1155     public static double length(double x, double y, double z) {
1156         return Math.sqrt(Math.fma(x, x, Math.fma(y, y, z * z)));
1157     }
1158 
1159     /**
1160      * Normalize this vector.
1161      * 
1162      * @return this
1163      */
1164     ref public Vector3d normalize() return {
1165         double invLength = Math.invsqrt(Math.fma(x, x, Math.fma(y, y, z * z)));
1166         this.x = x * invLength;
1167         this.y = y * invLength;
1168         this.z = z * invLength;
1169         return this;
1170     }
1171 
1172     public Vector3d normalize(ref Vector3d dest) {
1173         double invLength = Math.invsqrt(Math.fma(x, x, Math.fma(y, y, z * z)));
1174         dest.x = x * invLength;
1175         dest.y = y * invLength;
1176         dest.z = z * invLength;
1177         return dest;
1178     }
1179 
1180     /**
1181      * Scale this vector to have the given length.
1182      * 
1183      * @param length
1184      *          the desired length
1185      * @return this
1186      */
1187     ref public Vector3d normalize(double length) return {
1188         double invLength = Math.invsqrt(Math.fma(x, x, Math.fma(y, y, z * z))) * length;
1189         this.x = x * invLength;
1190         this.y = y * invLength;
1191         this.z = z * invLength;
1192         return this;
1193     }
1194 
1195     public Vector3d normalize(double length, ref Vector3d dest) {
1196         double invLength = Math.invsqrt(Math.fma(x, x, Math.fma(y, y, z * z))) * length;
1197         dest.x = x * invLength;
1198         dest.y = y * invLength;
1199         dest.z = z * invLength;
1200         return dest;
1201     }
1202 
1203     /**
1204      * Set this vector to be the cross product of this and v2.
1205      * 
1206      * @param v
1207      *          the other vector
1208      * @return this
1209      */
1210     ref public Vector3d cross(Vector3d v) return {
1211         double rx = Math.fma(y, v.z, -z * v.y);
1212         double ry = Math.fma(z, v.x, -x * v.z);
1213         double rz = Math.fma(x, v.y, -y * v.x);
1214         this.x = rx;
1215         this.y = ry;
1216         this.z = rz;
1217         return this;
1218     }
1219 
1220     /**
1221      * Set this vector to be the cross product of itself and <code>(x, y, z)</code>.
1222      * 
1223      * @param x
1224      *          the x component of the other vector
1225      * @param y
1226      *          the y component of the other vector
1227      * @param z
1228      *          the z component of the other vector
1229      * @return this
1230      */
1231     ref public Vector3d cross(double x, double y, double z) return {
1232         double rx = Math.fma(this.y, z, -this.z * y);
1233         double ry = Math.fma(this.z, x, -this.x * z);
1234         double rz = Math.fma(this.x, y, -this.y * x);
1235         this.x = rx;
1236         this.y = ry;
1237         this.z = rz;
1238         return this;
1239     }
1240 
1241     public Vector3d cross(Vector3d v, ref Vector3d dest) {
1242         double rx = Math.fma(y, v.z, -z * v.y);
1243         double ry = Math.fma(z, v.x, -x * v.z);
1244         double rz = Math.fma(x, v.y, -y * v.x);
1245         dest.x = rx;
1246         dest.y = ry;
1247         dest.z = rz;
1248         return dest;
1249     }
1250 
1251     public Vector3d cross(double x, double y, double z, ref Vector3d dest) {
1252         double rx = Math.fma(this.y, z, -this.z * y);
1253         double ry = Math.fma(this.z, x, -this.x * z);
1254         double rz = Math.fma(this.x, y, -this.y * x);
1255         dest.x = rx;
1256         dest.y = ry;
1257         dest.z = rz;
1258         return dest;
1259     }
1260 
1261     public double distance(Vector3d v) {
1262         double dx = this.x - v.x;
1263         double dy = this.y - v.y;
1264         double dz = this.z - v.z;
1265         return Math.sqrt(Math.fma(dx, dx, Math.fma(dy, dy, dz * dz)));
1266     }
1267 
1268     public double distance(double x, double y, double z) {
1269         double dx = this.x - x;
1270         double dy = this.y - y;
1271         double dz = this.z - z;
1272         return Math.sqrt(Math.fma(dx, dx, Math.fma(dy, dy, dz * dz)));
1273     }
1274 
1275     public double distanceSquared(Vector3d v) {
1276         double dx = this.x - v.x;
1277         double dy = this.y - v.y;
1278         double dz = this.z - v.z;
1279         return Math.fma(dx, dx, Math.fma(dy, dy, dz * dz));
1280     }
1281 
1282     public double distanceSquared(double x, double y, double z) {
1283         double dx = this.x - x;
1284         double dy = this.y - y;
1285         double dz = this.z - z;
1286         return Math.fma(dx, dx, Math.fma(dy, dy, dz * dz));
1287     }
1288 
1289     /**
1290      * Return the distance between <code>(x1, y1, z1)</code> and <code>(x2, y2, z2)</code>.
1291      *
1292      * @param x1
1293      *          the x component of the first vector
1294      * @param y1
1295      *          the y component of the first vector
1296      * @param z1
1297      *          the z component of the first vector
1298      * @param x2
1299      *          the x component of the second vector
1300      * @param y2
1301      *          the y component of the second vector
1302      * @param z2
1303      *          the z component of the second vector
1304      * @return the euclidean distance
1305      */
1306     public static double distance(double x1, double y1, double z1, double x2, double y2, double z2) {
1307         return Math.sqrt(distanceSquared(x1, y1, z1, x2, y2, z2));
1308     }
1309 
1310     /**
1311      * Return the squared distance between <code>(x1, y1, z1)</code> and <code>(x2, y2, z2)</code>.
1312      *
1313      * @param x1
1314      *          the x component of the first vector
1315      * @param y1
1316      *          the y component of the first vector
1317      * @param z1
1318      *          the z component of the first vector
1319      * @param x2
1320      *          the x component of the second vector
1321      * @param y2
1322      *          the y component of the second vector
1323      * @param z2
1324      *          the z component of the second vector
1325      * @return the euclidean distance squared
1326      */
1327     public static double distanceSquared(double x1, double y1, double z1, double x2, double y2, double z2) {
1328         double dx = x1 - x2;
1329         double dy = y1 - y2;
1330         double dz = z1 - z2;
1331         return Math.fma(dx, dx, Math.fma(dy, dy, dz * dz));
1332     }
1333 
1334     public double dot(Vector3d v) {
1335         return Math.fma(this.x, v.x, Math.fma(this.y, v.y, this.z * v.z));
1336     }
1337 
1338     public double dot(double x, double y, double z) {
1339         return Math.fma(this.x, x, Math.fma(this.y, y, this.z * z));
1340     }
1341 
1342     public double angleCos(Vector3d v) {
1343         double length1Squared = Math.fma(x, x, Math.fma(y, y, z * z));
1344         double length2Squared = Math.fma(v.x, v.x, Math.fma(v.y, v.y, v.z * v.z));
1345         double dot = Math.fma(x, v.x, Math.fma(y, v.y, z * v.z));
1346         return dot / Math.sqrt(length1Squared * length2Squared);
1347     }
1348 
1349     public double angle(Vector3d v) {
1350         double cos = angleCos(v);
1351         // This is because sometimes cos goes above 1 or below -1 because of lost precision
1352         cos = cos < 1 ? cos : 1;
1353         cos = cos > -1 ? cos : -1;
1354         return Math.acos(cos);
1355     }
1356 
1357     public double angleSigned(Vector3d v, Vector3d n) {
1358         double x = v.x;
1359         double y = v.y;
1360         double z = v.z;
1361         return Math.atan2(
1362         (this.y * z - this.z * y) * n.x + (this.z * x - this.x * z) * n.y + (this.x * y - this.y * x) * n.z,
1363         this.x * x + this.y * y + this.z * z);
1364     }
1365 
1366     public double angleSigned(double x, double y, double z, double nx, double ny, double nz) {
1367         return Math.atan2(
1368                 (this.y * z - this.z * y) * nx + (this.z * x - this.x * z) * ny + (this.x * y - this.y * x) * nz,
1369                 this.x * x + this.y * y + this.z * z);
1370     }
1371 
1372     /**
1373      * Set the components of this vector to be the component-wise minimum of this and the other vector.
1374      *
1375      * @param v
1376      *          the other vector
1377      * @return this
1378      */
1379     ref public Vector3d min(Vector3d v) return {
1380         this.x = x < v.x ? x : v.x;
1381         this.y = y < v.y ? y : v.y;
1382         this.z = z < v.z ? z : v.z;
1383         return this;
1384     }
1385 
1386     public Vector3d min(Vector3d v, ref Vector3d dest) {
1387         dest.x = x < v.x ? x : v.x;
1388         dest.y = y < v.y ? y : v.y;
1389         dest.z = z < v.z ? z : v.z;
1390         return dest;
1391     }
1392 
1393     /**
1394      * Set the components of this vector to be the component-wise maximum of this and the other vector.
1395      *
1396      * @param v
1397      *          the other vector
1398      * @return this
1399      */
1400     ref public Vector3d max(Vector3d v) return {
1401         this.x = x > v.x ? x : v.x;
1402         this.y = y > v.y ? y : v.y;
1403         this.z = z > v.z ? z : v.z;
1404         return this;
1405     }
1406 
1407     public Vector3d max(Vector3d v, ref Vector3d dest) {
1408         dest.x = x > v.x ? x : v.x;
1409         dest.y = y > v.y ? y : v.y;
1410         dest.z = z > v.z ? z : v.z;
1411         return dest;
1412     }
1413 
1414     /**
1415      * Set all components to zero.
1416      * 
1417      * @return this
1418      */
1419     ref public Vector3d zero() return {
1420         this.x = 0;
1421         this.y = 0;
1422         this.z = 0;
1423         return this;
1424     }
1425 
1426     /**
1427      * Negate this vector.
1428      * 
1429      * @return this
1430      */
1431     ref public Vector3d negate() return {
1432         this.x = -x;
1433         this.y = -y;
1434         this.z = -z;
1435         return this;
1436     }
1437 
1438     public Vector3d negate(ref Vector3d dest) {
1439         dest.x = -x;
1440         dest.y = -y;
1441         dest.z = -z;
1442         return dest;
1443     }
1444 
1445     /**
1446      * Set <code>this</code> vector's components to their respective absolute values.
1447      * 
1448      * @return this
1449      */
1450     ref public Vector3d absolute() return {
1451         this.x = Math.abs(this.x);
1452         this.y = Math.abs(this.y);
1453         this.z = Math.abs(this.z);
1454         return this;
1455     }
1456 
1457     public Vector3d absolute(ref Vector3d dest) {
1458         dest.x = Math.abs(this.x);
1459         dest.y = Math.abs(this.y);
1460         dest.z = Math.abs(this.z);
1461         return dest;
1462     }
1463 
1464     public int hashCode() {
1465         immutable int prime = 31;
1466         int result = 1;
1467         long temp;
1468         temp = Math.doubleToLongBits(x);
1469         result = prime * result + cast(int) (temp ^ (temp >>> 32));
1470         temp = Math.doubleToLongBits(y);
1471         result = prime * result + cast(int) (temp ^ (temp >>> 32));
1472         temp = Math.doubleToLongBits(z);
1473         result = prime * result + cast(int) (temp ^ (temp >>> 32));
1474         return result;
1475     }
1476 
1477 
1478     public bool equals(Vector3d v, double delta) {
1479         if (this == v)
1480             return true;
1481         if (!Math.equals(x, v.x, delta))
1482             return false;
1483         if (!Math.equals(y, v.y, delta))
1484             return false;
1485         if (!Math.equals(z, v.z, delta))
1486             return false;
1487         return true;
1488     }
1489 
1490     public bool equals(double x, double y, double z) {
1491         if (Math.doubleToLongBits(this.x) != Math.doubleToLongBits(x))
1492             return false;
1493         if (Math.doubleToLongBits(this.y) != Math.doubleToLongBits(y))
1494             return false;
1495         if (Math.doubleToLongBits(this.z) != Math.doubleToLongBits(z))
1496             return false;
1497         return true;
1498     }
1499 
1500     public bool equals(Vector3d other) {
1501         if (Math.doubleToLongBits(this.x) != Math.doubleToLongBits(other.x))
1502             return false;
1503         if (Math.doubleToLongBits(this.y) != Math.doubleToLongBits(other.y))
1504             return false;
1505         if (Math.doubleToLongBits(this.z) != Math.doubleToLongBits(other.z))
1506             return false;
1507         return true;
1508     }
1509 
1510     /**
1511      * Reflect this vector about the given normal vector.
1512      * 
1513      * @param normal
1514      *          the vector to reflect about
1515      * @return this
1516      */
1517     ref public Vector3d reflect(Vector3d normal) return {
1518         double x = normal.x;
1519         double y = normal.y;
1520         double z = normal.z;
1521         double dot = Math.fma(this.x, x, Math.fma(this.y, y, this.z * z));
1522         this.x = this.x - (dot + dot) * x;
1523         this.y = this.y - (dot + dot) * y;
1524         this.z = this.z - (dot + dot) * z;
1525         return this;
1526     }
1527 
1528     /**
1529      * Reflect this vector about the given normal vector.
1530      * 
1531      * @param x
1532      *          the x component of the normal
1533      * @param y
1534      *          the y component of the normal
1535      * @param z
1536      *          the z component of the normal
1537      * @return this
1538      */
1539     ref public Vector3d reflect(double x, double y, double z) return {
1540         double dot = Math.fma(this.x, x, Math.fma(this.y, y, this.z * z));
1541         this.x = this.x - (dot + dot) * x;
1542         this.y = this.y - (dot + dot) * y;
1543         this.z = this.z - (dot + dot) * z;
1544         return this;
1545     }
1546 
1547     public Vector3d reflect(Vector3d normal, ref Vector3d dest) {
1548         double x = normal.x;
1549         double y = normal.y;
1550         double z = normal.z;
1551         double dot = Math.fma(this.x, x, Math.fma(this.y, y, this.z * z));
1552         dest.x = this.x - (dot + dot) * x;
1553         dest.y = this.y - (dot + dot) * y;
1554         dest.z = this.z - (dot + dot) * z;
1555         return dest;
1556     }
1557 
1558     public Vector3d reflect(double x, double y, double z, ref Vector3d dest) {
1559         double dot = Math.fma(this.x, x, Math.fma(this.y, y, this.z * z));
1560         dest.x = this.x - (dot + dot) * x;
1561         dest.y = this.y - (dot + dot) * y;
1562         dest.z = this.z - (dot + dot) * z;
1563         return dest;
1564     }
1565 
1566     /**
1567      * Compute the half vector between this and the other vector.
1568      * 
1569      * @param other
1570      *          the other vector
1571      * @return this
1572      */
1573     ref public Vector3d half(Vector3d other) return {
1574         return this.set(this).add(other.x, other.y, other.z).normalize();
1575     }
1576 
1577     /**
1578      * Compute the half vector between this and the vector <code>(x, y, z)</code>.
1579      * 
1580      * @param x
1581      *          the x component of the other vector
1582      * @param y
1583      *          the y component of the other vector
1584      * @param z
1585      *          the z component of the other vector
1586      * @return this
1587      */
1588     ref public Vector3d half(double x, double y, double z) return {
1589         return this.set(this).add(x, y, z).normalize();
1590     }
1591 
1592     public Vector3d half(Vector3d other, ref Vector3d dest) {
1593         return dest.set(this).add(other.x, other.y, other.z).normalize();
1594     }
1595 
1596     public Vector3d half(double x, double y, double z, ref Vector3d dest) {
1597         return dest.set(this).add(x, y, z).normalize();
1598     }
1599 
1600     public Vector3d smoothStep(Vector3d v, double t, ref Vector3d dest) {
1601         double t2 = t * t;
1602         double t3 = t2 * t;
1603         dest.x = (x + x - v.x - v.x) * t3 + (3.0 * v.x - 3.0 * x) * t2 + x * t + x;
1604         dest.y = (y + y - v.y - v.y) * t3 + (3.0 * v.y - 3.0 * y) * t2 + y * t + y;
1605         dest.z = (z + z - v.z - v.z) * t3 + (3.0 * v.z - 3.0 * z) * t2 + z * t + z;
1606         return dest;
1607     }
1608 
1609     public Vector3d hermite(Vector3d t0, Vector3d v1, Vector3d t1, double t, ref Vector3d dest) {
1610         double t2 = t * t;
1611         double t3 = t2 * t;
1612         dest.x = (x + x - v1.x - v1.x + t1.x + t0.x) * t3 + (3.0 * v1.x - 3.0 * x - t0.x - t0.x - t1.x) * t2 + x * t + x;
1613         dest.y = (y + y - v1.y - v1.y + t1.y + t0.y) * t3 + (3.0 * v1.y - 3.0 * y - t0.y - t0.y - t1.y) * t2 + y * t + y;
1614         dest.z = (z + z - v1.z - v1.z + t1.z + t0.z) * t3 + (3.0 * v1.z - 3.0 * z - t0.z - t0.z - t1.z) * t2 + z * t + z;
1615         return dest;
1616     }
1617 
1618     /**
1619      * Linearly interpolate <code>this</code> and <code>other</code> using the given interpolation factor <code>t</code>
1620      * and store the result in <code>this</code>.
1621      * <p>
1622      * If <code>t</code> is <code>0.0</code> then the result is <code>this</code>. If the interpolation factor is <code>1.0</code>
1623      * then the result is <code>other</code>.
1624      * 
1625      * @param other
1626      *          the other vector
1627      * @param t
1628      *          the interpolation factor between 0.0 and 1.0
1629      * @return this
1630      */
1631     ref public Vector3d lerp(Vector3d other, double t) return {
1632         this.x = Math.fma(other.x - x, t, x);
1633         this.y = Math.fma(other.y - y, t, y);
1634         this.z = Math.fma(other.z - z, t, z);
1635         return this;
1636     }
1637 
1638     public Vector3d lerp(Vector3d other, double t, ref Vector3d dest) {
1639         dest.x = Math.fma(other.x - x, t, x);
1640         dest.y = Math.fma(other.y - y, t, y);
1641         dest.z = Math.fma(other.z - z, t, z);
1642         return dest;
1643     }
1644 
1645     public double get(int component) {
1646         switch (component) {
1647         case 0:
1648             return x;
1649         case 1:
1650             return y;
1651         case 2:
1652             return z;
1653         default:
1654             return 0;
1655         }
1656     }
1657 
1658     public Vector3i get(int mode, ref Vector3i dest) {
1659         dest.x = Math.roundUsing(this.x, mode);
1660         dest.y = Math.roundUsing(this.y, mode);
1661         dest.z = Math.roundUsing(this.z, mode);
1662         return dest;
1663     }
1664 
1665     public Vector3d get(ref Vector3d dest) {
1666         dest.x = this.x;
1667         dest.y = this.y;
1668         dest.z = this.z;
1669         return dest;
1670     }
1671 
1672     public int maxComponent() {
1673         double absX = Math.abs(x);
1674         double absY = Math.abs(y);
1675         double absZ = Math.abs(z);
1676         if (absX >= absY && absX >= absZ) {
1677             return 0;
1678         } else if (absY >= absZ) {
1679             return 1;
1680         }
1681         return 2;
1682     }
1683 
1684     public int minComponent() {
1685         double absX = Math.abs(x);
1686         double absY = Math.abs(y);
1687         double absZ = Math.abs(z);
1688         if (absX < absY && absX < absZ) {
1689             return 0;
1690         } else if (absY < absZ) {
1691             return 1;
1692         }
1693         return 2;
1694     }
1695 
1696     public Vector3d orthogonalize(Vector3d v, ref Vector3d dest) {
1697         /*
1698          * http://lolengine.net/blog/2013/09/21/picking-orthogonal-vector-combing-coconuts
1699          */
1700         double rx, ry, rz;
1701         if (Math.abs(v.x) > Math.abs(v.z)) {
1702             rx = -v.y;
1703             ry = v.x;
1704             rz = 0.0;
1705         } else {
1706             rx = 0.0;
1707             ry = -v.z;
1708             rz = v.y;
1709         }
1710         double invLen = Math.invsqrt(rx * rx + ry * ry + rz * rz);
1711         dest.x = rx * invLen;
1712         dest.y = ry * invLen;
1713         dest.z = rz * invLen;
1714         return dest;
1715     }
1716 
1717     /**
1718      * Transform <code>this</code> vector so that it is orthogonal to the given vector <code>v</code> and normalize the result.
1719      * <p>
1720      * Reference: <a href="https://en.wikipedia.org/wiki/Gram%E2%80%93Schmidt_process">Gram–Schmidt process</a>
1721      * 
1722      * @param v
1723      *          the reference vector which the result should be orthogonal to
1724      * @return this
1725      */
1726     ref public Vector3d orthogonalize(Vector3d v) return {
1727         orthogonalize(v, this);
1728         return this;
1729     }
1730 
1731     public Vector3d orthogonalizeUnit(Vector3d v, ref Vector3d dest) {
1732         return orthogonalize(v, dest);
1733     }
1734 
1735     /**
1736      * Transform <code>this</code> vector so that it is orthogonal to the given unit vector <code>v</code> and normalize the result.
1737      * <p>
1738      * The vector <code>v</code> is assumed to be a {@link #normalize() unit} vector.
1739      * <p>
1740      * Reference: <a href="https://en.wikipedia.org/wiki/Gram%E2%80%93Schmidt_process">Gram–Schmidt process</a>
1741      * 
1742      * @param v
1743      *          the reference unit vector which the result should be orthogonal to
1744      * @return this
1745      */
1746     ref public Vector3d orthogonalizeUnit(Vector3d v) return {
1747         orthogonalizeUnit(v, this);
1748         return this;
1749     }
1750 
1751     /**
1752      * Set each component of this vector to the largest (closest to positive
1753      * infinity) {@code double} value that is less than or equal to that
1754      * component and is equal to a mathematical integer.
1755      *
1756      * @return this
1757      */
1758     ref public Vector3d floor() return {
1759         this.x = Math.floor(x);
1760         this.y = Math.floor(y);
1761         this.z = Math.floor(z);
1762         return this;
1763     }
1764 
1765     public Vector3d floor(ref Vector3d dest) {
1766         dest.x = Math.floor(x);
1767         dest.y = Math.floor(y);
1768         dest.z = Math.floor(z);
1769         return dest;
1770     }
1771 
1772     /**
1773      * Set each component of this vector to the smallest (closest to negative
1774      * infinity) {@code double} value that is greater than or equal to that
1775      * component and is equal to a mathematical integer.
1776      *
1777      * @return this
1778      */
1779     ref public Vector3d ceil() return {
1780         this.x = Math.ceil(x);
1781         this.y = Math.ceil(y);
1782         this.z = Math.ceil(z);
1783         return this;
1784     }
1785 
1786     public Vector3d ceil(ref Vector3d dest) {
1787         dest.x = Math.ceil(x);
1788         dest.y = Math.ceil(y);
1789         dest.z = Math.ceil(z);
1790         return dest;
1791     }
1792 
1793     /**
1794      * Set each component of this vector to the closest double that is equal to
1795      * a mathematical integer, with ties rounding to positive infinity.
1796      *
1797      * @return this
1798      */
1799     ref public Vector3d round() return {
1800         this.x = Math.round(x);
1801         this.y = Math.round(y);
1802         this.z = Math.round(z);
1803         return this;
1804     }
1805 
1806     public Vector3d round(ref Vector3d dest) {
1807         dest.x = Math.round(x);
1808         dest.y = Math.round(y);
1809         dest.z = Math.round(z);
1810         return dest;
1811     }
1812 
1813     public bool isFinite() {
1814         return Math.isFinite(x) && Math.isFinite(y) && Math.isFinite(z);
1815     }
1816 }