TEST_FIXTURE(INDMathTests,LookAtMatrixEyeLookUpLH) { //Result IND_Matrix result; IND_Vector3 eye(1.0f, 2.0f, 3.0f); IND_Vector3 look(1.0f, 2.0f, 2.0f); //Just on z coord lower IND_Vector3 up(0.0f, -1.0f, 0.0f); math->matrix4DLookAtMatrixEyeLookUpLH(eye,look,up,result); IND_Vector3 x(1.0f, 0.0f, 0.0f); IND_Vector3 y(0.0f, -1.0f, 0.0f); IND_Vector3 z(0.0f, 0.0f, -1.0f); CHECK_CLOSE(x._x, result._11, 0.01f); CHECK_CLOSE(x._y, result._12, 0.01f); CHECK_CLOSE(x._z, result._13, 0.01f); CHECK_CLOSE(0.0f, result._41, 0.01f); CHECK_CLOSE(y._x, result._21, 0.01f); CHECK_CLOSE(y._y, result._22, 0.01f); CHECK_CLOSE(y._z, result._23, 0.01f); CHECK_CLOSE(0.0f, result._42, 0.01f); CHECK_CLOSE(z._x, result._31, 0.01f); CHECK_CLOSE(z._y, result._32, 0.01f); CHECK_CLOSE(z._z, result._33, 0.01f); CHECK_CLOSE(0.0f, result._43, 0.01f); CHECK_CLOSE(-x.dotProduct(eye), result._14, 0.01f); CHECK_CLOSE(-y.dotProduct(eye), result._24, 0.01f); CHECK_CLOSE(-z.dotProduct(eye), result._34, 0.01f); CHECK_CLOSE(1.0f, result._44, 0.01f); }
TEST_FIXTURE(INDMathTests,idendityMatrix) { IND_Matrix matrix = IND_Matrix::identity(); CHECK_CLOSE(1.f, matrix._11, 0.01f); CHECK_CLOSE(0.f, matrix._12, 0.01f); CHECK_CLOSE(0.f, matrix._13, 0.01f); CHECK_CLOSE(0.f, matrix._14, 0.01f); CHECK_CLOSE(0.f, matrix._21, 0.01f); CHECK_CLOSE(1.f, matrix._22, 0.01f); CHECK_CLOSE(0.f, matrix._23, 0.01f); CHECK_CLOSE(0.f, matrix._24, 0.01f); CHECK_CLOSE(0.f, matrix._31, 0.01f); CHECK_CLOSE(0.f, matrix._32, 0.01f); CHECK_CLOSE(1.f, matrix._33, 0.01f); CHECK_CLOSE(0.f, matrix._34, 0.01f); CHECK_CLOSE(0.f, matrix._41, 0.01f); CHECK_CLOSE(0.f, matrix._42, 0.01f); CHECK_CLOSE(0.f, matrix._43, 0.01f); CHECK_CLOSE(1.f, matrix._44, 0.01f); }
TEST_FIXTURE(INDMathTests,LookAtMatrixLH) { //Result IND_Matrix result; IND_Vector3 up(0.0f, 1.0f, 0.0f); IND_Vector3 right(1.0f, 0.0f, 0.0f); IND_Vector3 look(0.0f, 0.0f, -1.0f); IND_Vector3 pos(1.0f, 2.0f, 3.0f); math->matrix4DLookAtMatrixLH(right, up, look, pos, result); CHECK_CLOSE(right._x, result._11, 0.01f); CHECK_CLOSE(right._y, result._12, 0.01f); CHECK_CLOSE(right._z, result._13, 0.01f); CHECK_CLOSE(0.0f, result._41, 0.01f); CHECK_CLOSE(up._x, result._21, 0.01f); CHECK_CLOSE(up._y, result._22, 0.01f); CHECK_CLOSE(up._z, result._23, 0.01f); CHECK_CLOSE(0.0f, result._42, 0.01f); CHECK_CLOSE(look._x, result._31, 0.01f); CHECK_CLOSE(look._y, result._32, 0.01f); CHECK_CLOSE(look._z, result._33, 0.01f); CHECK_CLOSE(0.0f, result._43, 0.01f); CHECK_CLOSE(-pos.dotProduct(right), result._14, 0.01f); CHECK_CLOSE(-pos.dotProduct(up), result._24, 0.01f); CHECK_CLOSE(-pos.dotProduct(look), result._34, 0.01f); CHECK_CLOSE(1.0f, result._44, 0.01f); }
TEST_FIXTURE(INDMathTests,MatrixMultiplyIdentity) { IND_Matrix m1; IND_Matrix m2; IND_Matrix result; //Construct first matrix math->matrix4DSetIdentity(m1); //Construct second matrix m2._11 = 11.0f; m2._12 = 12.0f; m2._13 = 12.0f; m2._14 = 14.0f; m2._21 = 21.0f; m2._22 = 22.0f; m2._23 = 22.0f; m2._24 = 24.0f; m2._31 = 31.0f; m2._32 = 32.0f; m2._33 = 32.0f; m2._34 = 34.0f; m2._41 = 41.0f; m2._42 = 42.0f; m2._43 = 42.0f; m2._44 = 44.0f; //Perform matrix multiplication math->matrix4DMultiply(m1, m2, result); //Checkings CHECK_CLOSE(m2._11, result._11, 0.01f); CHECK_CLOSE(m2._12, result._12, 0.01f); CHECK_CLOSE(m2._13, result._13, 0.01f); CHECK_CLOSE(m2._14, result._14, 0.01f); CHECK_CLOSE(m2._21, result._21, 0.01f); CHECK_CLOSE(m2._22, result._22, 0.01f); CHECK_CLOSE(m2._23, result._23, 0.01f); CHECK_CLOSE(m2._24, result._24, 0.01f); CHECK_CLOSE(m2._31, result._31, 0.01f); CHECK_CLOSE(m2._32, result._32, 0.01f); CHECK_CLOSE(m2._33, result._33, 0.01f); CHECK_CLOSE(m2._34, result._34, 0.01f); CHECK_CLOSE(m2._41, result._41, 0.01f); CHECK_CLOSE(m2._42, result._42, 0.01f); CHECK_CLOSE(m2._43, result._43, 0.01f); CHECK_CLOSE(m2._44, result._44, 0.01f); }
TEST_FIXTURE(INDMathTests,MatrixMultiplyInPlace) { IND_Matrix m1; IND_Matrix m2; //Construct first matrix m1._11 = 1.0f; m1._12 = 2.0f; m1._13 = 3.0f; m1._14 = 4.0f; m1._21 = 5.0f; m1._22 = 6.0f; m1._23 = 7.0f; m1._24 = 8.0f; m1._31 = 9.0f; m1._32 = 10.0f; m1._33 = 11.0f; m1._34 = 12.0f; m1._41 = 13.0f; m1._42 = 14.0f; m1._43 = 15.0f; m1._44 = 16.0f; //Construct second matrix m2._11 = 1.0f; m2._12 = 2.0f; m2._13 = 3.0f; m2._14 = 4.0f; m2._21 = 5.0f; m2._22 = 6.0f; m2._23 = 7.0f; m2._24 = 8.0f; m2._31 = 9.0f; m2._32 = 10.0f; m2._33 = 11.0f; m2._34 = 12.0f; m2._41 = 13.0f; m2._42 = 14.0f; m2._43 = 15.0f; m2._44 = 16.0f; //Perform matrix multiplication math->matrix4DMultiplyInPlace(m1, m2); //Checkings CHECK_CLOSE(90.0f, m1._11, 0.01f); CHECK_CLOSE(100.0f, m1._12, 0.01f); CHECK_CLOSE(110.0f, m1._13, 0.01f); CHECK_CLOSE(120.0f, m1._14, 0.01f); CHECK_CLOSE(202.0f, m1._21, 0.01f); CHECK_CLOSE(228.0f, m1._22, 0.01f); CHECK_CLOSE(254.0f, m1._23, 0.01f); CHECK_CLOSE(280.0f, m1._24, 0.01f); CHECK_CLOSE(314.0f, m1._31, 0.01f); CHECK_CLOSE(356.0f, m1._32, 0.01f); CHECK_CLOSE(398.0f, m1._33, 0.01f); CHECK_CLOSE(440.0f, m1._34, 0.01f); CHECK_CLOSE(426.0f, m1._41, 0.01f); CHECK_CLOSE(484.0f, m1._42, 0.01f); CHECK_CLOSE(542.0f, m1._43, 0.01f); CHECK_CLOSE(600.0f, m1._44, 0.01f); }
TEST_FIXTURE(INDMathTests,RotateVector) { //Rotation matrix IND_Matrix mrot; //Vector to rotate IND_Vector3 vec; //------------Rotation around Z axis------------------------------- //90 degress around z axis (x axis vector) vec = IND_Vector3(1.0f, 0.0f, 0.0f); math->matrix4DSetRotationAroundAxis(mrot, 90.f, IND_Vector3(0.0f, 0.0f, 1.0f)); //Rotation math->transformVector3DbyMatrix4D(vec, mrot); CHECK_CLOSE(0.0f, vec._x, 0.01f); CHECK_CLOSE(1.0f, vec._y, 0.01f); CHECK_CLOSE(0.0f, vec._z, 0.01f); //45 degress around z axis (x axis vector) vec = IND_Vector3(1.0f, 0.0f, 0.0f); math->matrix4DSetRotationAroundAxis(mrot, 45.0f, IND_Vector3(0.0f, 0.0f, 1.0f)); //Rotation math->transformVector3DbyMatrix4D(vec, mrot); CHECK_CLOSE(0.7f, vec._x, 0.01f); CHECK_CLOSE(0.7f, vec._y, 0.01f); CHECK_CLOSE(0.0f, vec._z, 0.01f); //90 degress around z axis (y axis vector) vec = IND_Vector3(0.0f, 1.0f, 0.0f); math->matrix4DSetRotationAroundAxis(mrot, 90.f, IND_Vector3(0.0f, 0.0f, 1.0f)); //Rotation math->transformVector3DbyMatrix4D(vec, mrot); CHECK_CLOSE(-1.0f, vec._x, 0.01f); CHECK_CLOSE(0.0f, vec._y, 0.01f); CHECK_CLOSE(0.0f, vec._z, 0.01f); //45 degress around z axis (y axis vector) vec = IND_Vector3(0.0f, 1.0f, 0.0f); math->matrix4DSetRotationAroundAxis(mrot, 45.0f, IND_Vector3(0.0f, 0.0f, 1.0f)); //Rotation math->transformVector3DbyMatrix4D(vec, mrot); CHECK_CLOSE(-0.7f, vec._x, 0.01f); CHECK_CLOSE(0.7f, vec._y, 0.01f); CHECK_CLOSE(0.0f, vec._z, 0.01f); //90 degress around z axis (z axis vector) vec = IND_Vector3(0.0f, 0.0f, 1.0f); math->matrix4DSetRotationAroundAxis(mrot, 90.f, IND_Vector3(0.0f, 0.0f, 1.0f)); //Rotation math->transformVector3DbyMatrix4D(vec, mrot); CHECK_CLOSE(0.0f, vec._x, 0.01f); CHECK_CLOSE(0.0f, vec._y, 0.01f); CHECK_CLOSE(1.0f, vec._z, 0.01f); //45 degress around z axis (z axis vector) vec = IND_Vector3(0.0f, 0.0f, 1.0f); math->matrix4DSetRotationAroundAxis(mrot, 45.0f, IND_Vector3(0.0f, 0.0f, 1.0f)); //Rotation math->transformVector3DbyMatrix4D(vec, mrot); CHECK_CLOSE(0.0f, vec._x, 0.01f); CHECK_CLOSE(0.0f, vec._y, 0.01f); CHECK_CLOSE(1.0f, vec._z, 0.01f); //------------Rotation around Y axis------------------------------- //90 degress around y axis (x axis vector) vec = IND_Vector3(1.0f, 0.0f, 0.0f); math->matrix4DSetRotationAroundAxis(mrot, 90.f, IND_Vector3(0.0f, 1.0f, 0.0f)); //Rotation math->transformVector3DbyMatrix4D(vec, mrot); CHECK_CLOSE(0.0f, vec._x, 0.01f); CHECK_CLOSE(0.0f, vec._y, 0.01f); CHECK_CLOSE(-1.0f, vec._z, 0.01f); //45 degress around y axis (x axis vector) vec = IND_Vector3(1.0f, 0.0f, 0.0f); math->matrix4DSetRotationAroundAxis(mrot, 45.0f, IND_Vector3(0.0f, 1.0f, 0.0f)); //Rotation math->transformVector3DbyMatrix4D(vec, mrot); CHECK_CLOSE(0.7f, vec._x, 0.01f); CHECK_CLOSE(0.0f, vec._y, 0.01f); CHECK_CLOSE(-0.7f, vec._z, 0.01f); //90 degress around y axis (y axis vector) vec = IND_Vector3(0.0f, 1.0f, 0.0f); math->matrix4DSetRotationAroundAxis(mrot, 90.f, IND_Vector3(0.0f, 1.0f, 0.0f)); //Rotation math->transformVector3DbyMatrix4D(vec, mrot); CHECK_CLOSE(0.0f, vec._x, 0.01f); CHECK_CLOSE(1.0f, vec._y, 0.01f); CHECK_CLOSE(0.0f, vec._z, 0.01f); //45 degress around y axis (y axis vector) vec = IND_Vector3(0.0f, 1.0f, 0.0f); math->matrix4DSetRotationAroundAxis(mrot, 45.0f, IND_Vector3(0.0f, 1.0f, 0.0f)); //Rotation math->transformVector3DbyMatrix4D(vec, mrot); CHECK_CLOSE(0.0f, vec._x, 0.01f); CHECK_CLOSE(1.0f, vec._y, 0.01f); CHECK_CLOSE(0.0f, vec._z, 0.01f); //90 degress around y axis (z axis vector) vec = IND_Vector3(0.0f, 0.0f, 1.0f); math->matrix4DSetRotationAroundAxis(mrot, 90.f, IND_Vector3(0.0f, 1.0f, 0.0f)); //Rotation math->transformVector3DbyMatrix4D(vec, mrot); CHECK_CLOSE(1.0f, vec._x, 0.01f); CHECK_CLOSE(0.0f, vec._y, 0.01f); CHECK_CLOSE(0.0f, vec._z, 0.01f); //45 degress around y axis (z axis vector) vec = IND_Vector3(0.0f, 0.0f, 1.0f); math->matrix4DSetRotationAroundAxis(mrot, 45.0f, IND_Vector3(0.0f, 1.0f, 0.0f)); //Rotation math->transformVector3DbyMatrix4D(vec, mrot); CHECK_CLOSE(0.7f, vec._x, 0.01f); CHECK_CLOSE(0.0f, vec._y, 0.01f); CHECK_CLOSE(0.7f, vec._z, 0.01f); //------------Rotation around X axis------------------------------- //90 degress around x axis (x axis vector) vec = IND_Vector3(1.0f, 0.0f, 0.0f); math->matrix4DSetRotationAroundAxis(mrot, 90.f, IND_Vector3(1.0f, 0.0f, 0.0f)); //Rotation math->transformVector3DbyMatrix4D(vec, mrot); CHECK_CLOSE(1.0f, vec._x, 0.01f); CHECK_CLOSE(0.0f, vec._y, 0.01f); CHECK_CLOSE(0.0f, vec._z, 0.01f); //45 degress around x axis (x axis vector) vec = IND_Vector3(1.0f, 0.0f, 0.0f); math->matrix4DSetRotationAroundAxis(mrot, 45.0f, IND_Vector3(1.0f, 0.0f, 0.0f)); //Rotation math->transformVector3DbyMatrix4D(vec, mrot); CHECK_CLOSE(1.0f, vec._x, 0.01f); CHECK_CLOSE(0.0f, vec._y, 0.01f); CHECK_CLOSE(0.0f, vec._z, 0.01f); //90 degress around x axis (y axis vector) vec = IND_Vector3(0.0f, 1.0f, 0.0f); math->matrix4DSetRotationAroundAxis(mrot, 90.f, IND_Vector3(1.0f, 0.0f, 0.0f)); //Rotation math->transformVector3DbyMatrix4D(vec, mrot); CHECK_CLOSE(0.0f, vec._x, 0.01f); CHECK_CLOSE(0.0f, vec._y, 0.01f); CHECK_CLOSE(1.0f, vec._z, 0.01f); //45 degress around x axis (y axis vector) vec = IND_Vector3(0.0f, 1.0f, 0.0f); math->matrix4DSetRotationAroundAxis(mrot, 45.0f, IND_Vector3(1.0f, 0.0f, 0.0f)); //Rotation math->transformVector3DbyMatrix4D(vec, mrot); CHECK_CLOSE(0.0f, vec._x, 0.01f); CHECK_CLOSE(0.7f, vec._y, 0.01f); CHECK_CLOSE(0.7f, vec._z, 0.01f); //90 degress around x axis (z axis vector) vec = IND_Vector3(0.0f, 0.0f, 1.0f); math->matrix4DSetRotationAroundAxis(mrot, 90.f, IND_Vector3(1.0f, 0.0f, 0.0f)); //Rotation math->transformVector3DbyMatrix4D(vec, mrot); CHECK_CLOSE(0.0f, vec._x, 0.01f); CHECK_CLOSE(-1.0f, vec._y, 0.01f); CHECK_CLOSE(0.0f, vec._z, 0.01f); //45 degress around x axis (z axis vector) vec = IND_Vector3(0.0f, 0.0f, 1.0f); math->matrix4DSetRotationAroundAxis(mrot, 45.0f, IND_Vector3(1.0f, 0.0f, 0.0f)); //Rotation math->transformVector3DbyMatrix4D(vec, mrot); CHECK_CLOSE(0.0f, vec._x, 0.01f); CHECK_CLOSE(-0.7f, vec._y, 0.01f); CHECK_CLOSE(0.7f, vec._z, 0.01f); }
TEST_F (MyFixture, TestCase1) { CHECK_CLOSE (someValue, 2.0f, 0.00001); someValue = 13; }
TEST_F (MyFixture, TestCase2) { CHECK_CLOSE (someValue, 2.0f, 0.00001); CHECK_EQUAL (str, "Hello"); }
void test_boundary_mesh() { typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel; typedef CGAL::Polyhedron_3<Kernel, CGAL::Polyhedron_items_with_id_3> Polyhedron_3; typedef CGAL::Surface_mesh_shortest_path_traits<Kernel, Polyhedron_3> Traits; typedef Traits::Barycentric_coordinate Barycentric_coordinate; typedef Traits::FT FT; typedef Traits::Point_3 Point_3; typedef Traits::Triangle_3 Triangle_3; typedef boost::graph_traits<Polyhedron_3> Graph_traits; typedef Graph_traits::vertex_descriptor vertex_descriptor; typedef Graph_traits::vertex_iterator vertex_iterator; typedef Graph_traits::face_descriptor face_descriptor; typedef Graph_traits::face_iterator face_iterator; typedef CGAL::Surface_mesh_shortest_path<Traits> Surface_mesh_shortest_path; typedef boost::property_map<Polyhedron_3, CGAL::vertex_point_t>::type VPM; Traits traits; Traits::Construct_triangle_3_to_triangle_2_projection project_triangle_3_to_triangle_2(traits.construct_triangle_3_to_triangle_2_projection_object()); CGAL_USE(project_triangle_3_to_triangle_2); Traits::Compute_squared_distance_3 compute_squared_distance_3(traits.compute_squared_distance_3_object()); Traits::Construct_barycenter_3 construct_barycenter_3(traits.construct_barycenter_3_object()); Traits::Construct_triangle_3_along_segment_2_flattening flatten_triangle_3_along_segment_2(traits.construct_triangle_3_along_segment_2_flattening_object()); CGAL_USE(flatten_triangle_3_along_segment_2); Traits::Construct_barycentric_coordinate construct_barycentric_coordinate(traits.construct_barycentric_coordinate_object()); struct Construct_barycenter_in_triangle_3 { Traits::Construct_barycenter_3 m_cb3; Construct_barycenter_in_triangle_3(Traits::Construct_barycenter_3 cb3) : m_cb3(cb3) { } Point_3 operator() (const Triangle_3& t, const Barycentric_coordinate& b) { return m_cb3(t[0], b[0], t[1], b[1], t[2], b[2]); } } construct_barycenter_in_triangle_3(construct_barycenter_3); std::ifstream inFile("data/boundary_mesh.off"); Polyhedron_3 P; inFile >> P; inFile.close(); CGAL::set_halfedgeds_items_id(P); face_iterator startFace; face_iterator endFace; boost::tie(startFace, endFace) = CGAL::faces(P); vertex_iterator currentVertex; vertex_iterator endVertex; VPM vpm = CGAL::get(CGAL::vertex_point, P); vertex_descriptor vertexHandles[10]; face_descriptor faceHandles[8]; Point_3 vertexLocations[10]; size_t currentVertexIndex = 0; for (boost::tie(currentVertex, endVertex) = CGAL::vertices(P); currentVertex != endVertex; ++currentVertex) { vertexHandles[currentVertexIndex] = *currentVertex; vertexLocations[currentVertexIndex] = vpm[*currentVertex]; ++currentVertexIndex; } size_t currentFaceIndex = 0; for (face_iterator currentFace = startFace; currentFace != endFace; ++currentFace) { faceHandles[currentFaceIndex] = *currentFace; ++currentFaceIndex; } Barycentric_coordinate startLocation = construct_barycentric_coordinate(FT(0.1), FT(0.8), FT(0.1)); typedef boost::property_map<Polyhedron_3, CGAL::face_external_index_t>::type FaceIndexMap; FaceIndexMap faceIndexMap(CGAL::get(CGAL::face_external_index, P)); Surface_mesh_shortest_path shortestPaths(P, traits); //shortestPaths.m_debugOutput = true; shortestPaths.add_source_point(*startFace, startLocation); shortestPaths.build_sequence_tree(); Triangle_3 firstTriangle(vertexLocations[1], vertexLocations[0], vertexLocations[2]); Point_3 locationInTriangle(construct_barycenter_in_triangle_3(firstTriangle, startLocation)); FT dist0 = shortestPaths.shortest_distance_to_source_points(vertexHandles[0]).first; CHECK_CLOSE(dist0, CGAL::sqrt(compute_squared_distance_3(locationInTriangle, vertexLocations[0])), FT(0.000001)); FT dist1 = shortestPaths.shortest_distance_to_source_points(vertexHandles[1]).first; CHECK_CLOSE(dist1, CGAL::sqrt(compute_squared_distance_3(locationInTriangle, vertexLocations[1])), FT(0.000001)); FT dist2 = shortestPaths.shortest_distance_to_source_points(vertexHandles[2]).first; CHECK_CLOSE(dist2, CGAL::sqrt(compute_squared_distance_3(locationInTriangle, vertexLocations[2])), FT(0.000001)); FT dist3 = shortestPaths.shortest_distance_to_source_points(vertexHandles[3]).first; CHECK_CLOSE(dist3, CGAL::sqrt(compute_squared_distance_3(locationInTriangle, vertexLocations[3])), FT(0.000001)); FT dist4 = shortestPaths.shortest_distance_to_source_points(vertexHandles[4]).first; CHECK_CLOSE(dist4, CGAL::sqrt(compute_squared_distance_3(locationInTriangle, vertexLocations[1])) + CGAL::sqrt(compute_squared_distance_3(vertexLocations[1], vertexLocations[4])), FT(0.000001)); FT dist5 = shortestPaths.shortest_distance_to_source_points(vertexHandles[5]).first; CHECK_CLOSE(dist5, CGAL::sqrt(compute_squared_distance_3(locationInTriangle, vertexLocations[3])) + CGAL::sqrt(compute_squared_distance_3(vertexLocations[3], vertexLocations[5])), FT(0.000001)); Barycentric_coordinate somewhereElseInFirstTriangle = construct_barycentric_coordinate(0.8, 0.05, 0.15); FT distT0 = shortestPaths.shortest_distance_to_source_points(faceHandles[0], somewhereElseInFirstTriangle).first; CHECK_CLOSE(distT0, CGAL::sqrt(compute_squared_distance_3(locationInTriangle, construct_barycenter_in_triangle_3(firstTriangle, somewhereElseInFirstTriangle))), FT(0.000001)); Triangle_3 oneStepTriangle(vertexLocations[4], vertexLocations[1], vertexLocations[3]); Barycentric_coordinate locationInOneStepTriangle = construct_barycentric_coordinate(0.1, 0.8, 0.1); CGAL::test::Edge_sequence_collector<Traits> collector(P); shortestPaths.shortest_path_sequence_to_source_points(faceHandles[2], locationInOneStepTriangle, collector); FT distT2 = shortestPaths.shortest_distance_to_source_points(faceHandles[2], locationInOneStepTriangle).first; CHECK_CLOSE(distT2, dist1 + CGAL::sqrt(compute_squared_distance_3(vertexLocations[1], construct_barycenter_in_triangle_3(oneStepTriangle, locationInOneStepTriangle))), FT(0.00001)); Triangle_3 twoStepTriangle(vertexLocations[6], vertexLocations[5], vertexLocations[7]); Barycentric_coordinate locationInTwoStepTriangle = construct_barycentric_coordinate(0.8, 0.1, 0.1); FT distT5 = shortestPaths.shortest_distance_to_source_points(faceHandles[5], locationInTwoStepTriangle).first; CHECK_CLOSE(distT5, dist3 + CGAL::sqrt(compute_squared_distance_3(vertexLocations[3], construct_barycenter_in_triangle_3(twoStepTriangle, locationInTwoStepTriangle))), FT(0.00001)); Triangle_3 threeStepTriangle(vertexLocations[7], vertexLocations[5], vertexLocations[8]); Barycentric_coordinate locationInThreeStepTriangle = construct_barycentric_coordinate(0.2, 0.6, 0.2); FT distT6 = shortestPaths.shortest_distance_to_source_points(faceHandles[6], locationInThreeStepTriangle).first; CHECK_CLOSE(distT6, dist5 + CGAL::sqrt(compute_squared_distance_3(vertexLocations[5], construct_barycenter_in_triangle_3(threeStepTriangle, locationInThreeStepTriangle))), FT(0.00001)); }
void test_simple_saddle_vertex_mesh() { typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel; typedef CGAL::Polyhedron_3<Kernel, CGAL::Polyhedron_items_with_id_3> Polyhedron_3; typedef CGAL::Surface_mesh_shortest_path_traits<Kernel, Polyhedron_3> Traits; typedef Traits::Barycentric_coordinate Barycentric_coordinate; typedef Traits::FT FT; typedef Traits::Point_3 Point_3; typedef Traits::Point_2 Point_2; typedef Traits::Triangle_3 Triangle_3; typedef Traits::Triangle_2 Triangle_2; typedef Traits::Segment_2 Segment_2; typedef boost::graph_traits<Polyhedron_3> Graph_traits; typedef Graph_traits::vertex_descriptor vertex_descriptor; typedef Graph_traits::vertex_iterator vertex_iterator; typedef Graph_traits::halfedge_descriptor halfedge_descriptor; typedef Graph_traits::face_descriptor face_descriptor; typedef CGAL::Surface_mesh_shortest_path<Traits> Surface_mesh_shortest_path; typedef boost::property_map<Polyhedron_3, CGAL::vertex_point_t>::type VPM; Traits traits; Traits::Compute_squared_distance_3 compute_squared_distance_3(traits.compute_squared_distance_3_object()); Traits::Compute_squared_distance_2 compute_squared_distance_2(traits.compute_squared_distance_2_object()); Traits::Construct_triangle_3_along_segment_2_flattening flatten_triangle_3_along_segment_2(traits.construct_triangle_3_along_segment_2_flattening_object()); Traits::Construct_barycentric_coordinate construct_barycentric_coordinate(traits.construct_barycentric_coordinate_object()); std::ifstream inFile("data/saddle_vertex_mesh.off"); Polyhedron_3 P; inFile >> P; inFile.close(); CGAL::set_halfedgeds_items_id(P); vertex_iterator startVertex; vertex_iterator endVertex; boost::tie(startVertex, endVertex) = CGAL::vertices(P); vertex_iterator currentVertex = startVertex; ++currentVertex; vertex_descriptor rootSearchVertex = *currentVertex; face_descriptor currentFace = CGAL::face(CGAL::halfedge(rootSearchVertex, P), P); size_t vertexIndex = CGAL::test::face_vertex_index(currentFace, rootSearchVertex, P); Barycentric_coordinate baryCoord = construct_barycentric_coordinate(vertexIndex == 0 ? FT(1.0) : FT(0.0), vertexIndex == 1 ? FT(1.0) : FT(0.0), vertexIndex == 2 ? FT(1.0) : FT(0.0)); Surface_mesh_shortest_path shortestPaths(P, traits); //shortestPaths.m_debugOutput = true; Surface_mesh_shortest_path::Source_point_iterator firstSourcePoint = shortestPaths.add_source_point(currentFace, baryCoord); shortestPaths.build_sequence_tree(); VPM vpm = CGAL::get(CGAL::vertex_point, P); Point_3 vertexLocations[8]; vertex_descriptor vertexHandles[8]; currentVertex = startVertex; for (size_t i = 0; i < 8; ++i) { vertexHandles[i] = *currentVertex; vertexLocations[i] = vpm[*currentVertex]; ++currentVertex; } FT distanceToBottom = CGAL::sqrt(compute_squared_distance_3(vertexLocations[1], vertexLocations[0])); FT largerSideLength = CGAL::sqrt(compute_squared_distance_3(vertexLocations[1], vertexLocations[2])); FT distanceToSaddle = CGAL::sqrt(compute_squared_distance_3(vertexLocations[1], vertexLocations[4])); FT shorterSideLength = CGAL::sqrt(compute_squared_distance_3(vertexLocations[4], vertexLocations[6])); Triangle_3 lower(vertexLocations[6], vertexLocations[4], vertexLocations[1]); Triangle_3 upper(vertexLocations[4], vertexLocations[6], vertexLocations[7]); Segment_2 base(Point_2(CGAL::ORIGIN), Point_2(shorterSideLength, FT(0.0))); Triangle_2 flatLower(flatten_triangle_3_along_segment_2(lower, 0, base)); Triangle_2 flatUpper(flatten_triangle_3_along_segment_2(upper, 0, Segment_2(base[1], base[0]))); FT distanceToApex = CGAL::sqrt(compute_squared_distance_2(flatLower[2], flatUpper[2])); FT expectedDistances[8] = { distanceToBottom, // a vertex of the larger tetrahedron FT(0.0), // the initial vertex largerSideLength, // a vertex of the larger tetrahedron largerSideLength, // a vertex of the larger tetrahedron distanceToSaddle, // direct line of sight from root distanceToSaddle + shorterSideLength, // around the corner from a pseudo-source (not in direct line of geodesic sight) distanceToSaddle, // direct line of sight from root distanceToApex, }; currentVertex = startVertex; for (size_t i = 0; i < 8; ++i) { CHECK_CLOSE(shortestPaths.shortest_distance_to_source_points(*currentVertex).first, expectedDistances[i], Kernel::FT(0.0001)); ++currentVertex; } // test the edge sequence reporting CGAL::test::Edge_sequence_collector<Traits> collector(P); shortestPaths.shortest_path_sequence_to_source_points(vertexHandles[5], collector); CHECK_EQUAL(collector.m_sequence.size(), 3u); CHECK_EQUAL(collector.m_sequence[1].type, CGAL::test::SEQUENCE_ITEM_VERTEX); assert(collector.m_sequence[1].index == 4 || collector.m_sequence[1].index == 6); CHECK_EQUAL(collector.m_sequence[2].type, CGAL::test::SEQUENCE_ITEM_VERTEX); CHECK_EQUAL(collector.m_sequence[2].index, 1u); collector.m_sequence.clear(); typedef boost::property_map<Polyhedron_3, CGAL::halfedge_external_index_t>::type HalfedgeIndexMap; HalfedgeIndexMap halfedgeIndexMap(CGAL::get(CGAL::halfedge_external_index, P)); shortestPaths.shortest_path_sequence_to_source_points(vertexHandles[7], collector); CHECK_EQUAL(collector.m_sequence.size(), 3u); CHECK_EQUAL(collector.m_sequence[1].type, CGAL::test::SEQUENCE_ITEM_EDGE); CHECK_EQUAL(collector.m_sequence[1].index, halfedgeIndexMap[CGAL::halfedge(vertexHandles[4], vertexHandles[6], P).first]); CHECK_CLOSE(collector.m_sequence[1].edgeAlpha, FT(0.5), FT(0.0001)); CHECK_EQUAL(collector.m_sequence[2].type, CGAL::test::SEQUENCE_ITEM_VERTEX); CHECK_EQUAL(collector.m_sequence[2].index, 1u); // Now test an internal face location sequence halfedge_descriptor firstCrossing = CGAL::halfedge(vertexHandles[4], vertexHandles[7], P).first; size_t edgeIndex = CGAL::internal::edge_index(firstCrossing, P); Barycentric_coordinate location = construct_barycentric_coordinate(0.25, 0.5, 0.25); collector.m_sequence.clear(); shortestPaths.shortest_path_sequence_to_source_points(CGAL::face(firstCrossing, P), construct_barycentric_coordinate(location[edgeIndex], location[(edgeIndex + 1) % 3], location[(edgeIndex + 2) % 3]), collector); CHECK_EQUAL(collector.m_sequence.size(), 4u); CHECK_EQUAL(collector.m_sequence[1].type, CGAL::test::SEQUENCE_ITEM_EDGE); CHECK_EQUAL(collector.m_sequence[1].index, halfedgeIndexMap[firstCrossing]); CHECK_EQUAL(collector.m_sequence[2].type, CGAL::test::SEQUENCE_ITEM_EDGE); CHECK_EQUAL(collector.m_sequence[2].index, halfedgeIndexMap[CGAL::halfedge(vertexHandles[4], vertexHandles[6], P).first]); CHECK_EQUAL(collector.m_sequence[3].type, CGAL::test::SEQUENCE_ITEM_VERTEX); CHECK_EQUAL(collector.m_sequence[3].index, 1u); // Now test with 2 source vertices currentVertex = startVertex; for (size_t i = 0; i < 5; ++i) { ++currentVertex; } vertex_descriptor rootSearchVertex2 = *currentVertex; face_descriptor currentFace2 = CGAL::face(CGAL::halfedge(rootSearchVertex2, P), P); size_t vertexIndex2 = CGAL::test::face_vertex_index(currentFace2, rootSearchVertex2, P); Barycentric_coordinate baryCoord2 = construct_barycentric_coordinate(vertexIndex2 == 0 ? FT(1.0) : FT(0.0), vertexIndex2 == 1 ? FT(1.0) : FT(0.0), vertexIndex2 == 2 ? FT(1.0) : FT(0.0)); Surface_mesh_shortest_path::Source_point_iterator secondSourcePoint = shortestPaths.add_source_point(currentFace2, baryCoord2); shortestPaths.build_sequence_tree(); FT distanceToApexFrom2 = CGAL::sqrt(compute_squared_distance_3(vertexLocations[5], vertexLocations[7])); Triangle_3 lower2(vertexLocations[2], vertexLocations[3], vertexLocations[5]); Triangle_3 upper2(vertexLocations[3], vertexLocations[2], vertexLocations[0]); Segment_2 base2(Point_2(CGAL::ORIGIN), Point_2(largerSideLength, FT(0.0))); Triangle_2 flatLower2(flatten_triangle_3_along_segment_2(lower2, 0, base2)); Triangle_2 flatUpper2(flatten_triangle_3_along_segment_2(upper2, 0, Segment_2(base2[1], base2[0]))); FT distanceToBottom2 = CGAL::sqrt(compute_squared_distance_2(flatLower2[2], flatUpper2[2])); FT expectedDistances2[8] = { distanceToBottom2, // a vertex of the larger tetrahedron FT(0.0), // an initial vertex distanceToSaddle, // a vertex of the larger tetrahedron distanceToSaddle, // a vertex of the larger tetrahedron shorterSideLength, // direct line of sight from root FT(0.0), // around the corner from a pseudo-source (not in direct line of geodesic sight) shorterSideLength, // direct line of sight from root distanceToApexFrom2, }; Surface_mesh_shortest_path::Source_point_iterator expectedSources2[8] = { secondSourcePoint, firstSourcePoint, secondSourcePoint, secondSourcePoint, secondSourcePoint, secondSourcePoint, secondSourcePoint, secondSourcePoint, }; currentVertex = startVertex; for (size_t i = 0; i < 8; ++i) { Surface_mesh_shortest_path::Shortest_path_result result = shortestPaths.shortest_distance_to_source_points(*currentVertex); CHECK_CLOSE(result.first, expectedDistances2[i], Kernel::FT(0.0001)); assert(result.second == expectedSources2[i]); ++currentVertex; } // Test removing a source vertex shortestPaths.remove_source_point(firstSourcePoint); shortestPaths.build_sequence_tree(); // replace the only shortest path which was not reporting to the 2nd source point expectedDistances2[1] = distanceToSaddle + shorterSideLength; currentVertex = startVertex; for (size_t i = 0; i < 8; ++i) { Surface_mesh_shortest_path::Shortest_path_result result = shortestPaths.shortest_distance_to_source_points(*currentVertex); CHECK_CLOSE(result.first, expectedDistances2[i], Kernel::FT(0.0001)); assert(result.second == secondSourcePoint); ++currentVertex; } }
/* Basic functionality test for distributed 3D FFT This tests the integrity of a forward transform, followed by an inverse transform */ void test_distributed_fft_nd(int nd) { int p,s; MPI_Comm_size(MPI_COMM_WORLD, &p); MPI_Comm_rank(MPI_COMM_WORLD, &s); int *pdim; pdim = (int *) malloc(sizeof(int)*nd); /* choose a decomposition */ int r = powf(p,1.0/(double)nd)+0.5; int root = 1; while (root < r) root*=2; int ptot = 1; if (!s) printf("Processor grid: "); int i; for (i = 0; i < nd-1; ++i) { pdim[i] = (((ptot*root) > p) ? 1 : root); ptot *= pdim[i]; if (!s) printf("%d x ",pdim[i]); } pdim[nd-1] = p/ptot; if (!s) printf("%d\n", pdim[nd-1]); /* determine processor index */ int *pidx; pidx = (int*)malloc(nd*sizeof(int)); int idx = s; for (i = nd-1; i >= 0; --i) { pidx[i] = idx % pdim[i]; idx /= pdim[i]; } double tol = 0.001; double abs_tol = 0.2; int *dim_glob; dim_glob = (int *) malloc(sizeof(int)*nd); /* test with a 1x1 matrix, but only if we are executing on a single rank */ if (p == 1) { cuda_cpx_t *in_1_d; cuda_cpx_t *in_1_h; in_1_h = (cuda_cpx_t *) malloc(sizeof(cuda_cpx_t)*1); cudaMalloc((void **)&in_1_d,sizeof(cuda_cpx_t)*1); for (i = 0; i < nd; ++i) dim_glob[i] = 1*pdim[i]; CUDA_RE(in_1_h[0]) = (double) s; CUDA_IM(in_1_h[0]) = 0.0f; /* copy to device */ cudaMemcpy(in_1_d, in_1_h, sizeof(cuda_cpx_t)*1,cudaMemcpyDefault); dfft_plan plan_1; int pidx[1]; pidx[0] =s; dfft_cuda_create_plan(&plan_1, nd, dim_glob, NULL, NULL, pdim, pidx, 0, 0, 0, MPI_COMM_WORLD, proc_map); dfft_cuda_check_errors(&plan_1,1); /* forward transform */ dfft_cuda_execute(in_1_d, in_1_d, 0, &plan_1); /* backward transform */ dfft_cuda_execute(in_1_d, in_1_d, 1, &plan_1); /* copy back to host */ cudaMemcpy(in_1_h, in_1_d, sizeof(cuda_cpx_t)*1,cudaMemcpyDefault); if (s == 0) { CHECK_SMALL(CUDA_RE(in_1_h[0]),abs_tol); CHECK_SMALL(CUDA_IM(in_1_h[0]),abs_tol); } else { CHECK_CLOSE(CUDA_RE(in_1_h[0]),(double)s/(double)p,tol); CHECK_SMALL(CUDA_IM(in_1_h[0]),abs_tol); } cudaFree(in_1_d); free(in_1_h); dfft_cuda_destroy_plan(plan_1); } /* now do a test with a 2^n local matrix */ cuda_cpx_t *in_2_d; cuda_cpx_t *in_2_h; int size_2n = 1; for (i = 0; i < nd; ++i) size_2n *= 2; cudaMalloc((void **)&in_2_d,sizeof(cuda_cpx_t)*size_2n); in_2_h = (cuda_cpx_t *) malloc(sizeof(cuda_cpx_t)*size_2n); for (i = 0; i < size_2n; ++i) { CUDA_RE(in_2_h[i]) =(i+s*(double)size_2n); CUDA_IM(in_2_h[i]) =0.0f; } /* copy data to device */ cudaMemcpy(in_2_d, in_2_h, sizeof(cuda_cpx_t)*size_2n,cudaMemcpyDefault); for (i = 0; i < nd; ++i) dim_glob[i] = 2*pdim[i]; for (i = 0; i < nd-1; ++i) if (!s) printf("%d x ",dim_glob[i]); if (!s) printf("%d matrix\n", dim_glob[nd-1]); dfft_plan plan_2; dfft_cuda_create_plan(&plan_2, nd, dim_glob, NULL, NULL, pdim, pidx, 0, 0, 0, MPI_COMM_WORLD, proc_map); dfft_cuda_check_errors(&plan_2,1); /* forward transfom */ dfft_cuda_execute(in_2_d, in_2_d, 0, &plan_2); /* inverse transform */ dfft_cuda_execute(in_2_d, in_2_d, 1, &plan_2); /* copy back to host */ cudaMemcpy(in_2_h, in_2_d, sizeof(cuda_cpx_t)*size_2n, cudaMemcpyDefault); for (i = 0; i < size_2n; ++i) { if (s == 0 && i == 0) { CHECK_SMALL(CUDA_RE(in_2_h[i]), abs_tol); CHECK_SMALL(CUDA_IM(in_2_h[i]), abs_tol); } else { CHECK_CLOSE(CUDA_RE(in_2_h[i]), size_2n*p*(i+(double)size_2n*(double)s),tol); CHECK_SMALL(CUDA_IM(in_2_h[i]), abs_tol); } } cudaFree(in_2_d); free(in_2_h); dfft_cuda_destroy_plan(plan_2); // test with a padded 4^n local matrix (two ghost cells per axis) cuda_cpx_t *in_3_d; cuda_cpx_t *out_3_d; cuda_cpx_t *in_3_h; int *inembed; inembed = (int *) malloc(sizeof(int)*nd); int size_4n_embed = 1; int size_4n = 1; for (i = 0; i < nd; ++i) { inembed[i] = 4; size_4n_embed *= 4; size_4n *= 2; dim_glob[i]= 2*pdim[i]; } for (i = 0; i < nd-1; ++i) if (!s) printf("%d x ",dim_glob[i]); if (!s) printf("%d matrix with padding\n", dim_glob[nd-1]); cudaMalloc((void **)&in_3_d,sizeof(cuda_cpx_t)*size_4n_embed); cudaMalloc((void **)&out_3_d,sizeof(cuda_cpx_t)*size_4n); in_3_h = (cuda_cpx_t *) malloc(sizeof(cuda_cpx_t)*size_4n_embed); int *lidx; int *gidx; lidx = (int *) malloc(nd*sizeof(int)); gidx = (int *) malloc(nd*sizeof(int)); for (i = 0; i < size_4n_embed; ++i) { //processor grid in column major int idx = i; // find local coordinate tuple int j; for (j = nd-1; j >= 0; --j) { int length = inembed[j]; lidx[j] = idx % length; idx /= length; } // global coordinates in block distribution for (j = 0; j<nd; ++j) gidx[j] = lidx[j] + inembed[j]*pidx[j]; int val=0; for (j = 0; j<nd; ++j) { val *= inembed[j]; val += gidx[j]; } int ghost_cell = 0; for (j = 0; j < nd; ++j) if (lidx[j] == 0 || lidx[j] == 3) ghost_cell = 1; if (ghost_cell) { CUDA_RE(in_3_h[i]) = 99.0; CUDA_IM(in_3_h[i]) = 123.0; } else { CUDA_RE(in_3_h[i]) = (double) val; CUDA_IM(in_3_h[i]) = 0.0; } } /* copy data to device */ cudaMemcpy(in_3_d, in_3_h, sizeof(cuda_cpx_t)*size_4n_embed,cudaMemcpyDefault); dfft_plan plan_3_fw,plan_3_bw; dfft_cuda_create_plan(&plan_3_fw, nd, dim_glob, inembed, NULL, pdim, pidx, 0, 0, 0, MPI_COMM_WORLD, proc_map); dfft_cuda_check_errors(&plan_3_fw,1); dfft_cuda_create_plan(&plan_3_bw, nd, dim_glob, NULL, inembed, pdim, pidx, 0, 0, 0, MPI_COMM_WORLD, proc_map); dfft_cuda_check_errors(&plan_3_bw,1); int offset = 0; int n_ghost = 2; for (i = 0; i < nd; i++) { offset *= 4; offset += n_ghost/2; } /* forward transform */ dfft_cuda_execute(in_3_d+offset, out_3_d, 0, &plan_3_fw); /* inverse transform */ dfft_cuda_execute(out_3_d,in_3_d+offset, 1, &plan_3_bw); /* copy data back to host */ cudaMemcpy(in_3_h, in_3_d, sizeof(cuda_cpx_t)*size_4n_embed,cudaMemcpyDefault); /* check results */ for (i = 0; i < size_4n_embed; ++i) { //processor grid in column major int idx = i; // find local coordinate tuple int j; for (j = nd-1; j >= 0; --j) { int length = inembed[j]; lidx[j] = idx % length; idx /= length; } // global coordinates in block distribution for (j = 0; j<nd; ++j) gidx[j] = lidx[j] + inembed[j]*pidx[j]; int val=0; for (j = 0; j<nd; ++j) { val *= inembed[j]; val += gidx[j]; } int ghost_cell = 0; for (j = 0; j < nd; ++j) if (lidx[j] == 0 || lidx[j] == 3) ghost_cell = 1; if (ghost_cell) { //CHECK_CLOSE(CUDA_RE(in_3[i]),99.0,tol); //CHECK_CLOSE(CUDA_IM(in_3[i]), 123.0,tol); } else { CHECK_CLOSE(CUDA_RE(in_3_h[i]), (double) val*(double)p*(double)size_4n,tol); CHECK_SMALL(CUDA_IM(in_3_h[i]), abs_tol); } } cudaFree(in_3_d); cudaFree(out_3_d); free(in_3_h); free(lidx); free(gidx); dfft_cuda_destroy_plan(plan_3_fw); dfft_cuda_destroy_plan(plan_3_bw); free(pidx); free(pdim); free(dim_glob); }
/* Compare a 3d FFT against a reference FFT */ void test_distributed_fft_3d_compare() { int s,p; MPI_Comm_size(MPI_COMM_WORLD, &p); MPI_Comm_rank(MPI_COMM_WORLD, &s); int nd = 3; int *pdim; pdim = (int *) malloc(sizeof(int)*nd); /* choose a decomposition */ int r = powf(p,1.0/(double)nd)+0.5; int root = 1; while (root < r) root*=2; int ptot = 1; if (!s) printf("Processor grid: "); int i; for (i = 0; i < nd-1; ++i) { pdim[i] = (((ptot*root) > p) ? 1 : root); ptot *= pdim[i]; if (!s) printf("%d x ",pdim[i]); } pdim[nd-1] = p/ptot; if (!s) printf("%d\n", pdim[nd-1]); /* determine processor index */ int *pidx; pidx = (int*)malloc(nd*sizeof(int)); int idx = s; for (i = nd-1; i >= 0; --i) { pidx[i] = idx % pdim[i]; idx /= pdim[i]; } int *dim_glob; dim_glob = (int *) malloc(sizeof(int)*nd); // Do a pdim[0]*4 x pdim[1]* 8 x pdim[2] * 16 FFT (powers of two) int local_nx = 4; int local_ny = 8; int local_nz = 16; dim_glob[0] = pdim[0]*local_nx; dim_glob[1] = pdim[1]*local_ny; dim_glob[2] = pdim[2]*local_nz; for (i = 0; i < nd-1; ++i) if (!s) printf("%d x ",dim_glob[i]); if (!s) printf("%d matrix\n", dim_glob[nd-1]); float scale = dim_glob[0]*dim_glob[1]*dim_glob[2]; /* assume 0.5 sig digit loss per addition/twiddling (empirical)*/ float sig_digits = 7.0-0.5*logf(scale)/logf(2.0); double tol = powf(10.0,-sig_digits); double abs_tol = 1.0*tol; printf("Testing with %f sig digits, rel precision %f, abs precision %f\n", sig_digits, tol, abs_tol); kiss_fft_cpx *in_kiss; in_kiss = (kiss_fft_cpx *)malloc(sizeof(kiss_fft_cpx)*dim_glob[0]*dim_glob[1]*dim_glob[2]); srand(12345); // fill table with complex random numbers in row major order int x,y,z; int nx = dim_glob[0]; int ny = dim_glob[1]; int nz = dim_glob[2]; for (x = 0; x < dim_glob[0]; ++x) for (y = 0; y < dim_glob[1]; ++y) for (z = 0; z < dim_glob[2]; ++z) { // KISS has column-major storage in_kiss[z+nz*(y+ny*x)].r = (float)rand()/(float)RAND_MAX; in_kiss[z+nz*(y+ny*x)].i =(float)rand()/(float)RAND_MAX; } kiss_fft_cpx *out_kiss; out_kiss = (kiss_fft_cpx *)malloc(sizeof(kiss_fft_cpx)*dim_glob[0]*dim_glob[1]*dim_glob[2]); // construct forward transform kiss_fftnd_cfg cfg = kiss_fftnd_alloc(dim_glob,3,0,NULL,NULL); // carry out conventional FFT kiss_fftnd(cfg, in_kiss, out_kiss); // compare to distributed FFT cuda_cpx_t * in_d, *in_h; cudaMalloc((void **)&in_d,sizeof(cuda_cpx_t)*local_nx*local_ny*local_nz); in_h = (cuda_cpx_t *) malloc(sizeof(cuda_cpx_t)*local_nx*local_ny*local_nz); int x_local, y_local, z_local; for (x = 0; x < nx; ++x) for (y = 0; y < ny; ++y) for (z = 0; z < nz; ++z) { if (x>=pidx[0]*local_nx && x < (pidx[0]+1)*local_nx && y>=pidx[1]*local_ny && y < (pidx[1]+1)*local_ny && z>=pidx[2]*local_nz && z < (pidx[2]+1)*local_nz) { x_local = x - pidx[0]*local_nx; y_local = y - pidx[1]*local_ny; z_local = z - pidx[2]*local_nz; CUDA_RE(in_h[z_local+local_nz*(y_local+local_ny*x_local)]) = in_kiss[z+nz*(y+ny*x)].r; CUDA_IM(in_h[z_local+local_nz*(y_local+local_ny*x_local)]) = in_kiss[z+nz*(y+ny*x)].i; } } cuda_cpx_t *out_d, *out_h; cudaMalloc((void **)&out_d,sizeof(cuda_cpx_t)*local_nx*local_ny*local_nz); out_h = (cuda_cpx_t *) malloc(sizeof(cuda_cpx_t)*local_nx*local_ny*local_nz); dfft_plan plan; dfft_cuda_create_plan(&plan,3, dim_glob, NULL, NULL, pdim, pidx,0, 0, 0, MPI_COMM_WORLD, proc_map); dfft_cuda_check_errors(&plan,1); /* copy data to device */ cudaMemcpy(in_d, in_h, sizeof(cuda_cpx_t)*local_nx*local_ny*local_nz, cudaMemcpyDefault); // forward transform dfft_cuda_execute(in_d, out_d, 0, &plan); /* copy data back to host */ cudaMemcpy(out_h, out_d, sizeof(cuda_cpx_t)*local_nx*local_ny*local_nz, cudaMemcpyDefault); // do comparison int n_wave_local = local_nx * local_ny * local_nz; for (i = 0; i < n_wave_local; ++i) { x_local = i / local_ny / local_nz; y_local = (i - x_local*local_ny*local_nz)/local_nz; z_local = i % local_nz; x = pidx[0]*local_nx + x_local; y = pidx[1]*local_ny + y_local; z = pidx[2]*local_nz + z_local; double re = CUDA_RE(out_h[i]); double im = CUDA_IM(out_h[i]); double re_kiss = out_kiss[z+nz*(y+ny*x)].r; double im_kiss = out_kiss[z+nz*(y+ny*x)].i; if (fabs(re_kiss) < abs_tol) { CHECK_SMALL(re,2*abs_tol); } else { CHECK_CLOSE(re,re_kiss, tol); } if (fabs(im_kiss) < abs_tol) { CHECK_SMALL(im,2*abs_tol); } else { CHECK_CLOSE(im, im_kiss, tol); } } free(in_kiss); free(out_kiss); cudaFree(out_d); cudaFree(in_d); free(in_h); free(out_h); free(pidx); free(dim_glob); dfft_cuda_destroy_plan(plan); }
/* Compare a 1d FFT against a reference FFT */ void test_distributed_fft_1d_compare(int n) { int s,p; MPI_Comm_size(MPI_COMM_WORLD, &p); MPI_Comm_rank(MPI_COMM_WORLD, &s); int pdim[1]; pdim[0]=p; /* determine processor index */ int pidx[1]; pidx[0]=s; float scale = n; /* assume 0.5 sig digit loss per addition/twiddling (empirical)*/ float sig_digits = 7.0-0.5*logf(scale)/logf(2.0); double tol = powf(10.0,-sig_digits); double abs_tol = 1.0*tol; printf("Testing with %f sig digits, rel precision %f, abs precision %f\n", sig_digits, tol, abs_tol); int dim_glob[1]; dim_glob[0] = n; // Do a size n FFT (n = power of two) kiss_fft_cpx *in_kiss; in_kiss = (kiss_fft_cpx *)malloc(sizeof(kiss_fft_cpx)*n); srand(45678); // fill vector with complex random numbers in row major order int i; for (i = 0; i < n; ++i) { in_kiss[i].r = (float)rand()/(float)RAND_MAX; in_kiss[i].i =(float)rand()/(float)RAND_MAX; } kiss_fft_cpx *out_kiss; out_kiss = (kiss_fft_cpx *)malloc(sizeof(kiss_fft_cpx)*n); // construct forward transform kiss_fft_cfg cfg = kiss_fft_alloc(n,0,NULL,NULL); // carry out conventional FFT kiss_fft(cfg, in_kiss, out_kiss); // compare to distributed FFT cuda_cpx_t * in_d, *in_h; cudaMalloc((void **)&in_d,sizeof(cuda_cpx_t)*n/p); in_h = (cuda_cpx_t *) malloc(sizeof(cuda_cpx_t)*n/p); for (i = 0; i < n/p; ++i) { CUDA_RE(in_h[i]) = in_kiss[s*n/p+i].r; CUDA_IM(in_h[i]) = in_kiss[s*n/p+i].i; } cuda_cpx_t *out_d,*out_h; cudaMalloc((void **)&out_d,sizeof(cuda_cpx_t)*n/p); out_h = (cuda_cpx_t *)malloc(sizeof(cuda_cpx_t)*n/p); dfft_plan plan; dfft_cuda_create_plan(&plan,1, dim_glob, NULL, NULL, pdim, pidx,0, 0, 0, MPI_COMM_WORLD, proc_map); dfft_cuda_check_errors(&plan,1); /* copy data to device */ cudaMemcpy(in_d, in_h, sizeof(cuda_cpx_t)*n/p, cudaMemcpyDefault); /* forward transform */ dfft_cuda_execute(in_d, out_d, 0, &plan); /* copy data back to host */ cudaMemcpy(out_h, out_d, sizeof(cuda_cpx_t)*n/p, cudaMemcpyDefault); /* do comparison */ for (i = 0; i < n/p; ++i) { int j = s*n/p + i; double re = CUDA_RE(out_h[i]); double im = CUDA_IM(out_h[i]); double re_kiss = out_kiss[j].r; double im_kiss = out_kiss[j].i; if (fabs(re_kiss) < abs_tol) { CHECK_SMALL(re,2*abs_tol); } else { CHECK_CLOSE(re,re_kiss, tol); } if (fabs(im_kiss) < abs_tol) { CHECK_SMALL(im,2*abs_tol); } else { CHECK_CLOSE(im, im_kiss, tol); } } free(in_kiss); free(out_kiss); cudaFree(out_d); cudaFree(in_d); free(in_h); free(out_h); dfft_cuda_destroy_plan(plan); }
/** * Retrieve a single configuration \c widget for the \c camera. * * @param camera a #Camera * @param name the name of a configuration widget * @param widget a #CameraWidget * @param context a #GPContext * @return gphoto2 error code * * This \c widget will then contain the current and the possible values and the type. * */ int gp_camera_get_single_config (Camera *camera, const char *name, CameraWidget **widget, GPContext *context) { CameraWidget *rootwidget, *child; CameraWidgetType type; const char *label; int ret, ro; C_PARAMS (camera); CHECK_INIT (camera, context); if (camera->functions->get_single_config) { CHECK_RESULT_OPEN_CLOSE (camera, camera->functions->get_single_config ( camera, name, widget, context), context); CAMERA_UNUSED (camera, context); return GP_OK; } if (!camera->functions->get_config) { gp_context_error (context, _("This camera does not provide any configuration options.")); CAMERA_UNUSED (camera, context); return GP_ERROR_NOT_SUPPORTED; } /* emulate it ... */ CHECK_OPEN (camera, context); ret = camera->functions->get_config ( camera, &rootwidget, context); if (ret != GP_OK) { CHECK_CLOSE (camera, context); CAMERA_UNUSED (camera, context); return ret; } ret = gp_widget_get_child_by_name (rootwidget, name, &child); if (ret != GP_OK) { gp_widget_free (rootwidget); CHECK_CLOSE (camera, context); CAMERA_UNUSED (camera, context); return ret; } /* We need to duplicate the widget, as we will free the widgettree */ gp_widget_get_type (child, &type); gp_widget_get_label (child, &label); gp_widget_get_readonly (child, &ro); ret = gp_widget_new (type, label, widget); if (ret != GP_OK) goto out; gp_widget_set_name (*widget, name); gp_widget_set_readonly (*widget, ro); switch (type) { case GP_WIDGET_MENU: case GP_WIDGET_RADIO: { char *value; int i, nrofchoices; nrofchoices = gp_widget_count_choices (child); for (i = 0; i < nrofchoices; i++) { const char *choice; gp_widget_get_choice (child, i, &choice); gp_widget_add_choice (*widget, choice); } gp_widget_get_value (child, &value); gp_widget_set_value (*widget, value); break; } case GP_WIDGET_TEXT: { char *value; gp_widget_get_value (child, &value); gp_widget_set_value (*widget, value); break; } case GP_WIDGET_RANGE: { float value, rmin, rmax, rstep; gp_widget_get_range (child, &rmin, &rmax, &rstep); gp_widget_set_range (*widget, rmin, rmax, rstep); gp_widget_get_value (child, &value); gp_widget_set_value (*widget, &value); break; } case GP_WIDGET_TOGGLE: case GP_WIDGET_DATE: { int value; gp_widget_get_value (child, &value); gp_widget_set_value (*widget, &value); break; } case GP_WIDGET_BUTTON: case GP_WIDGET_SECTION: case GP_WIDGET_WINDOW: default: ret = GP_ERROR_BAD_PARAMETERS; break; } out: gp_widget_free (rootwidget); CHECK_CLOSE (camera, context); CAMERA_UNUSED (camera, context); return ret; }
/** * Set a single configuration \c widget for the \c camera. * * @param camera a #Camera * @param name the name of a configuration widget * @param widget a #CameraWidget * @param context a #GPContext * @return gphoto2 error code * * This \c widget contains the new value of the widget to set. * */ int gp_camera_set_single_config (Camera *camera, const char *name, CameraWidget *widget, GPContext *context) { CameraWidget *rootwidget, *child; CameraWidgetType type; int ret; C_PARAMS (camera); CHECK_INIT (camera, context); if (camera->functions->set_single_config) { CHECK_RESULT_OPEN_CLOSE (camera, camera->functions->set_single_config ( camera, name, widget, context), context); CAMERA_UNUSED (camera, context); return GP_OK; } if (!camera->functions->set_config) { gp_context_error (context, _("This camera does not provide any configuration options.")); CAMERA_UNUSED (camera, context); return GP_ERROR_NOT_SUPPORTED; } /* emulate single config with the full tree */ CHECK_OPEN (camera, context); ret = camera->functions->get_config ( camera, &rootwidget, context); if (ret != GP_OK) { CHECK_CLOSE (camera, context); CAMERA_UNUSED (camera, context); return ret; } ret = gp_widget_get_child_by_name (rootwidget, name, &child); if (ret != GP_OK) { gp_widget_free (rootwidget); CHECK_CLOSE (camera, context); CAMERA_UNUSED (camera, context); return ret; } gp_widget_get_type (child, &type); ret = GP_OK; switch (type) { case GP_WIDGET_MENU: case GP_WIDGET_RADIO: case GP_WIDGET_TEXT: { char *value; gp_widget_get_value (widget, &value); gp_widget_set_value (child, value); break; } case GP_WIDGET_RANGE: { float value; gp_widget_get_value (widget, &value); gp_widget_set_value (child, &value); break; } case GP_WIDGET_TOGGLE: case GP_WIDGET_DATE: { int value; gp_widget_get_value (widget, &value); gp_widget_set_value (child, &value); break; } case GP_WIDGET_BUTTON: case GP_WIDGET_SECTION: case GP_WIDGET_WINDOW: default: ret = GP_ERROR_BAD_PARAMETERS; break; } gp_widget_set_changed (child, 1); if (ret == GP_OK) ret = camera->functions->set_config (camera, rootwidget, context); gp_widget_free (rootwidget); CHECK_CLOSE (camera, context); CAMERA_UNUSED (camera, context); return ret; }