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