We need to copy the matrix before altering it's contents: Fix a SGMathTest failure
This commit is contained in:
+53
-50
@@ -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;
|
||||||
|
|||||||
@@ -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
@@ -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__ */
|
||||||
|
|
||||||
|
|||||||
@@ -20,3 +20,4 @@
|
|||||||
|
|
||||||
#cmakedefine SYSTEM_EXPAT
|
#cmakedefine SYSTEM_EXPAT
|
||||||
#cmakedefine ENABLE_SOUND
|
#cmakedefine ENABLE_SOUND
|
||||||
|
#cmakedefine ENABLE_SIMD
|
||||||
|
|||||||
Reference in New Issue
Block a user