We need to copy the matrix before altering it's contents: Fix a SGMathTest failure

This commit is contained in:
Erik Hofman
2017-02-03 15:07:35 +01:00
parent 3417ca7e49
commit 7f65e7f905
4 changed files with 92 additions and 66 deletions
+53 -50
View File
@@ -28,6 +28,9 @@
#include "SGRect.hxx" #include "SGRect.hxx"
#include "sg_random.h" #include "sg_random.h"
int lineno = 0;
template<typename T> template<typename T>
bool bool
Vec3Test(void) Vec3Test(void)
@@ -38,45 +41,45 @@ Vec3Test(void)
v1 = SGVec3<T>(1, 2, 3); v1 = SGVec3<T>(1, 2, 3);
v2 = SGVec3<T>(3, 2, 1); v2 = SGVec3<T>(3, 2, 1);
if (equivalent(v1, v2)) if (equivalent(v1, v2))
return false; { lineno = __LINE__; return false; }
// Check the unary minus operator // Check the unary minus operator
v3 = SGVec3<T>(-1, -2, -3); v3 = SGVec3<T>(-1, -2, -3);
if (!equivalent(-v1, v3)) if (!equivalent(-v1, v3))
return false; { lineno = __LINE__; return false; }
// Check the unary plus operator // Check the unary plus operator
v3 = SGVec3<T>(1, 2, 3); v3 = SGVec3<T>(1, 2, 3);
if (!equivalent(+v1, v3)) if (!equivalent(+v1, v3))
return false; { lineno = __LINE__; return false; }
// Check the addition operator // Check the addition operator
v3 = SGVec3<T>(4, 4, 4); v3 = SGVec3<T>(4, 4, 4);
if (!equivalent(v1 + v2, v3)) if (!equivalent(v1 + v2, v3))
return false; { lineno = __LINE__; return false; }
// Check the subtraction operator // Check the subtraction operator
v3 = SGVec3<T>(-2, 0, 2); v3 = SGVec3<T>(-2, 0, 2);
if (!equivalent(v1 - v2, v3)) if (!equivalent(v1 - v2, v3))
return false; { lineno = __LINE__; return false; }
// Check the scaler multiplication operator // Check the scaler multiplication operator
v3 = SGVec3<T>(2, 4, 6); v3 = SGVec3<T>(2, 4, 6);
if (!equivalent(2*v1, v3)) if (!equivalent(2*v1, v3))
return false; { lineno = __LINE__; return false; }
// Check the dot product // Check the dot product
if (fabs(dot(v1, v2) - 10) > 10*SGLimits<T>::epsilon()) if (fabs(dot(v1, v2) - 10) > 10*SGLimits<T>::epsilon())
return false; { lineno = __LINE__; return false; }
// Check the cross product // Check the cross product
v3 = SGVec3<T>(-4, 8, -4); v3 = SGVec3<T>(-4, 8, -4);
if (!equivalent(cross(v1, v2), v3)) if (!equivalent(cross(v1, v2), v3))
return false; { lineno = __LINE__; return false; }
// Check the euclidean length // Check the euclidean length
if (fabs(14 - length(v1)*length(v1)) > 14*SGLimits<T>::epsilon()) if (fabs(14 - length(v1)*length(v1)) > 14*SGLimits<T>::epsilon())
return false; { lineno = __LINE__; return false; }
return true; return true;
} }
@@ -89,11 +92,11 @@ isSameRotation(const SGQuat<T>& q1, const SGQuat<T>& q2)
const SGVec3<T> e2(0, 1, 0); const SGVec3<T> e2(0, 1, 0);
const SGVec3<T> e3(0, 0, 1); const SGVec3<T> e3(0, 0, 1);
if (!equivalent(q1.transform(e1), q2.transform(e1))) if (!equivalent(q1.transform(e1), q2.transform(e1)))
return false; { lineno = __LINE__; return false; }
if (!equivalent(q1.transform(e2), q2.transform(e2))) if (!equivalent(q1.transform(e2), q2.transform(e2)))
return false; { lineno = __LINE__; return false; }
if (!equivalent(q1.transform(e3), q2.transform(e3))) if (!equivalent(q1.transform(e3), q2.transform(e3)))
return false; { lineno = __LINE__; return false; }
return true; return true;
} }
@@ -111,37 +114,37 @@ QuatTest(void)
v1 = SGVec3<T>(1, 2, 3); v1 = SGVec3<T>(1, 2, 3);
v2 = SGVec3<T>(1, -2, -3); v2 = SGVec3<T>(1, -2, -3);
if (!equivalent(q1.transform(v1), v2)) if (!equivalent(q1.transform(v1), v2))
return false; { lineno = __LINE__; return false; }
// Check a rotation around the x axis // Check a rotation around the x axis
q1 = SGQuat<T>::fromAngleAxis(0.5*SGMisc<T>::pi(), e1); q1 = SGQuat<T>::fromAngleAxis(0.5*SGMisc<T>::pi(), e1);
v2 = SGVec3<T>(1, 3, -2); v2 = SGVec3<T>(1, 3, -2);
if (!equivalent(q1.transform(v1), v2)) if (!equivalent(q1.transform(v1), v2))
return false; { lineno = __LINE__; return false; }
// Check a rotation around the y axis // Check a rotation around the y axis
q1 = SGQuat<T>::fromAngleAxis(SGMisc<T>::pi(), e2); q1 = SGQuat<T>::fromAngleAxis(SGMisc<T>::pi(), e2);
v2 = SGVec3<T>(-1, 2, -3); v2 = SGVec3<T>(-1, 2, -3);
if (!equivalent(q1.transform(v1), v2)) if (!equivalent(q1.transform(v1), v2))
return false; { lineno = __LINE__; return false; }
// Check a rotation around the y axis // Check a rotation around the y axis
q1 = SGQuat<T>::fromAngleAxis(0.5*SGMisc<T>::pi(), e2); q1 = SGQuat<T>::fromAngleAxis(0.5*SGMisc<T>::pi(), e2);
v2 = SGVec3<T>(-3, 2, 1); v2 = SGVec3<T>(-3, 2, 1);
if (!equivalent(q1.transform(v1), v2)) if (!equivalent(q1.transform(v1), v2))
return false; { lineno = __LINE__; return false; }
// Check a rotation around the z axis // Check a rotation around the z axis
q1 = SGQuat<T>::fromAngleAxis(SGMisc<T>::pi(), e3); q1 = SGQuat<T>::fromAngleAxis(SGMisc<T>::pi(), e3);
v2 = SGVec3<T>(-1, -2, 3); v2 = SGVec3<T>(-1, -2, 3);
if (!equivalent(q1.transform(v1), v2)) if (!equivalent(q1.transform(v1), v2))
return false; { lineno = __LINE__; return false; }
// Check a rotation around the z axis // Check a rotation around the z axis
q1 = SGQuat<T>::fromAngleAxis(0.5*SGMisc<T>::pi(), e3); q1 = SGQuat<T>::fromAngleAxis(0.5*SGMisc<T>::pi(), e3);
v2 = SGVec3<T>(2, -1, 3); v2 = SGVec3<T>(2, -1, 3);
if (!equivalent(q1.transform(v1), v2)) if (!equivalent(q1.transform(v1), v2))
return false; { lineno = __LINE__; return false; }
// Now check some successive transforms // Now check some successive transforms
// We can reuse the prevously tested stuff // We can reuse the prevously tested stuff
@@ -150,7 +153,7 @@ QuatTest(void)
q3 = q1*q2; q3 = q1*q2;
v2 = q2.transform(q1.transform(v1)); v2 = q2.transform(q1.transform(v1));
if (!equivalent(q3.transform(v1), v2)) if (!equivalent(q3.transform(v1), v2))
return false; { lineno = __LINE__; return false; }
/// Test from Euler angles /// Test from Euler angles
float x = 0.2*SGMisc<T>::pi(); float x = 0.2*SGMisc<T>::pi();
@@ -162,7 +165,7 @@ QuatTest(void)
v2 = q3.transform(q2.transform(q1.transform(v1))); v2 = q3.transform(q2.transform(q1.transform(v1)));
q4 = SGQuat<T>::fromEulerRad(z, y, x); q4 = SGQuat<T>::fromEulerRad(z, y, x);
if (!equivalent(q4.transform(v1), v2)) if (!equivalent(q4.transform(v1), v2))
return false; { lineno = __LINE__; return false; }
/// Test angle axis forward and back transform /// Test angle axis forward and back transform
q1 = SGQuat<T>::fromAngleAxis(0.2*SGMisc<T>::pi(), e1); q1 = SGQuat<T>::fromAngleAxis(0.2*SGMisc<T>::pi(), e1);
@@ -172,15 +175,15 @@ QuatTest(void)
q1.getAngleAxis(angleAxis); q1.getAngleAxis(angleAxis);
q4 = SGQuat<T>::fromAngleAxis(angleAxis); q4 = SGQuat<T>::fromAngleAxis(angleAxis);
if (!isSameRotation(q1, q4)) if (!isSameRotation(q1, q4))
return false; { lineno = __LINE__; return false; }
q2.getAngleAxis(angleAxis); q2.getAngleAxis(angleAxis);
q4 = SGQuat<T>::fromAngleAxis(angleAxis); q4 = SGQuat<T>::fromAngleAxis(angleAxis);
if (!isSameRotation(q2, q4)) if (!isSameRotation(q2, q4))
return false; { lineno = __LINE__; return false; }
q3.getAngleAxis(angleAxis); q3.getAngleAxis(angleAxis);
q4 = SGQuat<T>::fromAngleAxis(angleAxis); q4 = SGQuat<T>::fromAngleAxis(angleAxis);
if (!isSameRotation(q3, q4)) if (!isSameRotation(q3, q4))
return false; { lineno = __LINE__; return false; }
/// Test angle axis forward and back transform /// Test angle axis forward and back transform
q1 = SGQuat<T>::fromAngleAxis(0.2*SGMisc<T>::pi(), e1); q1 = SGQuat<T>::fromAngleAxis(0.2*SGMisc<T>::pi(), e1);
@@ -189,15 +192,15 @@ QuatTest(void)
SGVec3<T> positiveAngleAxis = q1.getPositiveRealImag(); SGVec3<T> positiveAngleAxis = q1.getPositiveRealImag();
q4 = SGQuat<T>::fromPositiveRealImag(positiveAngleAxis); q4 = SGQuat<T>::fromPositiveRealImag(positiveAngleAxis);
if (!isSameRotation(q1, q4)) if (!isSameRotation(q1, q4))
return false; { lineno = __LINE__; return false; }
positiveAngleAxis = q2.getPositiveRealImag(); positiveAngleAxis = q2.getPositiveRealImag();
q4 = SGQuat<T>::fromPositiveRealImag(positiveAngleAxis); q4 = SGQuat<T>::fromPositiveRealImag(positiveAngleAxis);
if (!isSameRotation(q2, q4)) if (!isSameRotation(q2, q4))
return false; { lineno = __LINE__; return false; }
positiveAngleAxis = q3.getPositiveRealImag(); positiveAngleAxis = q3.getPositiveRealImag();
q4 = SGQuat<T>::fromPositiveRealImag(positiveAngleAxis); q4 = SGQuat<T>::fromPositiveRealImag(positiveAngleAxis);
if (!isSameRotation(q3, q4)) if (!isSameRotation(q3, q4))
return false; { lineno = __LINE__; return false; }
return true; return true;
} }
@@ -219,13 +222,13 @@ QuatDerivativeTest(void)
// Check if we can restore the angular velocity // Check if we can restore the angular velocity
SGVec3<T> av2 = SGQuat<T>::forwardDifferenceVelocity(o0, o1, dt); SGVec3<T> av2 = SGQuat<T>::forwardDifferenceVelocity(o0, o1, dt);
if (!equivalent(av, av2)) if (!equivalent(av, av2))
return false; { lineno = __LINE__; return false; }
// Test with the equivalent orientation // Test with the equivalent orientation
o1 = -o1; o1 = -o1;
av2 = SGQuat<T>::forwardDifferenceVelocity(o0, o1, dt); av2 = SGQuat<T>::forwardDifferenceVelocity(o0, o1, dt);
if (!equivalent(av, av2)) if (!equivalent(av, av2))
return false; { lineno = __LINE__; return false; }
} }
return true; return true;
} }
@@ -250,23 +253,23 @@ MatrixTest(void)
invert(m2, m0); invert(m2, m0);
m3 = transNeg(m0); m3 = transNeg(m0);
if (!equivalent(m1, m2)) if (!equivalent(m1, m2))
return false; { lineno = __LINE__; return false; }
if (!equivalent(m2, m3)) if (!equivalent(m2, m3))
return false; { lineno = __LINE__; return false; }
// Check matrix multiplication and inversion // Check matrix multiplication and inversion
if (!equivalent(m0*m1, SGMatrix<T>::unit())) if (!equivalent(m0*m1, SGMatrix<T>::unit()))
return false; { lineno = __LINE__; return false; }
if (!equivalent(m1*m0, SGMatrix<T>::unit())) if (!equivalent(m1*m0, SGMatrix<T>::unit()))
return false; { lineno = __LINE__; return false; }
if (!equivalent(m0*m2, SGMatrix<T>::unit())) if (!equivalent(m0*m2, SGMatrix<T>::unit()))
return false; { lineno = __LINE__; return false; }
if (!equivalent(m2*m0, SGMatrix<T>::unit())) if (!equivalent(m2*m0, SGMatrix<T>::unit()))
return false; { lineno = __LINE__; return false; }
if (!equivalent(m0*m3, SGMatrix<T>::unit())) if (!equivalent(m0*m3, SGMatrix<T>::unit()))
return false; { lineno = __LINE__; return false; }
if (!equivalent(m3*m0, SGMatrix<T>::unit())) if (!equivalent(m3*m0, SGMatrix<T>::unit()))
return false; { lineno = __LINE__; return false; }
return true; return true;
} }
@@ -320,13 +323,13 @@ GeodesyTest(void)
if (epsDeg < fabs(geod0.getLongitudeDeg() - geod1.getLongitudeDeg()) || if (epsDeg < fabs(geod0.getLongitudeDeg() - geod1.getLongitudeDeg()) ||
epsDeg < fabs(geod0.getLatitudeDeg() - geod1.getLatitudeDeg()) || epsDeg < fabs(geod0.getLatitudeDeg() - geod1.getLatitudeDeg()) ||
epsM < fabs(geod0.getElevationM() - geod1.getElevationM())) epsM < fabs(geod0.getElevationM() - geod1.getElevationM()))
return false; { lineno = __LINE__; return false; }
// Test the conversion routines to radial coordinates // Test the conversion routines to radial coordinates
geoc0 = SGGeoc::fromCart(cart0); geoc0 = SGGeoc::fromCart(cart0);
cart1 = SGVec3<double>::fromGeoc(geoc0); cart1 = SGVec3<double>::fromGeoc(geoc0);
if (!equivalent(cart0, cart1)) if (!equivalent(cart0, cart1))
return false; { lineno = __LINE__; return false; }
// test course / advance routines // test course / advance routines
// uses examples from Williams aviation formulary // uses examples from Williams aviation formulary
@@ -336,12 +339,12 @@ GeodesyTest(void)
double distNm = SGGeodesy::distanceRad(lax, jfk) * SG_RAD_TO_NM; double distNm = SGGeodesy::distanceRad(lax, jfk) * SG_RAD_TO_NM;
std::cout << "distance is " << distNm << std::endl; std::cout << "distance is " << distNm << std::endl;
if (0.5 < fabs(distNm - 2144)) // 2144 nm if (0.5 < fabs(distNm - 2144)) // 2144 nm
return false; { lineno = __LINE__; return false; }
double crsDeg = SGGeodesy::courseRad(lax, jfk) * SG_RADIANS_TO_DEGREES; double crsDeg = SGGeodesy::courseRad(lax, jfk) * SG_RADIANS_TO_DEGREES;
std::cout << "course is " << crsDeg << std::endl; std::cout << "course is " << crsDeg << std::endl;
if (0.5 < fabs(crsDeg - 66)) // 66 degrees if (0.5 < fabs(crsDeg - 66)) // 66 degrees
return false; { lineno = __LINE__; return false; }
SGGeoc adv; SGGeoc adv;
SGGeodesy::advanceRadM(lax, crsDeg * SG_DEGREES_TO_RADIANS, 100 * SG_NM_TO_METER, adv); SGGeodesy::advanceRadM(lax, crsDeg * SG_DEGREES_TO_RADIANS, 100 * SG_NM_TO_METER, adv);
@@ -349,7 +352,7 @@ GeodesyTest(void)
if (0.01 < fabs(adv.getLongitudeRad() - (-2.034206)) || if (0.01 < fabs(adv.getLongitudeRad() - (-2.034206)) ||
0.01 < fabs(adv.getLatitudeRad() - 0.604180)) 0.01 < fabs(adv.getLatitudeRad() - 0.604180))
return false; { lineno = __LINE__; return false; }
return true; return true;
} }
@@ -361,25 +364,25 @@ main(void)
// Do vector tests // Do vector tests
if (!Vec3Test<float>()) if (!Vec3Test<float>())
return EXIT_FAILURE; { fprintf(stderr, "Error at line: %i called from line: %i\n", lineno, __LINE__); return EXIT_FAILURE; }
if (!Vec3Test<double>()) if (!Vec3Test<double>())
return EXIT_FAILURE; { fprintf(stderr, "Error at line: %i called from line: %i\n", lineno, __LINE__); return EXIT_FAILURE; }
// Do quaternion tests // Do quaternion tests
if (!QuatTest<float>()) if (!QuatTest<float>())
return EXIT_FAILURE; { fprintf(stderr, "Error at line: %i called from line: %i\n", lineno, __LINE__); return EXIT_FAILURE; }
if (!QuatTest<double>()) if (!QuatTest<double>())
return EXIT_FAILURE; { fprintf(stderr, "Error at line: %i called from line: %i\n", lineno, __LINE__); return EXIT_FAILURE; }
if (!QuatDerivativeTest<float>()) if (!QuatDerivativeTest<float>())
return EXIT_FAILURE; { fprintf(stderr, "Error at line: %i called from line: %i\n", lineno, __LINE__); return EXIT_FAILURE; }
if (!QuatDerivativeTest<double>()) if (!QuatDerivativeTest<double>())
return EXIT_FAILURE; { fprintf(stderr, "Error at line: %i called from line: %i\n", lineno, __LINE__); return EXIT_FAILURE; }
// Do matrix tests // Do matrix tests
if (!MatrixTest<float>()) if (!MatrixTest<float>())
return EXIT_FAILURE; { fprintf(stderr, "Error at line: %i called from line: %i\n", lineno, __LINE__); return EXIT_FAILURE; }
if (!MatrixTest<double>()) if (!MatrixTest<double>())
return EXIT_FAILURE; { fprintf(stderr, "Error at line: %i called from line: %i\n", lineno, __LINE__); return EXIT_FAILURE; }
// Do rect tests // Do rect tests
doRectTest<int>(); doRectTest<int>();
@@ -387,7 +390,7 @@ main(void)
// Check geodetic/geocentric/cartesian conversions // Check geodetic/geocentric/cartesian conversions
if (!GeodesyTest()) if (!GeodesyTest())
return EXIT_FAILURE; { fprintf(stderr, "Error at line: %i called from line: %i\n", lineno, __LINE__); return EXIT_FAILURE; }
std::cout << "Successfully passed all tests!" << std::endl; std::cout << "Successfully passed all tests!" << std::endl;
return EXIT_SUCCESS; return EXIT_SUCCESS;
+8 -1
View File
@@ -1,4 +1,4 @@
// Copyright (C) 2016 Erik Hofman - erik@ehofman.com // Copyright (C) 2016-2017 Erik Hofman - erik@ehofman.com
// //
// This library is free software; you can redistribute it and/or // This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public // modify it under the terms of the GNU Library General Public
@@ -18,6 +18,10 @@
#ifndef __SIMD_H__ #ifndef __SIMD_H__
#define __SIMD_H__ 1 #define __SIMD_H__ 1
#ifdef HAVE_CONFIG_H
# include <simgear/simgear_config.h>
#endif
#include <cstdint> #include <cstdint>
#include <cstring> #include <cstring>
#include <cassert> #include <cassert>
@@ -305,6 +309,7 @@ inline simd4_t<T,N> operator*(simd4_t<T,N> v, T f) {
return v; return v;
} }
#ifdef ENABLE_SIMD
# ifdef __SSE__ # ifdef __SSE__
namespace simd4 namespace simd4
@@ -1294,5 +1299,7 @@ inline simd4_t<int,N> max(simd4_t<int,N> v1, const simd4_t<int,N>& v2) {
# endif # endif
#endif /* ENABLE_SIMD */
#endif /* __SIMD_H__ */ #endif /* __SIMD_H__ */
+30 -15
View File
@@ -20,6 +20,10 @@
#include <cstring> #include <cstring>
#ifdef HAVE_CONFIG_H
# include <simgear/simgear_config.h>
#endif
#if defined(__GNUC__) && defined(__ARM_NEON__) #if defined(__GNUC__) && defined(__ARM_NEON__)
# include <simgear/math/simd4x4_neon.hxx> # include <simgear/math/simd4x4_neon.hxx>
#endif #endif
@@ -285,6 +289,8 @@ inline simd4x4_t<T,N> operator*(const simd4x4_t<T,N>& m1, const simd4x4_t<T,N>&
} }
#ifdef ENABLE_SIMD
# ifdef __SSE__ # ifdef __SSE__
template<> template<>
class alignas(16) simd4x4_t<float,4> class alignas(16) simd4x4_t<float,4>
@@ -380,13 +386,14 @@ public:
} }
simd4x4_t<float,4>& operator*=(const simd4x4_t<float,4>& m2) { simd4x4_t<float,4>& operator*=(const simd4x4_t<float,4>& m2) {
simd4x4_t<float,4> m1 = *this;
__m128 row, col; __m128 row, col;
for (int i=0; i<4; ++i ) { for (int i=0; i<4; ++i) {
col = _mm_set1_ps(m2.ptr()[i][0]); col = _mm_set1_ps(m2.ptr()[i][0]);
row = _mm_mul_ps(simd4x4[0], col); row = _mm_mul_ps(m1.m4x4()[0], col);
for (int j=1; j<4; ++j) { for (int j=1; j<4; ++j) {
col = _mm_set1_ps(m2.ptr()[i][j]); col = _mm_set1_ps(m2.ptr()[i][j]);
row = _mm_add_ps(row, _mm_mul_ps(simd4x4[j], col)); row = _mm_add_ps(row, _mm_mul_ps(m1.m4x4()[j], col));
} }
simd4x4[i] = row; simd4x4[i] = row;
} }
@@ -583,13 +590,14 @@ public:
} }
simd4x4_t<double,4>& operator*=(const simd4x4_t<double,4>& m2) { simd4x4_t<double,4>& operator*=(const simd4x4_t<double,4>& m2) {
simd4x4_t<double,4> m1 = *this;
__m256d row, col; __m256d row, col;
for (int i=0; i<4; ++i ) { for (int i=0; i<4; ++i) {
col = _mm256_set1_pd(m2.ptr()[i][0]); col = _mm256_set1_pd(m2.ptr()[i][0]);
row = _mm256_mul_pd(simd4x4[0], col); row = _mm256_mul_pd(m1.m4x4()[0], col);
for (int j=1; j<4; ++j) { for (int j=1; j<4; ++j) {
col = _mm256_set1_pd(m2.ptr()[i][j]); col = _mm256_set1_pd(m2.ptr()[i][j]);
row = _mm256_add_pd(row, _mm256_mul_pd(simd4x4[j], col)); row = _mm256_add_pd(row, _mm256_mul_pd(m1.m4x4()[j], col));
} }
simd4x4[i] = row; simd4x4[i] = row;
} }
@@ -738,7 +746,11 @@ public:
simd4x4[3][1] = _mm_set_pd(m33,m23); simd4x4[3][1] = _mm_set_pd(m33,m23);
} }
simd4x4_t(const double m[4*4]) { simd4x4_t(const double m[4*4]) {
const double *p = m;
for (int i=0; i<4; ++i) { for (int i=0; i<4; ++i) {
simd4_t<double,4> vec4(p);
simd4x4[i][0] = vec4.v4()[0]; p += 4;
simd4x4[i][1] = vec4.v4()[1];
simd4x4[i][0] = _mm_loadu_pd((const double*)&m[4*i]); simd4x4[i][0] = _mm_loadu_pd((const double*)&m[4*i]);
simd4x4[i][1] = _mm_loadu_pd((const double*)&m[4*i+2]); simd4x4[i][1] = _mm_loadu_pd((const double*)&m[4*i+2]);
} }
@@ -746,6 +758,8 @@ public:
simd4x4_t(const __mtx4d_t m) { simd4x4_t(const __mtx4d_t m) {
for (int i=0; i<4; ++i) { for (int i=0; i<4; ++i) {
simd4x4[i][0] = simd4_t<double,4>(m[i]).v4()[0];
simd4x4[i][1] = simd4_t<double,4>(m[i]).v4()[1];
simd4x4[i][0] = _mm_loadu_pd(m[i]); simd4x4[i][0] = _mm_loadu_pd(m[i]);
simd4x4[i][1] = _mm_loadu_pd(m[i+2]); simd4x4[i][1] = _mm_loadu_pd(m[i+2]);
} }
@@ -814,18 +828,17 @@ public:
} }
simd4x4_t<double,4>& operator*=(const simd4x4_t<double,4>& m2) { simd4x4_t<double,4>& operator*=(const simd4x4_t<double,4>& m2) {
__m128d row[2], col; simd4x4_t<double,4> m1 = *this;
simd4_t<double,4> row, col;
for (int i=0; i<4; ++i ) { for (int i=0; i<4; ++i ) {
col = _mm_set1_pd(m2.ptr()[i][0]); simd4_t<double,4> col = m1.m4x4()[0];
row[0] = _mm_mul_pd(simd4x4[0][0], col); row = col * m2.ptr()[i][0];
row[1] = _mm_mul_pd(simd4x4[0][1], col);
for (int j=1; j<4; ++j) { for (int j=1; j<4; ++j) {
col = _mm_set1_pd(m2.ptr()[i][j]); col = m1.m4x4()[j];
row[0] = _mm_add_pd(row[0], _mm_mul_pd(simd4x4[j][0], col)); row += col * m2.ptr()[i][j];
row[1] = _mm_add_pd(row[1], _mm_mul_pd(simd4x4[j][1], col));
} }
simd4x4[i][0] = row[0]; simd4x4[i][0] = row.v4()[0];
simd4x4[i][1] = row[1]; simd4x4[i][1] = row.v4()[1];
} }
return *this; return *this;
} }
@@ -1178,5 +1191,7 @@ inline simd4_t<int,3> transform<int>(const simd4x4_t<int,4>& m, const simd4_t<in
} /* namespace simd4x */ } /* namespace simd4x */
# endif # endif
#endif /* ENABLE_SIMD */
#endif /* __SIMD4X4_H__ */ #endif /* __SIMD4X4_H__ */
+1
View File
@@ -20,3 +20,4 @@
#cmakedefine SYSTEM_EXPAT #cmakedefine SYSTEM_EXPAT
#cmakedefine ENABLE_SOUND #cmakedefine ENABLE_SOUND
#cmakedefine ENABLE_SIMD