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