1 /**
2  * Contains the definition of a Vector comprising 4 ints and associated
3  * transformations.
4  *
5  * @author Richard Greenlees
6  * @author Kai Burjack
7  * @author Hans Uhlig
8  */
9 module doml.vector_4i;
10 
11 import Math = doml.math;
12 
13 import doml.vector_3i;
14 import doml.vector_2i;
15 import doml.vector_4d;
16 
17 
18 /*
19  * The MIT License
20  *
21  * Copyright (c) 2015-2021 Richard Greenlees
22  $@$ Translated by jordan4ibanez
23  *
24  * Permission is hereby granted, free of charge, to any person obtaining a copy
25  * of this software and associated documentation files (the "Software"), to deal
26  * in the Software without restriction, including without limitation the rights
27  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
28  * copies of the Software, and to permit persons to whom the Software is
29  * furnished to do so, subject to the following conditions:
30  *
31  * The above copyright notice and this permission notice shall be included in
32  * all copies or substantial portions of the Software.
33  *
34  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
35  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
36  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
37  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
38  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
39  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
40  * THE SOFTWARE.
41  */
42 
43 /**
44  * Contains the definition of a Vector comprising 4 ints and associated
45  * transformations.
46  *
47  * @author Richard Greenlees
48  * @author Kai Burjack
49  * @author Hans Uhlig
50  */
51 struct Vector4i {
52 
53     /**
54      * The x component of the vector.
55      */
56     int x = 0;
57     /**
58      * The y component of the vector.
59      */
60     int y = 0;
61     /**
62      * The z component of the vector.
63      */
64     int z = 0;
65     /**
66      * The w component of the vector.
67      */
68     int w = 1;
69 
70     /**
71      * Create a new {@link Vector4i} with the same values as <code>v</code>.
72      *
73      * @param v
74      *          the {@link Vector4i} to copy the values from
75      */
76     this(Vector4i v) {
77         this.x = v.x;
78         this.y = v.y;
79         this.z = v.z;
80         this.w = v.w;
81     }
82 
83     /**
84      * Create a new {@link Vector4i} with the first three components from the
85      * given <code>v</code> and the given <code>w</code>.
86      *
87      * @param v
88      *          the {@link Vector3i}
89      * @param w
90      *          the w component
91      */
92     this(Vector3i v, int w) {
93         this.x = v.x;
94         this.y = v.y;
95         this.z = v.z;
96         this.w = w;
97     }
98 
99     /**
100      * Create a new {@link Vector4i} with the first two components from the
101      * given <code>v</code> and the given <code>z</code>, and <code>w</code>.
102      *
103      * @param v
104      *          the {@link Vector2i}
105      * @param z
106      *          the z component
107      * @param w
108      *          the w component
109      */
110     this(Vector2i v, int z, int w) {
111         this.x = v.x;
112         this.y = v.y;
113         this.z = z;
114         this.w = w;
115     }
116 
117     /**
118      * Create a new {@link Vector4i} and initialize its components to the rounded value of
119      * the given vector.
120      *
121      * @param v
122      *          the {@link Vector4d} to round and copy the values from
123      * @param mode
124      *          the {@link RoundingMode} to use
125      */
126     this(Vector4d v, int mode) {
127         x = Math.roundUsing(v.x, mode);
128         y = Math.roundUsing(v.y, mode);
129         z = Math.roundUsing(v.z, mode);
130         w = Math.roundUsing(v.w, mode);
131     }
132 
133     /**
134      * Create a new {@link Vector4i} and initialize all four components with the
135      * given value.
136      *
137      * @param s
138      *          scalar value of all four components
139      */
140     this(int s) {
141         this.x = s;
142         this.y = s;
143         this.z = s;
144         this.w = s;
145     }
146 
147     /**
148      * Create a new {@link Vector4i} with the given component values.
149      *
150      * @param x
151      *          the x component
152      * @param y
153      *          the y component
154      * @param z
155      *          the z component
156      * @param w
157      *          the w component
158      */
159     this(int x, int y, int z, int w) {
160         this.x = x;
161         this.y = y;
162         this.z = z;
163         this.w = w;
164     }
165 
166     /**
167      * Create a new {@link Vector4i} and initialize its four components from the first
168      * four elements of the given array.
169      * 
170      * @param xyzw
171      *          the array containing at least four elements
172      */
173     this(int[] xyzw) {
174         this.x = xyzw[0];
175         this.y = xyzw[1];
176         this.z = xyzw[2];
177         this.w = xyzw[3];
178     }
179 
180     /**
181      * Set this {@link Vector4i} to the values of the given <code>v</code>.
182      *
183      * @param v
184      *          the vector whose values will be copied into this
185      * @return this
186      */
187     ref public Vector4i set(Vector4i v) return {
188         this.x = v.x;
189         this.y = v.y;
190         this.z = v.z;
191         this.w = v.w;
192         return this;
193     }
194 
195     /**
196      * Set this {@link Vector4i} to the values of v using {@link RoundingMode#TRUNCATE} rounding.
197      * <p>
198      * Note that due to the given vector <code>v</code> storing the components
199      * in double-precision, there is the possibility to lose precision.
200      *
201      * @param v
202      *          the vector to copy from
203      * @return this
204      */
205     ref public Vector4i set(Vector4d v) return {
206         this.x = cast(int) v.x;
207         this.y = cast(int) v.y;
208         this.z = cast(int) v.z;
209         this.w = cast(int) v.w;
210         return this;
211     }
212 
213     /**
214      * Set this {@link Vector4i} to the values of v using the given {@link RoundingMode}.
215      * <p>
216      * Note that due to the given vector <code>v</code> storing the components
217      * in double-precision, there is the possibility to lose precision.
218      *
219      * @param v
220      *          the vector to copy from
221      * @param mode
222      *          the {@link RoundingMode} to use
223      * @return this
224      */
225     ref public Vector4i set(Vector4d v, int mode) return {
226         this.x = Math.roundUsing(v.x, mode);
227         this.y = Math.roundUsing(v.y, mode);
228         this.z = Math.roundUsing(v.z, mode);
229         this.w = Math.roundUsing(v.w, mode);
230         return this;
231     }
232 
233     /**
234      * Set the first three components of this to the components of
235      * <code>v</code> and the last component to <code>w</code>.
236      *
237      * @param v
238      *          the {@link Vector3i} to copy
239      * @param w
240      *          the w component
241      * @return this
242      */
243     ref public Vector4i set(Vector3i v, int w) return {
244         this.x = v.x;
245         this.y = v.y;
246         this.z = v.z;
247         this.w = w;
248         return this;
249     }
250 
251     /**
252      * Sets the first two components of this to the components of given
253      * <code>v</code> and last two components to the given <code>z</code>, and
254      * <code>w</code>.
255      *
256      * @param v
257      *          the {@link Vector2i}
258      * @param z
259      *          the z component
260      * @param w
261      *          the w component
262      * @return this
263      */
264     ref public Vector4i set(Vector2i v, int z, int w) return {
265         this.x = v.x;
266         this.y = v.y;
267         this.z = z;
268         this.w = w;
269         return this;
270     }
271 
272     /**
273      * Set the x, y, z, and w components to the supplied value.
274      *
275      * @param s
276      *          the value of all four components
277      * @return this
278      */
279     ref public Vector4i set(int s) return {
280         this.x = s;
281         this.y = s;
282         this.z = s;
283         this.w = s;
284         return this;
285     }
286 
287     /**
288      * Set the x, y, z, and w components to the supplied values.
289      *
290      * @param x
291      *          the x component
292      * @param y
293      *          the y component
294      * @param z
295      *          the z component
296      * @param w
297      *          the w component
298      * @return this
299      */
300     ref public Vector4i set(int x, int y, int z, int w) return {
301         this.x = x;
302         this.y = y;
303         this.z = z;
304         this.w = w;
305         return this;
306     }
307 
308     /**
309      * Set the four components of this vector to the first four elements of the given array.
310      * 
311      * @param xyzw
312      *          the array containing at least four elements
313      * @return this
314      */
315     ref public Vector4i set(int[] xyzw) return {
316         this.x = xyzw[0];
317         this.y = xyzw[1];
318         this.z = xyzw[2];
319         this.w = xyzw[3];
320         return this;
321     }
322 
323     public int get(int component) {
324         switch (component) {
325         case 0:
326             return x;
327         case 1:
328             return y;
329         case 2:
330             return z;
331         case 3:
332             return w;
333         default:
334             return 0; // do nothing
335         }
336     }
337 
338     public int maxComponent() {
339         int absX = Math.abs(x);
340         int absY = Math.abs(y);
341         int absZ = Math.abs(z);
342         int absW = Math.abs(w);
343         if (absX >= absY && absX >= absZ && absX >= absW) {
344             return 0;
345         } else if (absY >= absZ && absY >= absW) {
346             return 1;
347         } else if (absZ >= absW) {
348             return 2;
349         }
350         return 3;
351     }
352 
353     public int minComponent() {
354         int absX = Math.abs(x);
355         int absY = Math.abs(y);
356         int absZ = Math.abs(z);
357         int absW = Math.abs(w);
358         if (absX < absY && absX < absZ && absX < absW) {
359             return 0;
360         } else if (absY < absZ && absY < absW) {
361             return 1;
362         } else if (absZ < absW) {
363             return 2;
364         }
365         return 3;
366     }
367 
368     /**
369      * Set the value of the specified component of this vector.
370      *
371      * @param component
372      *          the component whose value to set, within <code>[0..3]</code>
373      * @param value
374      *          the value to set
375      * @return this
376      * @throws IllegalArgumentException if <code>component</code> is not within <code>[0..3]</code>
377      */
378     ref public Vector4i setComponent(int component, int value) return {
379         switch (component) {
380             case 0:
381                 x = value;
382                 break;
383             case 1:
384                 y = value;
385                 break;
386             case 2:
387                 z = value;
388                 break;
389             case 3:
390                 w = value;
391                 break;
392             default: {}
393         }
394         return this;
395     }
396 
397     /**
398      * Subtract the supplied vector from this one.
399      *
400      * @param v
401      *          the vector to subtract
402      * @return this
403      */
404     ref public Vector4i sub(Vector4i v) return {
405         this.x = this.x - v.x;
406         this.y = this.y - v.y;
407         this.z = this.z - v.z;
408         this.w = this.w - v.w;
409         return this;
410     }
411 
412     /**
413      * Subtract <code>(x, y, z, w)</code> from this.
414      *
415      * @param x
416      *          the x component to subtract
417      * @param y
418      *          the y component to subtract
419      * @param z
420      *          the z component to subtract
421      * @param w
422      *          the w component to subtract
423      * @return this
424      */
425     ref public Vector4i sub(int x, int y, int z, int w) return {
426         this.x = this.x - x;
427         this.y = this.y - y;
428         this.z = this.z - z;
429         this.w = this.w - w;
430         return this;
431     }
432 
433     public Vector4i sub(Vector4i v, ref Vector4i dest) {
434         dest.x = this.x - v.x;
435         dest.y = this.y - v.y;
436         dest.z = this.z - v.z;
437         dest.w = this.w - v.w;
438         return dest;
439     }
440 
441     public Vector4i sub(int x, int y, int z, int w, ref Vector4i dest) {
442         dest.x = this.x - x;
443         dest.y = this.y - y;
444         dest.z = this.z - z;
445         dest.w = this.w - w;
446         return dest;
447     }
448 
449     /**
450      * Add the supplied vector to this one.
451      *
452      * @param v
453      *          the vector to add
454      * @return this
455      */
456     ref public Vector4i add(Vector4i v) return {
457         this.x = this.x + v.x;
458         this.y = this.y + v.y;
459         this.z = this.z + v.z;
460         this.w = this.w + v.w;
461         return this;
462     }
463 
464     public Vector4i add(Vector4i v, ref Vector4i dest) {
465         dest.x = this.x + v.x;
466         dest.y = this.y + v.y;
467         dest.z = this.z + v.z;
468         dest.w = this.w + v.w;
469         return dest;
470     }
471 
472     /**
473      * Increment the components of this vector by the given values.
474      *
475      * @param x
476      *          the x component to add
477      * @param y
478      *          the y component to add
479      * @param z
480      *          the z component to add
481      * @param w
482      *          the w component to add
483      * @return this
484      */
485     ref public Vector4i add(int x, int y, int z, int w) return {
486         this.x = this.x + x;
487         this.y = this.y + y;
488         this.z = this.z + z;
489         this.w = this.w + w;
490         return this;
491     }
492 
493     public Vector4i add(int x, int y, int z, int w, ref Vector4i dest) {
494         dest.x = this.x + x;
495         dest.y = this.y + y;
496         dest.z = this.z + z;
497         dest.w = this.w + w;
498         return dest;
499     }
500 
501     /**
502      * Multiply this Vector4i component-wise by another Vector4i.
503      *
504      * @param v
505      *          the other vector
506      * @return this
507      */
508     ref public Vector4i mul(Vector4i v) return {
509         this.x = x * v.x;
510         this.y = y * v.y;
511         this.z = z * v.z;
512         this.w = w * v.w;
513         return this;
514     }
515 
516     public Vector4i mul(Vector4i v, ref Vector4i dest) {
517         dest.x = x * v.x;
518         dest.y = y * v.y;
519         dest.z = z * v.z;
520         dest.w = w * v.w;
521         return dest;
522     }
523 
524     /**
525      * Divide this Vector4i component-wise by another Vector4i.
526      *
527      * @param v
528      *          the vector to divide by
529      * @return this
530      */
531     ref public Vector4i div(Vector4i v) return {
532         this.x = x / v.x;
533         this.y = y / v.y;
534         this.z = z / v.z;
535         this.w = w / v.w;
536         return this;
537     }
538 
539     public Vector4i div(Vector4i v, ref Vector4i dest) {
540         dest.x = x / v.x;
541         dest.y = y / v.y;
542         dest.z = z / v.z;
543         dest.w = w / v.w;
544         return dest;
545     }
546 
547     /**
548      * Multiply all components of this {@link Vector4i} by the given scalar
549      * value.
550      *
551      * @param scalar
552      *          the scalar to multiply by
553      * @return this
554      */
555     ref public Vector4i mul(int scalar) return {
556         this.x = x * scalar;
557         this.y = y * scalar;
558         this.z = z * scalar;
559         this.w = w * scalar;
560         return this;
561     }
562 
563     public Vector4i mul(int scalar, ref Vector4i dest) {
564         dest.x = x * scalar;
565         dest.y = y * scalar;
566         dest.z = z * scalar;
567         dest.w = w * scalar;
568         return dest;
569     }
570 
571     /**
572      * Divide all components of this {@link Vector3i} by the given scalar value.
573      *
574      * @param scalar
575      *          the scalar to divide by
576      * @return this
577      */
578     ref public Vector4i div(double scalar) return {
579         double invscalar = 1.0f / scalar;
580         this.x = cast(int) (x * invscalar);
581         this.y = cast(int) (y * invscalar);
582         this.z = cast(int) (z * invscalar);
583         this.w = cast(int) (w * invscalar);
584         return this;
585     }
586 
587     public Vector4i div(double scalar, ref Vector4i dest) {
588         double invscalar = 1.0f / scalar;
589         dest.x = cast(int) (x * invscalar);
590         dest.y = cast(int) (y * invscalar);
591         dest.z = cast(int) (z * invscalar);
592         dest.w = cast(int) (w * invscalar);
593         return dest;
594     }
595 
596     /**
597      * Divide all components of this {@link Vector4i} by the given scalar value.
598      *
599      * @param scalar
600      *          the scalar to divide by
601      * @return this
602      */
603     ref public Vector4i div(int scalar) return {
604         this.x = x / scalar;
605         this.y = y / scalar;
606         this.z = z / scalar;
607         this.w = w / scalar;
608         return this;
609     }
610 
611     public Vector4i div(int scalar, ref Vector4i dest) {
612         dest.x = x / scalar;
613         dest.y = y / scalar;
614         dest.z = z / scalar;
615         dest.w = w / scalar;
616         return dest;
617     }
618 
619     public long lengthSquared() {
620         return x * x + y * y + z * z + w * w;
621     }
622 
623     /**
624      * Get the length squared of a 4-dimensional single-precision vector.
625      *
626      * @param x The vector's x component
627      * @param y The vector's y component
628      * @param z The vector's z component
629      * @param w The vector's w component
630      *
631      * @return the length squared of the given vector
632      */
633     public static long lengthSquared(int x, int y, int z, int w) {
634         return x * x + y * y + z * z + w * w;
635     }
636 
637     public double length() {
638         return Math.sqrt(x * x + y * y + z * z + w * w);
639     }
640 
641     /**
642      * Get the length of a 4-dimensional single-precision vector.
643      *
644      * @param x The vector's x component
645      * @param y The vector's y component
646      * @param z The vector's z component
647      * @param w The vector's w component
648      *
649      * @return the length squared of the given vector
650      */
651     public static double length(int x, int y, int z, int w) {
652         return Math.sqrt(x * x + y * y + z * z + w * w);
653     }
654 
655     public double distance(Vector4i v) {
656         int dx = this.x - v.x;
657         int dy = this.y - v.y;
658         int dz = this.z - v.z;
659         int dw = this.w - v.w;
660         return Math.sqrt(Math.fma(dx, dx, Math.fma(dy, dy, Math.fma(dz, dz, dw * dw))));
661     }
662 
663     public double distance(int x, int y, int z, int w) {
664         int dx = this.x - x;
665         int dy = this.y - y;
666         int dz = this.z - z;
667         int dw = this.w - w;
668         return Math.sqrt(Math.fma(dx, dx, Math.fma(dy, dy, Math.fma(dz, dz, dw * dw))));
669     }
670 
671     public long gridDistance(Vector4i v) {
672         return Math.abs(v.x - this.x) + Math.abs(v.y - this.y)  + Math.abs(v.z - this.z)  + Math.abs(v.w - this.w);
673     }
674 
675     public long gridDistance(int x, int y, int z, int w) {
676         return Math.abs(x - this.x) + Math.abs(y - this.y) + Math.abs(z - this.z) + Math.abs(w - this.w);
677     }
678 
679     public int distanceSquared(Vector4i v) {
680         int dx = this.x - v.x;
681         int dy = this.y - v.y;
682         int dz = this.z - v.z;
683         int dw = this.w - v.w;
684         return dx * dx + dy * dy + dz * dz + dw * dw;
685     }
686 
687     public int distanceSquared(int x, int y, int z, int w) {
688         int dx = this.x - x;
689         int dy = this.y - y;
690         int dz = this.z - z;
691         int dw = this.w - w;
692         return dx * dx + dy * dy + dz * dz + dw * dw;
693     }
694 
695     /**
696      * Return the distance between <code>(x1, y1, z1, w1)</code> and <code>(x2, y2, z2, w2)</code>.
697      *
698      * @param x1
699      *          the x component of the first vector
700      * @param y1
701      *          the y component of the first vector
702      * @param z1
703      *          the z component of the first vector
704      * @param w1
705      *          the w component of the first vector
706      * @param x2
707      *          the x component of the second vector
708      * @param y2
709      *          the y component of the second vector
710      * @param z2
711      *          the z component of the second vector
712      * @param w2
713      *          the 2 component of the second vector
714      * @return the euclidean distance
715      */
716     public static double distance(int x1, int y1, int z1, int w1, int x2, int y2, int z2, int w2) {
717         int dx = x1 - x2;
718         int dy = y1 - y2;
719         int dz = z1 - z2;
720         int dw = w1 - w2;
721         return Math.sqrt(dx * dx + dy * dy + dz * dz + dw * dw);
722     }
723 
724     /**
725      * Return the squared distance between <code>(x1, y1, z1, w1)</code> and <code>(x2, y2, z2, w2)</code>.
726      *
727      * @param x1
728      *          the x component of the first vector
729      * @param y1
730      *          the y component of the first vector
731      * @param z1
732      *          the z component of the first vector
733      * @param w1
734      *          the w component of the first vector
735      * @param x2
736      *          the x component of the second vector
737      * @param y2
738      *          the y component of the second vector
739      * @param z2
740      *          the z component of the second vector
741      * @param w2
742      *          the w component of the second vector
743      * @return the euclidean distance squared
744      */
745     public static long distanceSquared(int x1, int y1, int z1, int w1, int x2, int y2, int z2, int w2) {
746         int dx = x1 - x2;
747         int dy = y1 - y2;
748         int dz = z1 - z2;
749         int dw = w1 - w2;
750         return dx * dx + dy * dy + dz * dz + dw * dw;
751     }
752 
753     public int dot(Vector4i v) {
754         return x * v.x + y * v.y + z * v.z + w * v.w;
755     }
756 
757     /**
758      * Set all components to zero.
759      *
760      * @return this
761      */
762     ref public Vector4i zero() return {
763         x = 0;
764         y = 0;
765         z = 0;
766         w = 0;
767         return this;
768     }
769 
770     /**
771      * Negate this vector.
772      *
773      * @return this
774      */
775     ref public Vector4i negate() return {
776         this.x = -x;
777         this.y = -y;
778         this.z = -z;
779         this.w = -w;
780         return this;
781     }
782 
783     public Vector4i negate(ref Vector4i dest) {
784         dest.x = -x;
785         dest.y = -y;
786         dest.z = -z;
787         dest.w = -w;
788         return dest;
789     }
790 
791     /**
792      * Set the components of this vector to be the component-wise minimum of this and the other vector.
793      *
794      * @param v
795      *          the other vector
796      * @return this
797      */
798     ref public Vector4i min(Vector4i v) return {
799         this.x = x < v.x ? x : v.x;
800         this.y = y < v.y ? y : v.y;
801         this.z = z < v.z ? z : v.z;
802         this.w = w < v.w ? w : v.w;
803         return this;
804     }
805 
806     public Vector4i min(Vector4i v, ref Vector4i dest) {
807         dest.x = x < v.x ? x : v.x;
808         dest.y = y < v.y ? y : v.y;
809         dest.z = z < v.z ? z : v.z;
810         dest.w = w < v.w ? w : v.w;
811         return dest;
812     }
813 
814     /**
815      * Set the components of this vector to be the component-wise maximum of this and the other vector.
816      *
817      * @param v
818      *          the other vector
819      * @return this
820      */
821     ref public Vector4i max(Vector4i v) return {
822         this.x = x > v.x ? x : v.x;
823         this.y = y > v.y ? y : v.y;
824         this.z = z > v.z ? z : v.z;
825         this.w = w > v.w ? w : v.w;
826         return this;
827     }
828 
829     public Vector4i max(Vector4i v, ref Vector4i dest) {
830         dest.x = x > v.x ? x : v.x;
831         dest.y = y > v.y ? y : v.y;
832         dest.z = z > v.z ? z : v.z;
833         dest.w = w > v.w ? w : v.w;
834         return dest;
835     }
836 
837     /**
838      * Compute the absolute of each of this vector's components.
839      * 
840      * @return this
841      */
842     ref public Vector4i absolute() return {
843         this.x = Math.abs(x);
844         this.y = Math.abs(y);
845         this.z = Math.abs(z);
846         this.w = Math.abs(w);
847         return this;
848     }
849 
850     public Vector4i absolute(ref Vector4i dest) {
851         dest.x = Math.abs(x);
852         dest.y = Math.abs(y);
853         dest.z = Math.abs(z);
854         dest.w = Math.abs(w);
855         return dest;
856     }
857 
858     public int hashCode() {
859         immutable int prime = 31;
860         int result = 1;
861         result = prime * result + x;
862         result = prime * result + y;
863         result = prime * result + z;
864         result = prime * result + w;
865         return result;
866     }
867 
868     public bool equals(int x, int y, int z, int w) {
869         if (this.x != x)
870             return false;
871         if (this.y != y)
872             return false;
873         if (this.z != z)
874             return false;
875         if (this.w != w)
876             return false;
877         return true;
878     }
879 
880     public bool equals(Vector4i other) {
881         if (this.x != other.x)
882             return false;
883         if (this.y != other.y)
884             return false;
885         if (this.z != other.z)
886             return false;
887         if (this.w != other.w)
888             return false;
889         return true;
890     }
891 
892 }