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