Browse Source

Added emulation of unary negation for convenience in simd.h.

David Piuva 3 years ago
parent
commit
e119193805
2 changed files with 25 additions and 0 deletions
  1. 23 0
      Source/DFPSR/base/simd.h
  2. 2 0
      Source/test/tests/SimdTest.cpp

+ 23 - 0
Source/DFPSR/base/simd.h

@@ -1637,6 +1637,29 @@
 		#endif
 	}
 
+	// Unary negation for convenience and code readability.
+	//   Before using unary negation, always check if:
+	//    * An addition can be turned into a subtraction?
+	//      x = -a + b
+	//      x = b - a
+	//    * A multiplying constant or scalar can be negated instead?
+	//      x = -b * 2
+	//      x = b * -2
+	inline F32x4 operator-(const F32x4& value) {
+		#ifdef USE_BASIC_SIMD
+			return F32x4(0) - value;
+		#else
+			return F32x4(-value.emulated[0], -value.emulated[1], -value.emulated[2], -value.emulated[3]);
+		#endif
+	}
+	inline I32x4 operator-(const I32x4& value) {
+		#ifdef USE_BASIC_SIMD
+			return I32x4(0.0f) - value;
+		#else
+			return I32x4(-value.emulated[0], -value.emulated[1], -value.emulated[2], -value.emulated[3]);
+		#endif
+	}
+
 	// Helper macros for generating the vector extract functions.
 	//   Having one function for each type and offset makes sure that the compiler gets an immediate integer within the valid range.
 	#ifdef USE_BASIC_SIMD

+ 2 - 0
Source/test/tests/SimdTest.cpp

@@ -168,6 +168,7 @@ START_TEST(Simd)
 	ASSERT_EQUAL(2.0f * F32x4(1.0f, 2.0f, 3.0f, 4.0f), F32x4(2.0f, 4.0f, 6.0f, 8.0f));
 	ASSERT_EQUAL(F32x4(1.0f, -2.0f, 3.0f, -4.0f) * -2.0f, F32x4(-2.0f, 4.0f, -6.0f, 8.0f));
 	ASSERT_EQUAL(F32x4(1.0f, -2.0f, 3.0f, -4.0f) * F32x4(1.0f, -2.0f, 3.0f, -4.0f), F32x4(1.0f, 4.0f, 9.0f, 16.0f));
+	ASSERT_EQUAL(-F32x4(1.0f, -2.0f, 3.0f, -4.0f), F32x4(-1.0f, 2.0f, -3.0f, 4.0f));
 
 	// I32x4 operations
 	ASSERT_EQUAL(I32x4(1, 2, -3, 4) + I32x4(-2, 4, 6, 8), I32x4(-1, 6, 3, 12));
@@ -176,6 +177,7 @@ START_TEST(Simd)
 	ASSERT_EQUAL(I32x4(1, 2, 3, 4) + I32x4(4), I32x4(5, 6, 7, 8));
 	ASSERT_EQUAL(I32x4(10) + I32x4(1, 2, 3, 4), I32x4(11, 12, 13, 14));
 	ASSERT_EQUAL(I32x4(-3, 6, -9, 12) * I32x4(1, 2, -3, -4), I32x4(-3, 12, 27, -48));
+	ASSERT_EQUAL(-I32x4(1, -2, 3, -4), I32x4(-1, 2, -3, 4));
 
 	// U32x4 operations
 	ASSERT_EQUAL(U32x4(1, 2, 3, 4) + U32x4(2, 4, 6, 8), U32x4(3, 6, 9, 12));