1use crate::float_vector::FloatVector;
9use crate::raw::RawVector_f32;
10use crate::sse_extensions::*;
11use crate::structure::SIMDVector2;
12use crate::vector2_bool::Vector2Bool;
13use crate::vector2_int::Vector2Int;
14use crate::vector3::Vector3;
15use crate::vector4::Vector4;
16use core::arch::x86_64::*;
17
18#[derive(Copy, Clone, Debug)]
20#[repr(C, align(16))]
21pub struct Vector2 {
22 pub data: __m128,
23}
24
25impl Vector2 {
26 #[inline(always)]
28 pub fn new(x: f32, y: f32) -> Vector2 {
29 unsafe {
30 Vector2 {
31 data: _mm_set_ps(0.0f32, 0.0f32, y, x),
32 }
33 }
34 }
35
36 #[inline(always)]
38 pub fn set<T: Into<FloatVector>>(value: T) -> Vector2 {
39 return Vector2 {
40 data: value.into().data,
41 };
42 }
43
44 #[inline(always)]
46 pub fn zero() -> Vector2 {
47 unsafe {
48 Vector2 {
49 data: _mm_setzero_ps(),
50 }
51 }
52 }
53
54 #[inline(always)]
56 pub fn x(self) -> FloatVector {
57 return FloatVector {
58 data: self.xxxx().data,
59 };
60 }
61
62 #[inline(always)]
64 pub fn y(self) -> FloatVector {
65 return FloatVector {
66 data: self.yyyy().data,
67 };
68 }
69 #[inline(always)]
71 pub fn load(raw: &RawVector_f32) -> Vector2 {
72 unsafe {
73 return Vector2 {
75 data: _mm_load_ps(core::mem::transmute(raw)),
76 };
77 }
78 }
79
80 #[inline(always)]
82 pub fn store(self, dst: &mut RawVector_f32) {
83 unsafe {
84 _mm_store_ps(core::mem::transmute(dst), self.data);
86 }
87 }
88
89 #[inline(always)]
91 pub fn set_x<T: Into<FloatVector>>(&mut self, value: T) {
92 unsafe {
93 self.data = _mm_move_ss(self.data, value.into().data);
94 }
95 }
96
97 #[inline(always)]
99 pub fn set_y<T: Into<FloatVector>>(&mut self, value: T) {
100 unsafe {
101 let v1 = _mm_move_ss(value.into().data, self.data);
102 self.data = _mm_shuffle_ps(v1, self.data, _ico_shuffle(3, 2, 1, 0));
103 }
104 }
105
106 #[inline(always)]
108 pub fn dot(self, v1: Vector2) -> FloatVector {
109 unsafe {
110 let tmp0 = _mm_mul_ps(self.data, v1.data);
111 let mut tmp1 = _yxzw(tmp0); tmp1 = _mm_add_ps(tmp0, tmp1); return FloatVector {
115 data: _mm_unpacklo_ps(tmp1, tmp1),
116 }; }
118 }
119
120 #[inline(always)]
123 pub fn rotate<T: Into<FloatVector>>(self, radians: T) -> Vector2 {
124 let tmp = radians.into();
125 let sn = tmp.sin().value();
130 let mut sncs = Vector4::from(tmp.cos());
131 sncs.set_z(sn);
132 sncs.set_w(-sn);
133 unsafe {
134 let epsilon = _mm_set1_ps(ABSOLUTE_COMPARISON_EPSILON);
136 let mask = _mm_cmpgt_ps(_ico_abs_ps(sncs.data), epsilon);
138
139 let masked_sncs = _mm_and_ps(sncs.data, mask);
140
141 let xyxy = _mm_movelh_ps(self.data, self.data);
143 let v2 = _mm_mul_ps(xyxy, masked_sncs);
145
146 return Vector2 {
150 data: _mm_add_ps(v2, _wzyx(v2)),
151 }; }
153 }
154
155 #[inline(always)]
157 pub fn add(self, v2: Vector2) -> Vector2 {
158 unsafe {
159 Vector2 {
160 data: _mm_add_ps(self.data, v2.data),
161 }
162 }
163 }
164
165 #[inline(always)]
167 pub fn sub(self, v2: Vector2) -> Vector2 {
168 unsafe {
169 Vector2 {
170 data: _mm_sub_ps(self.data, v2.data),
171 }
172 }
173 }
174
175 #[inline(always)]
178 pub fn mul(self, v2: Vector2) -> Vector2 {
179 unsafe {
180 Vector2 {
181 data: _mm_mul_ps(self.data, v2.data),
182 }
183 }
184 }
185
186 #[inline(always)]
189 pub fn div(self, v2: Vector2) -> Vector2 {
190 unsafe {
191 Vector2 {
192 data: _mm_div_ps(self.data, v2.data),
193 }
194 }
195 }
196
197 #[inline(always)]
199 pub fn mul_add(self, v2: Vector2, v3: Vector2) -> Vector2 {
200 unsafe {
201 return Vector2 {
202 data: _mm_fmadd_ps(self.data, v2.data, v3.data),
203 };
204 }
205 }
206
207 #[inline(always)]
209 pub fn mul_sub(self, v2: Vector2, v3: Vector2) -> Vector2 {
210 unsafe {
211 return Vector2 {
212 data: _mm_fmsub_ps(self.data, v2.data, v3.data),
213 };
214 }
215 }
216
217 #[inline(always)]
219 pub fn neg_mul_add(self, v2: Vector2, v3: Vector2) -> Vector2 {
220 unsafe {
221 return Vector2 {
222 data: _mm_fnmadd_ps(self.data, v2.data, v3.data),
223 };
224 }
225 }
226
227 #[inline(always)]
229 pub fn neg_mul_sub(self, v2: Vector2, v3: Vector2) -> Vector2 {
230 unsafe {
231 return Vector2 {
232 data: _mm_fnmsub_ps(self.data, v2.data, v3.data),
233 };
234 }
235 }
236
237 #[inline(always)]
240 pub fn and<T: SIMDVector2>(self, v2: T) -> Vector2 {
241 unsafe {
242 Vector2 {
243 data: _mm_and_ps(self.data, v2.data()),
244 }
245 }
246 }
247
248 #[inline(always)]
251 pub fn or<T: SIMDVector2>(self, v2: T) -> Vector2 {
252 unsafe {
253 Vector2 {
254 data: _mm_or_ps(self.data, v2.data()),
255 }
256 }
257 }
258
259 #[inline(always)]
262 pub fn andnot<T: SIMDVector2>(self, v2: T) -> Vector2 {
263 unsafe {
264 Vector2 {
265 data: _mm_andnot_ps(self.data, v2.data()),
266 }
267 }
268 }
269
270 #[inline(always)]
273 pub fn xor<T: SIMDVector2>(self, v2: T) -> Vector2 {
274 unsafe {
275 Vector2 {
276 data: _mm_xor_ps(self.data, v2.data()),
277 }
278 }
279 }
280
281 #[inline(always)]
283 pub fn equal(self, v2: Vector2) -> Vector2Bool {
284 unsafe {
285 Vector2Bool {
286 data: _mm_castps_si128(_mm_cmpeq_ps(self.data, v2.data)),
287 }
288 }
289 }
290 #[inline(always)]
292 pub fn not_equal(self, v2: Vector2) -> Vector2Bool {
293 unsafe {
294 Vector2Bool {
295 data: _mm_castps_si128(_mm_cmpneq_ps(self.data, v2.data)),
296 }
297 }
298 }
299 #[inline(always)]
301 pub fn greater_equal(self, v2: Vector2) -> Vector2Bool {
302 unsafe {
303 Vector2Bool {
304 data: _mm_castps_si128(_mm_cmpge_ps(self.data, v2.data)),
305 }
306 }
307 }
308 #[inline(always)]
310 pub fn greater(self, v2: Vector2) -> Vector2Bool {
311 unsafe {
312 Vector2Bool {
313 data: _mm_castps_si128(_mm_cmpgt_ps(self.data, v2.data)),
314 }
315 }
316 }
317 #[inline(always)]
319 pub fn less_equal(self, v2: Vector2) -> Vector2Bool {
320 unsafe {
321 Vector2Bool {
322 data: _mm_castps_si128(_mm_cmple_ps(self.data, v2.data)),
323 }
324 }
325 }
326 #[inline(always)]
328 pub fn less(self, v2: Vector2) -> Vector2Bool {
329 unsafe {
330 Vector2Bool {
331 data: _mm_castps_si128(_mm_cmplt_ps(self.data, v2.data)),
332 }
333 }
334 }
335 #[inline(always)]
341 pub fn approx_equal(self, v2: Vector2) -> Vector2Bool {
342 let delta = (self - v2).abs();
343 let abs_a = self.abs();
344 let abs_b = v2.abs();
345 let epsilon_bound = (abs_a.max(abs_b) * RELATIVE_COMPARISON_EPSILON)
346 .max(Vector2::from(ABSOLUTE_COMPARISON_EPSILON));
347 return delta.less_equal(epsilon_bound);
348 }
349
350 #[inline(always)]
353 pub fn definitely_greater(self, v2: Vector2) -> Vector2Bool {
354 let delta = self.sub(v2);
355 let abs_a = self.abs();
356 let abs_b = v2.abs();
357 let epsilon_bound = (abs_a.max(abs_b) * RELATIVE_COMPARISON_EPSILON)
358 .max(Vector2::from(ABSOLUTE_COMPARISON_EPSILON));
359 return delta.greater(epsilon_bound);
360 }
361 #[inline(always)]
364 pub fn definitely_less(self, v2: Vector2) -> Vector2Bool {
365 let delta = v2.sub(self);
366 let abs_a = self.abs();
367 let abs_b = v2.abs();
368 let epsilon_bound = (abs_a.max(abs_b) * RELATIVE_COMPARISON_EPSILON)
369 .max(Vector2::from(ABSOLUTE_COMPARISON_EPSILON));
370 return delta.greater(epsilon_bound);
371 }
372 #[inline(always)]
374 pub fn abs(self) -> Vector2 {
375 unsafe {
376 Vector2 {
377 data: _ico_abs_ps(self.data),
378 }
379 }
380 }
381
382 #[inline(always)]
384 pub fn copysign(self, v2: Vector2) -> Vector2 {
385 unsafe {
386 Vector2 {
387 data: _ico_copysign_ps(self.data, v2.data),
388 }
389 }
390 }
391
392 #[inline(always)]
394 pub fn floor(self) -> Vector2 {
395 unsafe {
396 Vector2 {
397 data: _mm_floor_ps(self.data),
398 }
399 }
400 }
401
402 #[inline(always)]
404 pub fn ceil(self) -> Vector2 {
405 unsafe {
406 Vector2 {
407 data: _mm_ceil_ps(self.data),
408 }
409 }
410 }
411
412 #[inline(always)]
414 pub fn round(self) -> Vector2 {
415 unsafe {
416 Vector2 {
417 data: _mm_round_ps(self.data, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC),
418 }
419 }
420 }
421
422 #[inline(always)]
424 pub fn truncate(self) -> Vector2 {
425 unsafe {
426 Vector2 {
427 data: _mm_round_ps(self.data, _MM_FROUND_TO_ZERO | _MM_FROUND_NO_EXC),
428 }
429 }
430 }
431
432 #[inline(always)]
434 pub fn floor_to_int(self) -> Vector2Int {
435 unsafe {
436 Vector2Int {
437 data: _mm_cvttps_epi32(self.floor().data),
438 }
439 }
440 }
441
442 #[inline(always)]
444 pub fn ceil_to_int(self) -> Vector2Int {
445 unsafe {
446 Vector2Int {
447 data: _mm_cvttps_epi32(self.ceil().data),
448 }
449 }
450 }
451 #[inline(always)]
453 pub fn round_to_int(self) -> Vector2Int {
454 unsafe {
455 Vector2Int {
456 data: _mm_cvttps_epi32(self.round().data),
457 }
458 }
459 }
460
461 #[inline(always)]
463 pub fn truncate_to_int(self) -> Vector2Int {
464 unsafe {
465 Vector2Int {
466 data: _mm_cvttps_epi32(self.truncate().data),
467 }
468 }
469 }
470
471 #[inline(always)]
474 pub fn frac(self) -> Vector2 {
475 return Vector2::sub(self, Vector2::floor(self));
476 }
477
478 #[inline(always)]
480 pub fn sqrt(self) -> Vector2 {
481 unsafe {
482 Vector2 {
483 data: _mm_sqrt_ps(self.data),
484 }
485 }
486 }
487
488 #[inline(always)]
490 pub fn sin(self) -> Vector2 {
491 unsafe {
492 Vector2 {
493 data: _ico_sin_ps(self.data),
494 }
495 }
496 }
497
498 #[inline(always)]
500 pub fn cos(self) -> Vector2 {
501 unsafe {
502 Vector2 {
503 data: _ico_cos_ps(self.data),
504 }
505 }
506 }
507 #[inline(always)]
509 pub fn tan(self) -> Vector2 {
510 unsafe {
511 Vector2 {
512 data: _ico_tan_ps(self.data),
513 }
514 }
515 }
516 #[inline(always)]
518 pub fn acos(self) -> Vector2 {
519 unsafe {
520 Vector2 {
521 data: _ico_acos_ps(self.data),
522 }
523 }
524 }
525
526 #[inline(always)]
528 pub fn asin(self) -> Vector2 {
529 unsafe {
530 Vector2 {
531 data: _ico_asin_ps(self.data),
532 }
533 }
534 }
535 #[inline(always)]
536 pub fn atan2(self, x: Vector2) -> Vector2 {
537 unsafe {
538 Vector2 {
539 data: _ico_atan2_ps(self.data, x.data),
540 }
541 }
542 }
543 #[inline(always)]
545 pub fn max(self, v2: Vector2) -> Vector2 {
546 unsafe {
547 Vector2 {
548 data: _mm_max_ps(self.data, v2.data),
549 }
550 }
551 }
552
553 #[inline(always)]
555 pub fn min(self, v2: Vector2) -> Vector2 {
556 unsafe {
557 Vector2 {
558 data: _mm_min_ps(self.data, v2.data),
559 }
560 }
561 }
562
563 #[inline(always)]
564 pub fn horizontal_min(self) -> FloatVector {
565 let x = self.x();
566 return FloatVector {
567 data: x.min(self.y()).data,
568 };
569 }
570
571 #[inline(always)]
572 pub fn horizontal_max(self) -> FloatVector {
573 let x = self.x();
574 return FloatVector {
575 data: x.max(self.y()).data,
576 };
577 }
578
579 #[inline(always)]
581 pub fn select(self, v2: Vector2, mask: Vector2Bool) -> Vector2 {
582 unsafe {
583 Vector2 {
584 data: _ico_select_ps(self.data, v2.data, _mm_castsi128_ps(mask.data)),
585 }
586 }
587 }
588 #[inline(always)]
590 pub fn lerp<T: Into<FloatVector>>(self, v2: Vector2, t: T) -> Vector2 {
591 unsafe {
592 let t_val = t.into().data;
593 let tmp = _mm_fnmadd_ps(self.data, t_val, self.data); Vector2 {
595 data: _mm_fmadd_ps(v2.data, t_val, tmp),
596 } }
598 }
599
600 #[inline(always)]
602 pub fn normalize(self) -> Vector2 {
603 let length = FloatVector::sqrt(Vector2::dot(self, self));
604 let norm = Vector2::div(self, Vector2::from(length));
605
606 unsafe {
607 let result_length_sqr = Vector2::from(Vector2::dot(norm, norm));
609 let mask_less = Vector2::less(
610 result_length_sqr,
611 Vector2 {
612 data: _ico_two_ps(),
613 },
614 );
615 return Vector2::and(norm, mask_less);
616 }
617 }
618
619 #[inline(always)]
622 pub fn normalize_length(self) -> (Vector2, FloatVector) {
623 let length = FloatVector::sqrt(Vector2::dot(self, self));
624 let norm = Vector2::div(self, Vector2::from(length));
625
626 unsafe {
627 let result_length_sqr = Vector2::from(Vector2::dot(norm, norm));
629 let mask_less = Vector2::less(
630 result_length_sqr,
631 Vector2 {
632 data: _ico_two_ps(),
633 },
634 );
635 return (Vector2::and(norm, mask_less), length);
636 }
637 }
638
639 #[inline(always)]
641 pub fn sqr_magnitude(self) -> FloatVector {
642 return Vector2::dot(self, self);
643 }
644
645 #[inline(always)]
647 pub fn magnitude(self) -> FloatVector {
648 return FloatVector::sqrt(Vector2::dot(self, self));
649 }
650
651 #[inline(always)]
652 pub fn xxxx(self) -> Vector4 {
653 unsafe {
654 return Vector4 {
655 data: _xxxx(self.data),
656 };
657 }
658 }
659 #[inline(always)]
660 pub fn yyyy(self) -> Vector4 {
661 unsafe {
662 return Vector4 {
663 data: _yyyy(self.data),
664 };
665 }
666 }
667
668 #[inline(always)]
669 pub fn xx(self) -> Vector2 {
670 unsafe {
671 return Vector2 {
672 data: _xxzw(self.data),
673 };
674 }
675 }
676 #[inline(always)]
677 pub fn xy(self) -> Vector2 {
678 unsafe {
679 return Vector2 {
680 data: _xyzw(self.data),
681 };
682 }
683 }
684 #[inline(always)]
685 pub fn yx(self) -> Vector2 {
686 unsafe {
687 return Vector2 {
688 data: _yxzw(self.data),
689 };
690 }
691 }
692 #[inline(always)]
693 pub fn yy(self) -> Vector2 {
694 unsafe {
695 return Vector2 {
696 data: _yyzw(self.data),
697 };
698 }
699 }
700}
701
702impl From<f32> for Vector2 {
703 #[inline(always)]
704 fn from(v: f32) -> Vector2 {
705 return Vector2::set(v);
706 }
707}
708impl From<FloatVector> for Vector2 {
709 #[inline(always)]
710 fn from(v: FloatVector) -> Vector2 {
711 return Vector2 { data: v.data };
712 }
713}
714impl From<Vector3> for Vector2 {
715 #[inline(always)]
716 fn from(v: Vector3) -> Vector2 {
717 Vector2 { data: v.data }
718 }
719}
720impl From<Vector4> for Vector2 {
721 #[inline(always)]
722 fn from(v: Vector4) -> Vector2 {
723 Vector2 { data: v.data }
724 }
725}
726impl From<Vector2Int> for Vector2 {
727 #[inline(always)]
728 fn from(v: Vector2Int) -> Vector2 {
729 unsafe {
730 return Vector2 {
731 data: _mm_cvtepi32_ps(v.data),
732 };
733 }
734 }
735}
736
737impl core::ops::Add for Vector2 {
738 type Output = Vector2;
739 #[inline(always)]
740 fn add(self, _rhs: Vector2) -> Vector2 {
741 Vector2::add(self, _rhs)
742 }
743}
744impl core::ops::AddAssign for Vector2 {
745 #[inline(always)]
746 fn add_assign(&mut self, other: Vector2) {
747 *self = Vector2::add(*self, other)
748 }
749}
750impl core::ops::Sub for Vector2 {
751 type Output = Vector2;
752 #[inline(always)]
753 fn sub(self, _rhs: Vector2) -> Vector2 {
754 Vector2::sub(self, _rhs)
755 }
756}
757impl core::ops::SubAssign for Vector2 {
758 #[inline(always)]
759 fn sub_assign(&mut self, other: Vector2) {
760 *self = Vector2::sub(*self, other)
761 }
762}
763impl core::ops::Neg for Vector2 {
764 type Output = Vector2;
765 #[inline(always)]
766 fn neg(self) -> Self::Output {
767 unsafe {
768 return Vector2 {
769 data: _mm_xor_ps(_ico_signbit_ps(), self.data),
770 };
771 }
772 }
773}
774impl<T: Into<FloatVector>> core::ops::Mul<T> for Vector2 {
775 type Output = Vector2;
776 #[inline(always)]
777 fn mul(self, _rhs: T) -> Vector2 {
778 return Vector2::mul(self, Vector2::from(_rhs.into()));
779 }
780}
781impl<T: Into<FloatVector>> core::ops::MulAssign<T> for Vector2 {
782 #[inline(always)]
783 fn mul_assign(&mut self, _rhs: T) {
784 *self = Vector2::mul(*self, Vector2::from(_rhs.into()));
785 }
786}
787impl core::ops::Mul<Vector2> for FloatVector {
788 type Output = Vector2;
789 #[inline(always)]
790 fn mul(self: FloatVector, _rhs: Vector2) -> Vector2 {
791 return Vector2::mul(_rhs, Vector2::from(self));
792 }
793}
794
795impl<T: Into<FloatVector>> core::ops::Div<T> for Vector2 {
796 type Output = Vector2;
797 #[inline(always)]
798 fn div(self, _rhs: T) -> Vector2 {
799 return Vector2::div(self, Vector2::from(_rhs.into()));
800 }
801}
802impl core::ops::Div<Vector2> for FloatVector {
803 type Output = Vector2;
804 #[inline(always)]
805 fn div(self: FloatVector, _rhs: Vector2) -> Vector2 {
806 return Vector2::div(Vector2::from(self), _rhs);
807 }
808}
809impl<T: Into<FloatVector>> core::ops::DivAssign<T> for Vector2 {
810 #[inline(always)]
811 fn div_assign(&mut self, _rhs: T) {
812 *self = Vector2::div(*self, Vector2::from(_rhs.into()));
813 }
814}
815
816impl PartialEq for Vector2 {
817 #[inline(always)]
818 fn eq(&self, other: &Vector2) -> bool {
819 return Vector2::equal(*self, *other).all();
820 }
821}
822
823impl SIMDVector2 for Vector2 {
824 #[inline(always)]
825 fn data(self) -> __m128 {
826 return self.data;
827 }
828 #[inline(always)]
829 fn data_i(self) -> __m128i {
830 return unsafe { _mm_castps_si128(self.data) };
831 }
832}
833#[cfg(test)]
834mod test;