<commit_before>#include "memlist.h"

MemList::MemList() {
	/* TODO: Nothing to do? */
}

void MemList::add(MemoryAlloc &alloc) {
	this->list.push_back(alloc);
}

MemoryAlloc MemList::add(void* address, int size) {
	MemoryAlloc alloc(address, size);
	this->list.push_back(alloc);
	return alloc;
}

MemoryAlloc MemList::add(void* address, int size, int fenceSize) {
	MemoryAlloc alloc(address, size, fenceSize);
	this->list.push_back(alloc);
	return alloc;
}

MemoryAlloc MemList::get(unsigned int index) {
	MemoryAlloc alloc;
	if(index >= 0 && index < this->list.size()) {
		alloc = list.at(index);
	}
	return alloc;
}

bool MemList::removeMatching(void* address) {
	bool success = false;
	int index = containsAddress(address);
	if(index >= 0) {
		success = remove(index);
	}
	return success;
}

bool MemList::removeMatching(MemoryAlloc &alloc) {
	return removeMatching(alloc.getAddress());
}

bool MemList::remove(unsigned int index) {
	bool success = false;
	if(index >= 0 && index < this->list.size()) {
		list.erase(this->list.begin() + index);
		success = true;
	}
	return success;
}

void MemList::clear() {
	this->list.clear();
}

int MemList::size() {
	return this->list.size();
}

bool MemList::isEmpty() {
	return this->list.empty();
}

int MemList::containsAddress(void* address) {
	int index = ERR_NOT_FOUND;
	for(unsigned int i = 0; i < this->list.size(); i++) {
		MemoryAlloc alloc = this->list.at(i);
		void *addr = alloc.getAddress();
		// Check to see if the address is valid
		if(addr == address) {
			/* We found the address, save the location
			and exit the loop. */
			index = i;
			break;
		// Perform a check to see if the address is allocated mid-memory
		} else if(address >= addr && address <= (void*)((char*)addr + alloc.getUserSize() - 1)) {
			// The address was a mid-memory chunk
			index = ERR_MID_CHUNK;
			break;
		// Perform a check to see if the address is allocaed in a memory-fence
		} else if((address >= alloc.getUnderflowFence() && address <= addr) ||
			(address >= (addr + alloc.getUserSize() - 1) && address <= alloc.getOverflowFence())) {
			// The address was contained in a memory fence
			index = ERR_IN_FENCE;
			break;
		}
	}
	return index;
}
<commit_msg>FIxed the check for the overflow fence in memlist.<commit_after>#include "memlist.h"

MemList::MemList() {
	/* TODO: Nothing to do? */
}

void MemList::add(MemoryAlloc &alloc) {
	this->list.push_back(alloc);
}

MemoryAlloc MemList::add(void* address, int size) {
	MemoryAlloc alloc(address, size);
	this->list.push_back(alloc);
	return alloc;
}

MemoryAlloc MemList::add(void* address, int size, int fenceSize) {
	MemoryAlloc alloc(address, size, fenceSize);
	this->list.push_back(alloc);
	return alloc;
}

MemoryAlloc MemList::get(unsigned int index) {
	MemoryAlloc alloc;
	if(index >= 0 && index < this->list.size()) {
		alloc = list.at(index);
	}
	return alloc;
}

bool MemList::removeMatching(void* address) {
	bool success = false;
	int index = containsAddress(address);
	if(index >= 0) {
		success = remove(index);
	}
	return success;
}

bool MemList::removeMatching(MemoryAlloc &alloc) {
	return removeMatching(alloc.getAddress());
}

bool MemList::remove(unsigned int index) {
	bool success = false;
	if(index >= 0 && index < this->list.size()) {
		list.erase(this->list.begin() + index);
		success = true;
	}
	return success;
}

void MemList::clear() {
	this->list.clear();
}

int MemList::size() {
	return this->list.size();
}

bool MemList::isEmpty() {
	return this->list.empty();
}

int MemList::containsAddress(void* address) {
	int index = ERR_NOT_FOUND;
	for(unsigned int i = 0; i < this->list.size(); i++) {
		MemoryAlloc alloc = this->list.at(i);
		void *addr = alloc.getAddress();
		// Check to see if the address is valid
		if(addr == address) {
			/* We found the address, save the location
			and exit the loop. */
			index = i;
			break;
		// Perform a check to see if the address is allocated mid-memory
		} else if(address >= addr && address <= (void*)((char*)addr + alloc.getUserSize() - 1)) {
			// The address was a mid-memory chunk
			index = ERR_MID_CHUNK;
			break;
		// Perform a check to see if the address is allocaed in a memory-fence
		} else if((address >= alloc.getUnderflowFence() && address < addr) ||
			(address >= alloc.getOverflowFence() && address < alloc.getOverflowFence() + alloc.getFenceSize())) {
			// The address was contained in a memory fence
			index = ERR_IN_FENCE;
			break;
		}
	}
	return index;
}
<|endoftext|>


<commit_before>// Copyright (c) 2010-2022, Lawrence Livermore National Security, LLC. Produced
// at the Lawrence Livermore National Laboratory. All Rights reserved. See files
// LICENSE and NOTICE for details. LLNL-CODE-806117.
//
// This file is part of the MFEM library. For more information and source code
// availability visit https://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the BSD-3 license. We welcome feedback and contributions, see file
// CONTRIBUTING.md for details.

#include "mfem.hpp"
#include "unit_tests.hpp"

using namespace mfem;

#ifdef MFEM_USE_MPI

namespace ParSubMeshTests
{
enum FECType
{
   H1,
   L2
};

FiniteElementCollection *create_fec(FECType fectype, int p, int dim)
{
   switch (fectype)
   {
      case H1:
         return new H1_FECollection(p, dim);
         break;
      case L2:
         return new L2_FECollection(p, dim, BasisType::GaussLobatto);
         break;
   }

   return nullptr;
}

void multidomain_test_2d(FECType fec_type)
{
   const int p = 2;

   constexpr int dim = 2;
   double Hy = 1.0;
   Mesh serial_parent_mesh = Mesh::MakeCartesian2D(5, 5,
                                                   Element::QUADRILATERAL, true, 1.0, Hy,
                                                   false);

   for (int i = 0; i < serial_parent_mesh.GetNBE(); i++)
   {
      Element *el = serial_parent_mesh.GetBdrElement(i);
      el->SetAttribute(1);

      Array<int> vertices;
      el->GetVertices(vertices);

      bool all_vtx_inside = true;
      for (int j = 0; j < vertices.Size(); j++)
      {
         if (serial_parent_mesh.GetVertex(vertices[j])[1] < 1.0)
         {
            all_vtx_inside = false;
         }
      }
      if (all_vtx_inside)
      {
         el->SetAttribute(2);
      }
   }
   for (int i = 0; i < serial_parent_mesh.GetNE(); i++)
   {
      Element *el = serial_parent_mesh.GetElement(i);
      el->SetAttribute(1);

      Array<int> vertices;
      el->GetVertices(vertices);

      for (int j = 0; j < vertices.Size(); j++)
      {
         double *coords = serial_parent_mesh.GetVertex(vertices[j]);

         if (coords[0] >= 0.25 &&
             coords[0] <= 0.75 &&
             coords[1] >= 0.25 &&
             coords[1] <= 0.75)
         {
            el->SetAttribute(2);
         }
      }
   }
   serial_parent_mesh.SetAttributes();
   serial_parent_mesh.EnsureNodes();
   serial_parent_mesh.SetCurvature(p);

   auto node_movement_coeff = VectorFunctionCoefficient(
                                 serial_parent_mesh.Dimension(),
                                 [](const Vector &coords, Vector &u)
   {
      double x = coords(0);
      double y = coords(1);

      u(0) = x;
      u(1) = y + 0.05 * sin(x * 2.0 * M_PI);
   });

   serial_parent_mesh.Transform(node_movement_coeff);

   ParMesh parent_mesh(MPI_COMM_WORLD, serial_parent_mesh);

   Array<int> domain1(1);
   domain1[0] = 1;

   Array<int> boundary1(1);
   boundary1[0] = 2;

   auto domain_submesh = ParSubMesh::CreateFromDomain(parent_mesh,
                                                      domain1);

   auto boundary_submesh = ParSubMesh::CreateFromDomain(parent_mesh,
                                                        boundary1);

   FiniteElementCollection *fec = create_fec(fec_type, p, parent_mesh.Dimension());

   ParFiniteElementSpace parent_fes(&parent_mesh, fec);
   ParGridFunction parent_gf(&parent_fes);

   ParFiniteElementSpace domain1_fes(&domain_submesh, fec);
   ParGridFunction domain1_gf(&domain1_fes);

   FiniteElementCollection *surface_fec = create_fec(fec_type, p,
                                                     domain_submesh.Dimension());
   ParFiniteElementSpace boundary1_fes(&boundary_submesh, surface_fec);
   ParGridFunction boundary1_gf(&boundary1_fes);

   auto coeff = FunctionCoefficient([](const Vector &coords)
   {
      double x = coords(0);
      double y = coords(1);
      return y + 0.05 * sin(x * 2.0 * M_PI);
   });

   parent_gf.ProjectCoefficient(coeff);

   Vector tmp;

   ParGridFunction parent_gf_ex(&parent_fes);
   parent_gf_ex.ProjectCoefficient(coeff);

   ParGridFunction domain1_gf_ex(&domain1_fes);
   domain1_gf_ex.ProjectCoefficient(coeff);

   ParGridFunction boundary1_gf_ex(&boundary1_fes);
   boundary1_gf_ex.ProjectCoefficient(coeff);

   auto CHECK_GLOBAL_NORM = [](Vector &v)
   {
      double norm_local = v.Norml2(), norm_global = 0.0;
      MPI_Allreduce(&norm_local, &norm_global, 1, MPI_DOUBLE, MPI_SUM,
                    MPI_COMM_WORLD);
      REQUIRE(norm_global < 1e-8);
   };

   SECTION("ParentToSubMesh")
   {
      SECTION("Volume to matching volume")
      {
         ParSubMesh::Transfer(parent_gf, domain1_gf);
         tmp = domain1_gf_ex;
         tmp -= domain1_gf;
         CHECK_GLOBAL_NORM(tmp);
      }
      SECTION("Volume to matching surface")
      {
         ParSubMesh::Transfer(parent_gf, boundary1_gf);
         tmp = boundary1_gf_ex;
         tmp -= boundary1_gf;
         CHECK_GLOBAL_NORM(tmp);
      }
   }
   SECTION("SubMeshToParent")
   {
      SECTION("Volume to matching volume")
      {
         parent_gf.ProjectCoefficient(coeff);
         domain1_gf.ProjectCoefficient(coeff);
         ParSubMesh::Transfer(domain1_gf, parent_gf);
         tmp = parent_gf_ex;
         tmp -= parent_gf;
         CHECK_GLOBAL_NORM(tmp);
      }
      SECTION("Surface to matching surface in volume")
      {
         boundary1_gf.ProjectCoefficient(coeff);
         ParSubMesh::Transfer(boundary1_gf, parent_gf);
         tmp = parent_gf_ex;
         tmp -= parent_gf;
         CHECK_GLOBAL_NORM(tmp);
      }
   }
}

void multidomain_test_3d(FECType fec_type)
{
   const int p = 2;
   // Circle: sideset 1
   // Domain boundary: sideset 2
   Mesh *serial_parent_mesh = new Mesh("../../data/multidomain-hex.mesh");
   ParMesh parent_mesh(MPI_COMM_WORLD, *serial_parent_mesh);
   delete serial_parent_mesh;

   Array<int> cylinder_domain_attributes(1);
   cylinder_domain_attributes[0] = 1;

   Array<int> outer_domain_attributes(1);
   outer_domain_attributes[0] = 2;

   Array<int> cylinder_surface_attributes(1);
   cylinder_surface_attributes[0] = 9;

   auto cylinder_submesh = ParSubMesh::CreateFromDomain(parent_mesh,
                                                        cylinder_domain_attributes);

   auto outer_submesh = ParSubMesh::CreateFromDomain(parent_mesh,
                                                     outer_domain_attributes);

   auto cylinder_surface_submesh = ParSubMesh::CreateFromBoundary(parent_mesh,
                                                                  cylinder_surface_attributes);

   FiniteElementCollection *fec = create_fec(fec_type, p, parent_mesh.Dimension());

   ParFiniteElementSpace parent_fes(&parent_mesh, fec);
   ParGridFunction parent_gf(&parent_fes);

   ParFiniteElementSpace cylinder_fes(&cylinder_submesh, fec);
   ParGridFunction cylinder_gf(&cylinder_fes);

   ParFiniteElementSpace outer_fes(&outer_submesh, fec);
   ParGridFunction outer_gf(&outer_fes);

   FiniteElementCollection *surface_fec = create_fec(fec_type, p,
                                                     cylinder_surface_submesh.Dimension());
   ParFiniteElementSpace cylinder_surface_fes(&cylinder_surface_submesh,
                                              surface_fec);
   ParGridFunction cylinder_surface_gf(&cylinder_surface_fes);

   auto coeff = FunctionCoefficient([](const Vector &coords)
   {
      double x = coords(0);
      double y = coords(1);
      double z = coords(2);
      return y + 0.05 * sin(x * 2.0 * M_PI) + z;
   });

   parent_gf.ProjectCoefficient(coeff);

   Vector tmp;

   ParGridFunction parent_gf_ex(&parent_fes);
   parent_gf_ex.ProjectCoefficient(coeff);

   ParGridFunction cylinder_gf_ex(&cylinder_fes);
   cylinder_gf_ex.ProjectCoefficient(coeff);

   ParGridFunction cylinder_surface_gf_ex(&cylinder_surface_fes);
   cylinder_surface_gf_ex.ProjectCoefficient(coeff);

   ParGridFunction outer_gf_ex(&outer_fes);
   outer_gf_ex.ProjectCoefficient(coeff);

   auto CHECK_GLOBAL_NORM = [](Vector &v)
   {
      double norm_local = v.Norml2(), norm_global = 0.0;
      MPI_Allreduce(&norm_local, &norm_global, 1, MPI_DOUBLE, MPI_SUM,
                    MPI_COMM_WORLD);
      REQUIRE(norm_global < 1e-8);
   };

   SECTION("ParentToSubMesh")
   {
      SECTION("Volume to matching volume")
      {
         ParSubMesh::Transfer(parent_gf, cylinder_gf);
         tmp = cylinder_gf_ex;
         tmp -= cylinder_gf;
         CHECK_GLOBAL_NORM(tmp);
      }
      SECTION("Volume to matching surface")
      {
         ParSubMesh::Transfer(parent_gf, cylinder_surface_gf);
         tmp = cylinder_surface_gf_ex;
         tmp -= cylinder_surface_gf;
         CHECK_GLOBAL_NORM(tmp);
      }
   }
   SECTION("SubMeshToParent")
   {
      SECTION("Volume to matching volume")
      {
         parent_gf.ProjectCoefficient(coeff);
         cylinder_gf.ProjectCoefficient(coeff);
         ParSubMesh::Transfer(cylinder_gf, parent_gf);
         tmp = parent_gf_ex;
         tmp -= parent_gf;
         CHECK_GLOBAL_NORM(tmp);
      }
      SECTION("Volume to matching volume")
      {
         outer_gf.ProjectCoefficient(coeff);
         ParSubMesh::Transfer(outer_gf, parent_gf);
         tmp = parent_gf_ex;
         tmp -= parent_gf;
         CHECK_GLOBAL_NORM(tmp);
      }
      SECTION("Surface to matching surface in volume")
      {
         cylinder_surface_gf.ProjectCoefficient(coeff);
         ParSubMesh::Transfer(cylinder_surface_gf, parent_gf);
         tmp = parent_gf_ex;
         tmp -= parent_gf;
         CHECK_GLOBAL_NORM(tmp);
      }
   }
   SECTION("SubMeshToSubMesh")
   {
      SECTION("Volume to matching volume")
      {
         cylinder_gf.ProjectCoefficient(coeff);
         outer_gf.ProjectCoefficient(coeff);
         outer_gf_ex.ProjectCoefficient(coeff);
         ParSubMesh::Transfer(cylinder_gf, outer_gf);
         tmp = outer_gf_ex;
         tmp -= outer_gf;
         CHECK_GLOBAL_NORM(tmp);
      }
      SECTION("Volume to matching surface on volume")
      {
         cylinder_gf.ProjectCoefficient(coeff);
         outer_gf.ProjectCoefficient(coeff);
         cylinder_gf_ex.ProjectCoefficient(coeff);
         ParSubMesh::Transfer(outer_gf, cylinder_gf);
         tmp = cylinder_gf_ex;
         tmp -= cylinder_gf;
         CHECK_GLOBAL_NORM(tmp);
      }

      SECTION("Volume to matching surface")
      {
         cylinder_gf.ProjectCoefficient(coeff);
         cylinder_surface_gf_ex.ProjectCoefficient(coeff);
         ParSubMesh::Transfer(cylinder_gf, cylinder_surface_gf);
         tmp = cylinder_surface_gf_ex;
         tmp -= cylinder_surface_gf;
         CHECK_GLOBAL_NORM(tmp);
      }
   }
}

TEST_CASE("ParSubMesh", "[Parallel],[ParSubMesh]")
{
   auto fec_type = GENERATE(FECType::H1, FECType::L2);
   multidomain_test_2d(fec_type);
   multidomain_test_3d(fec_type);
}

} // namespace ParSubMeshTests

#endif // MFEM_USE_MPI
<commit_msg>unused variable<commit_after>// Copyright (c) 2010-2022, Lawrence Livermore National Security, LLC. Produced
// at the Lawrence Livermore National Laboratory. All Rights reserved. See files
// LICENSE and NOTICE for details. LLNL-CODE-806117.
//
// This file is part of the MFEM library. For more information and source code
// availability visit https://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the BSD-3 license. We welcome feedback and contributions, see file
// CONTRIBUTING.md for details.

#include "mfem.hpp"
#include "unit_tests.hpp"

using namespace mfem;

#ifdef MFEM_USE_MPI

namespace ParSubMeshTests
{
enum FECType
{
   H1,
   L2
};

FiniteElementCollection *create_fec(FECType fectype, int p, int dim)
{
   switch (fectype)
   {
      case H1:
         return new H1_FECollection(p, dim);
         break;
      case L2:
         return new L2_FECollection(p, dim, BasisType::GaussLobatto);
         break;
   }

   return nullptr;
}

void multidomain_test_2d(FECType fec_type)
{
   const int p = 2;
   double Hy = 1.0;
   Mesh serial_parent_mesh = Mesh::MakeCartesian2D(5, 5,
                                                   Element::QUADRILATERAL, true, 1.0, Hy,
                                                   false);

   for (int i = 0; i < serial_parent_mesh.GetNBE(); i++)
   {
      Element *el = serial_parent_mesh.GetBdrElement(i);
      el->SetAttribute(1);

      Array<int> vertices;
      el->GetVertices(vertices);

      bool all_vtx_inside = true;
      for (int j = 0; j < vertices.Size(); j++)
      {
         if (serial_parent_mesh.GetVertex(vertices[j])[1] < 1.0)
         {
            all_vtx_inside = false;
         }
      }
      if (all_vtx_inside)
      {
         el->SetAttribute(2);
      }
   }
   for (int i = 0; i < serial_parent_mesh.GetNE(); i++)
   {
      Element *el = serial_parent_mesh.GetElement(i);
      el->SetAttribute(1);

      Array<int> vertices;
      el->GetVertices(vertices);

      for (int j = 0; j < vertices.Size(); j++)
      {
         double *coords = serial_parent_mesh.GetVertex(vertices[j]);

         if (coords[0] >= 0.25 &&
             coords[0] <= 0.75 &&
             coords[1] >= 0.25 &&
             coords[1] <= 0.75)
         {
            el->SetAttribute(2);
         }
      }
   }
   serial_parent_mesh.SetAttributes();
   serial_parent_mesh.EnsureNodes();
   serial_parent_mesh.SetCurvature(p);

   auto node_movement_coeff = VectorFunctionCoefficient(
                                 serial_parent_mesh.Dimension(),
                                 [](const Vector &coords, Vector &u)
   {
      double x = coords(0);
      double y = coords(1);

      u(0) = x;
      u(1) = y + 0.05 * sin(x * 2.0 * M_PI);
   });

   serial_parent_mesh.Transform(node_movement_coeff);

   ParMesh parent_mesh(MPI_COMM_WORLD, serial_parent_mesh);

   Array<int> domain1(1);
   domain1[0] = 1;

   Array<int> boundary1(1);
   boundary1[0] = 2;

   auto domain_submesh = ParSubMesh::CreateFromDomain(parent_mesh,
                                                      domain1);

   auto boundary_submesh = ParSubMesh::CreateFromDomain(parent_mesh,
                                                        boundary1);

   FiniteElementCollection *fec = create_fec(fec_type, p, parent_mesh.Dimension());

   ParFiniteElementSpace parent_fes(&parent_mesh, fec);
   ParGridFunction parent_gf(&parent_fes);

   ParFiniteElementSpace domain1_fes(&domain_submesh, fec);
   ParGridFunction domain1_gf(&domain1_fes);

   FiniteElementCollection *surface_fec = create_fec(fec_type, p,
                                                     domain_submesh.Dimension());
   ParFiniteElementSpace boundary1_fes(&boundary_submesh, surface_fec);
   ParGridFunction boundary1_gf(&boundary1_fes);

   auto coeff = FunctionCoefficient([](const Vector &coords)
   {
      double x = coords(0);
      double y = coords(1);
      return y + 0.05 * sin(x * 2.0 * M_PI);
   });

   parent_gf.ProjectCoefficient(coeff);

   Vector tmp;

   ParGridFunction parent_gf_ex(&parent_fes);
   parent_gf_ex.ProjectCoefficient(coeff);

   ParGridFunction domain1_gf_ex(&domain1_fes);
   domain1_gf_ex.ProjectCoefficient(coeff);

   ParGridFunction boundary1_gf_ex(&boundary1_fes);
   boundary1_gf_ex.ProjectCoefficient(coeff);

   auto CHECK_GLOBAL_NORM = [](Vector &v)
   {
      double norm_local = v.Norml2(), norm_global = 0.0;
      MPI_Allreduce(&norm_local, &norm_global, 1, MPI_DOUBLE, MPI_SUM,
                    MPI_COMM_WORLD);
      REQUIRE(norm_global < 1e-8);
   };

   SECTION("ParentToSubMesh")
   {
      SECTION("Volume to matching volume")
      {
         ParSubMesh::Transfer(parent_gf, domain1_gf);
         tmp = domain1_gf_ex;
         tmp -= domain1_gf;
         CHECK_GLOBAL_NORM(tmp);
      }
      SECTION("Volume to matching surface")
      {
         ParSubMesh::Transfer(parent_gf, boundary1_gf);
         tmp = boundary1_gf_ex;
         tmp -= boundary1_gf;
         CHECK_GLOBAL_NORM(tmp);
      }
   }
   SECTION("SubMeshToParent")
   {
      SECTION("Volume to matching volume")
      {
         parent_gf.ProjectCoefficient(coeff);
         domain1_gf.ProjectCoefficient(coeff);
         ParSubMesh::Transfer(domain1_gf, parent_gf);
         tmp = parent_gf_ex;
         tmp -= parent_gf;
         CHECK_GLOBAL_NORM(tmp);
      }
      SECTION("Surface to matching surface in volume")
      {
         boundary1_gf.ProjectCoefficient(coeff);
         ParSubMesh::Transfer(boundary1_gf, parent_gf);
         tmp = parent_gf_ex;
         tmp -= parent_gf;
         CHECK_GLOBAL_NORM(tmp);
      }
   }
}

void multidomain_test_3d(FECType fec_type)
{
   const int p = 2;
   // Circle: sideset 1
   // Domain boundary: sideset 2
   Mesh *serial_parent_mesh = new Mesh("../../data/multidomain-hex.mesh");
   ParMesh parent_mesh(MPI_COMM_WORLD, *serial_parent_mesh);
   delete serial_parent_mesh;

   Array<int> cylinder_domain_attributes(1);
   cylinder_domain_attributes[0] = 1;

   Array<int> outer_domain_attributes(1);
   outer_domain_attributes[0] = 2;

   Array<int> cylinder_surface_attributes(1);
   cylinder_surface_attributes[0] = 9;

   auto cylinder_submesh = ParSubMesh::CreateFromDomain(parent_mesh,
                                                        cylinder_domain_attributes);

   auto outer_submesh = ParSubMesh::CreateFromDomain(parent_mesh,
                                                     outer_domain_attributes);

   auto cylinder_surface_submesh = ParSubMesh::CreateFromBoundary(parent_mesh,
                                                                  cylinder_surface_attributes);

   FiniteElementCollection *fec = create_fec(fec_type, p, parent_mesh.Dimension());

   ParFiniteElementSpace parent_fes(&parent_mesh, fec);
   ParGridFunction parent_gf(&parent_fes);

   ParFiniteElementSpace cylinder_fes(&cylinder_submesh, fec);
   ParGridFunction cylinder_gf(&cylinder_fes);

   ParFiniteElementSpace outer_fes(&outer_submesh, fec);
   ParGridFunction outer_gf(&outer_fes);

   FiniteElementCollection *surface_fec = create_fec(fec_type, p,
                                                     cylinder_surface_submesh.Dimension());
   ParFiniteElementSpace cylinder_surface_fes(&cylinder_surface_submesh,
                                              surface_fec);
   ParGridFunction cylinder_surface_gf(&cylinder_surface_fes);

   auto coeff = FunctionCoefficient([](const Vector &coords)
   {
      double x = coords(0);
      double y = coords(1);
      double z = coords(2);
      return y + 0.05 * sin(x * 2.0 * M_PI) + z;
   });

   parent_gf.ProjectCoefficient(coeff);

   Vector tmp;

   ParGridFunction parent_gf_ex(&parent_fes);
   parent_gf_ex.ProjectCoefficient(coeff);

   ParGridFunction cylinder_gf_ex(&cylinder_fes);
   cylinder_gf_ex.ProjectCoefficient(coeff);

   ParGridFunction cylinder_surface_gf_ex(&cylinder_surface_fes);
   cylinder_surface_gf_ex.ProjectCoefficient(coeff);

   ParGridFunction outer_gf_ex(&outer_fes);
   outer_gf_ex.ProjectCoefficient(coeff);

   auto CHECK_GLOBAL_NORM = [](Vector &v)
   {
      double norm_local = v.Norml2(), norm_global = 0.0;
      MPI_Allreduce(&norm_local, &norm_global, 1, MPI_DOUBLE, MPI_SUM,
                    MPI_COMM_WORLD);
      REQUIRE(norm_global < 1e-8);
   };

   SECTION("ParentToSubMesh")
   {
      SECTION("Volume to matching volume")
      {
         ParSubMesh::Transfer(parent_gf, cylinder_gf);
         tmp = cylinder_gf_ex;
         tmp -= cylinder_gf;
         CHECK_GLOBAL_NORM(tmp);
      }
      SECTION("Volume to matching surface")
      {
         ParSubMesh::Transfer(parent_gf, cylinder_surface_gf);
         tmp = cylinder_surface_gf_ex;
         tmp -= cylinder_surface_gf;
         CHECK_GLOBAL_NORM(tmp);
      }
   }
   SECTION("SubMeshToParent")
   {
      SECTION("Volume to matching volume")
      {
         parent_gf.ProjectCoefficient(coeff);
         cylinder_gf.ProjectCoefficient(coeff);
         ParSubMesh::Transfer(cylinder_gf, parent_gf);
         tmp = parent_gf_ex;
         tmp -= parent_gf;
         CHECK_GLOBAL_NORM(tmp);
      }
      SECTION("Volume to matching volume")
      {
         outer_gf.ProjectCoefficient(coeff);
         ParSubMesh::Transfer(outer_gf, parent_gf);
         tmp = parent_gf_ex;
         tmp -= parent_gf;
         CHECK_GLOBAL_NORM(tmp);
      }
      SECTION("Surface to matching surface in volume")
      {
         cylinder_surface_gf.ProjectCoefficient(coeff);
         ParSubMesh::Transfer(cylinder_surface_gf, parent_gf);
         tmp = parent_gf_ex;
         tmp -= parent_gf;
         CHECK_GLOBAL_NORM(tmp);
      }
   }
   SECTION("SubMeshToSubMesh")
   {
      SECTION("Volume to matching volume")
      {
         cylinder_gf.ProjectCoefficient(coeff);
         outer_gf.ProjectCoefficient(coeff);
         outer_gf_ex.ProjectCoefficient(coeff);
         ParSubMesh::Transfer(cylinder_gf, outer_gf);
         tmp = outer_gf_ex;
         tmp -= outer_gf;
         CHECK_GLOBAL_NORM(tmp);
      }
      SECTION("Volume to matching surface on volume")
      {
         cylinder_gf.ProjectCoefficient(coeff);
         outer_gf.ProjectCoefficient(coeff);
         cylinder_gf_ex.ProjectCoefficient(coeff);
         ParSubMesh::Transfer(outer_gf, cylinder_gf);
         tmp = cylinder_gf_ex;
         tmp -= cylinder_gf;
         CHECK_GLOBAL_NORM(tmp);
      }

      SECTION("Volume to matching surface")
      {
         cylinder_gf.ProjectCoefficient(coeff);
         cylinder_surface_gf_ex.ProjectCoefficient(coeff);
         ParSubMesh::Transfer(cylinder_gf, cylinder_surface_gf);
         tmp = cylinder_surface_gf_ex;
         tmp -= cylinder_surface_gf;
         CHECK_GLOBAL_NORM(tmp);
      }
   }
}

TEST_CASE("ParSubMesh", "[Parallel],[ParSubMesh]")
{
   auto fec_type = GENERATE(FECType::H1, FECType::L2);
   multidomain_test_2d(fec_type);
   multidomain_test_3d(fec_type);
}

} // namespace ParSubMeshTests

#endif // MFEM_USE_MPI
<|endoftext|>


<commit_before>/*------------------------------------------------------------------------------

    Copyright (c) 2004 Media Development Loan Fund

    This file is part of the Campcaster project.
    http://campcaster.campware.org/
    To report bugs, send an e-mail to bugs@campware.org

    Campcaster is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    Campcaster is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with Campcaster; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

    Author   : $Author$
    Version  : $Revision$
    Location : $URL$

------------------------------------------------------------------------------*/

/* ============================================================ include files */

#ifdef HAVE_CONFIG_H
#include "configure.h"
#endif

#define DEBUG_PREFIX "SchedulerThread"
#include "LiveSupport/Core/Debug.h"

#include "LiveSupport/Core/TimeConversion.h"

#include "SchedulerThread.h"

using namespace LiveSupport::Core;
using namespace LiveSupport::EventScheduler;

/* ===================================================  local data structures */

/* ================================================  local constants & macros */

/* ===============================================  local function prototypes */

/* =============================================================  module code */

/*------------------------------------------------------------------------------
 *  Constructor.
 *----------------------------------------------------------------------------*/
SchedulerThread :: SchedulerThread(
                        Ptr<EventContainerInterface>::Ref   eventContainer,
                        Ptr<time_duration>::Ref             granularity)
                                                                    throw ()
      : eventContainer(eventContainer),
        granularity(granularity),
        shouldRun(false),
        isPreloading(false)
{
    //DEBUG_FUNC_INFO
}

/*------------------------------------------------------------------------------
 *  Get the next event from the eventContainer
 *----------------------------------------------------------------------------*/
void
SchedulerThread :: getNextEvent(Ptr<ptime>::Ref     when)       throw ()
{
    //DEBUG_FUNC_INFO

    nextEvent = eventContainer->getNextEvent(when);
    if (nextEvent.get()) {
        nextEventTime = nextEvent->getScheduledTime();
        nextInitTime.reset(new ptime(*nextEventTime
                                   - *granularity
                                   - *nextEvent->maxTimeToInitialize()));
        nextEventEnd.reset(new ptime(*nextEventTime
                                   + *nextEvent->eventLength()));
        debug() << "::getNextEvent() - nextInitTime:  "
                << to_simple_string(*nextInitTime) << endl;
        debug() << "                 - nextEventTime: "
                << to_simple_string(*nextEventTime) << endl;
        debug() << "                 - nextEventEnd:  "
                << to_simple_string(*nextEventEnd) << endl;
    }
}

/*------------------------------------------------------------------------------
 *  The main execution body of the thread.
 *----------------------------------------------------------------------------*/
void
SchedulerThread :: nextStep(Ptr<ptime>::Ref     now)            throw ()
{
    if (nextEvent) {
        if (imminent(now, nextInitTime)) {
            debug() << "::nextStep() - Init [" << *TimeConversion::now()
                    << "]" << endl;
            try {
                nextEvent->initialize();
            } catch (std::exception &e) {
                // cancel event by getting the next event after this was
                // supposed to finish
                getNextEvent(nextEventEnd);
                // TODO: log error
                std::cerr << "event initialization error: " << e.what()
                          << std::endl;
            }
            isPreloading = true;
        } else if (imminent(now, nextEventTime)) {
            Ptr<time_duration>::Ref timeLeft(new time_duration(*nextEventTime
                                                             - *now));
            TimeConversion::sleep(timeLeft);
            debug() << "::nextStep() - Start [" << *TimeConversion::now()
                    << "]" << endl;
            nextEvent->start();
            currentEvent = nextEvent;
            currentEventEnd = nextEventEnd;
            getNextEvent(TimeConversion::now());
            isPreloading = false;
        }
    }

    if (currentEvent && imminent(now, currentEventEnd)) {
        Ptr<time_duration>::Ref timeLeft(new time_duration(*currentEventEnd
                                                         - *now));
        TimeConversion::sleep(timeLeft);
        currentEvent->stop();
        currentEvent->deInitialize();
        currentEvent.reset();
        isPreloading = false;
        debug() << "::nextStep() - End [" << *TimeConversion::now()
                << "]" << endl;
    }
}

/*------------------------------------------------------------------------------
 *  The main execution body of the thread.
 *----------------------------------------------------------------------------*/
void
SchedulerThread :: run(void)                                    throw ()
{
    //DEBUG_FUNC_INFO

    shouldRun = true;
    getNextEvent(TimeConversion::now());

    while (shouldRun) {
        Ptr<ptime>::Ref     start = TimeConversion::now();

        nextStep(start);

        // sleep until the next granularity
        Ptr<ptime>::Ref             end = TimeConversion::now();
        Ptr<time_duration>::Ref     diff(new time_duration(*end - *start));
        if (*diff <= *granularity) {
            Ptr<time_duration>::Ref sleepTime(new time_duration(*granularity
                                                              - *diff));
            TimeConversion::sleep(sleepTime);
        }
    }
}

/*------------------------------------------------------------------------------
 *  Accept a signal.
 *----------------------------------------------------------------------------*/
void
SchedulerThread :: signal(int signalId)                         throw ()
{
    //DEBUG_FUNC_INFO
    debug() << "::signal() - [" << *TimeConversion::now() << "]" << endl;

    switch (signalId) {
        case UpdateSignal:
            if (!isPreloading) {
                getNextEvent(TimeConversion::now());
            }
            break;

        default:
            break;
    }
}

<commit_msg>this line made no sense<commit_after>/*------------------------------------------------------------------------------

    Copyright (c) 2004 Media Development Loan Fund

    This file is part of the Campcaster project.
    http://campcaster.campware.org/
    To report bugs, send an e-mail to bugs@campware.org

    Campcaster is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    Campcaster is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with Campcaster; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

    Author   : $Author$
    Version  : $Revision$
    Location : $URL$

------------------------------------------------------------------------------*/

/* ============================================================ include files */

#ifdef HAVE_CONFIG_H
#include "configure.h"
#endif

#define DEBUG_PREFIX "SchedulerThread"
#include "LiveSupport/Core/Debug.h"

#include "LiveSupport/Core/TimeConversion.h"

#include "SchedulerThread.h"

using namespace LiveSupport::Core;
using namespace LiveSupport::EventScheduler;

/* ===================================================  local data structures */

/* ================================================  local constants & macros */

/* ===============================================  local function prototypes */

/* =============================================================  module code */

/*------------------------------------------------------------------------------
 *  Constructor.
 *----------------------------------------------------------------------------*/
SchedulerThread :: SchedulerThread(
                        Ptr<EventContainerInterface>::Ref   eventContainer,
                        Ptr<time_duration>::Ref             granularity)
                                                                    throw ()
      : eventContainer(eventContainer),
        granularity(granularity),
        shouldRun(false),
        isPreloading(false)
{
    //DEBUG_FUNC_INFO
}

/*------------------------------------------------------------------------------
 *  Get the next event from the eventContainer
 *----------------------------------------------------------------------------*/
void
SchedulerThread :: getNextEvent(Ptr<ptime>::Ref     when)       throw ()
{
    //DEBUG_FUNC_INFO

    nextEvent = eventContainer->getNextEvent(when);
    if (nextEvent.get()) {
        nextEventTime = nextEvent->getScheduledTime();
        nextInitTime.reset(new ptime(*nextEventTime
                                   - *granularity
                                   - *nextEvent->maxTimeToInitialize()));
        nextEventEnd.reset(new ptime(*nextEventTime
                                   + *nextEvent->eventLength()));
        debug() << "::getNextEvent() - nextInitTime:  "
                << to_simple_string(*nextInitTime) << endl;
        debug() << "                 - nextEventTime: "
                << to_simple_string(*nextEventTime) << endl;
        debug() << "                 - nextEventEnd:  "
                << to_simple_string(*nextEventEnd) << endl;
    }
}

/*------------------------------------------------------------------------------
 *  The main execution body of the thread.
 *----------------------------------------------------------------------------*/
void
SchedulerThread :: nextStep(Ptr<ptime>::Ref     now)            throw ()
{
    if (nextEvent) {
        if (imminent(now, nextInitTime)) {
            debug() << "::nextStep() - Init [" << *TimeConversion::now()
                    << "]" << endl;
            try {
                nextEvent->initialize();
            } catch (std::exception &e) {
                // cancel event by getting the next event after this was
                // supposed to finish
                getNextEvent(nextEventEnd);
                // TODO: log error
                std::cerr << "event initialization error: " << e.what()
                          << std::endl;
            }
            isPreloading = true;
        } else if (imminent(now, nextEventTime)) {
            Ptr<time_duration>::Ref timeLeft(new time_duration(*nextEventTime
                                                             - *now));
            TimeConversion::sleep(timeLeft);
            debug() << "::nextStep() - Start [" << *TimeConversion::now()
                    << "]" << endl;
            nextEvent->start();
            currentEvent = nextEvent;
            currentEventEnd = nextEventEnd;
            getNextEvent(TimeConversion::now());
            isPreloading = false;
        }
    }

    if (currentEvent && imminent(now, currentEventEnd)) {
        Ptr<time_duration>::Ref timeLeft(new time_duration(*currentEventEnd
                                                         - *now));
        TimeConversion::sleep(timeLeft);
        currentEvent->stop();
        currentEvent->deInitialize();
        currentEvent.reset();
        debug() << "::nextStep() - End [" << *TimeConversion::now()
                << "]" << endl;
    }
}

/*------------------------------------------------------------------------------
 *  The main execution body of the thread.
 *----------------------------------------------------------------------------*/
void
SchedulerThread :: run(void)                                    throw ()
{
    //DEBUG_FUNC_INFO

    shouldRun = true;
    getNextEvent(TimeConversion::now());

    while (shouldRun) {
        Ptr<ptime>::Ref     start = TimeConversion::now();

        nextStep(start);

        // sleep until the next granularity
        Ptr<ptime>::Ref             end = TimeConversion::now();
        Ptr<time_duration>::Ref     diff(new time_duration(*end - *start));
        if (*diff <= *granularity) {
            Ptr<time_duration>::Ref sleepTime(new time_duration(*granularity
                                                              - *diff));
            TimeConversion::sleep(sleepTime);
        }
    }
}

/*------------------------------------------------------------------------------
 *  Accept a signal.
 *----------------------------------------------------------------------------*/
void
SchedulerThread :: signal(int signalId)                         throw ()
{
    //DEBUG_FUNC_INFO
    debug() << "::signal() - [" << *TimeConversion::now() << "]" << endl;

    switch (signalId) {
        case UpdateSignal:
            if (!isPreloading) {
                getNextEvent(TimeConversion::now());
            }
            break;

        default:
            break;
    }
}

<|endoftext|>


<commit_before>#ifndef URASTER_HPP
#define URASTER_HPP

#include<iostream>
#include<Eigen/Dense>
#include<Eigen/LU>	//for .inverse().  Probably not needed
#include<vector>
#include<array>
#include<memory>
#include<functional>

namespace uraster
{

template<class PixelType>
class Framebuffer
{
protected:
	std::vector<PixelType> data;
	std::size_t fw,fh;
public:
	const std::size_t& width;
	const std::size_t& height;
	Framebuffer(std::size_t w,std::size_t h):
		data(w*h),
		fw(w),fh(h),
		width(fw),height(fh)
	{}
	PixelType& operator()(std::size_t x,std::size_t y)
	{
		return data[y*width+x];
	}
	const PixelType& operator()(std::size_t x,std::size_t y) const
	{
		return data[y*width+x];
	}
	void clear(const PixelType& pt=PixelType())
	{
		std::fill(data.begin(),data.end(),pt);
	}
};

template<class VertexVsIn,class VertexVsOut,class VertShader>
void run_vertex_shader(const VertexVsIn* b,const VertexVsIn* e,VertexVsOut* o,
	VertShader vertex_shader)
{
	std::size_t n=e-b;
	#pragma omp parallel for
	for(std::size_t i=0;i<n;i++)
	{
		o[i]=vertex_shader(b[i]);
	}
}

template<class PixelOut,class VertexVsOut,class FragShader>
void rasterize_triangle(Framebuffer<PixelOut>& fb,const std::array<VertexVsOut,3>& verts,FragShader fragment_shader)
{
	std::array<Eigen::Vector4f,3> points{{verts[0].position(),verts[1].position(),verts[2].position()}};

	std::array<Eigen::Vector4f,3> epoints{{points[0]/points[0][3],points[1]/points[1][3],points[2]/points[2][3]}};

	auto ss1=epoints[0].head<2>().array(),ss2=epoints[1].head<2>().array(),ss3=epoints[2].head<2>().array();
	//calculate the bounding box of the triangle in screen space floating point.
	Eigen::Array2f bb_ul=ss1.min(ss2).min(ss3);
	Eigen::Array2f bb_lr=ss1.max(ss2).max(ss3);
	Eigen::Array2i isz(fb.width,fb.height);
	Eigen::Array2i ibb_ul=((bb_ul*0.5f+0.5f)*isz.cast<float>()).cast<int>();	//move bounding box from (-1.0,1.0)->(0,imgdim)
	Eigen::Array2i ibb_lr=((bb_lr*0.5f+0.5f)*isz.cast<float>()).cast<int>();
	ibb_lr+=1;	//add one pixel of coverage
	//clamp the bounding box to the framebuffer size
	ibb_ul=ibb_ul.max(Eigen::Array2i(0,0));
	ibb_lr=ibb_lr.min(isz);

	//Pre-compute barycentric
	Eigen::Matrix2f T;
	T << (ss1-ss3).matrix(),(ss2-ss3).matrix();
	Eigen::Matrix2f Ti=T.inverse();

	for(int y=ibb_ul[1];y<ibb_lr[1];y++)
	for(int x=ibb_ul[0];x<ibb_lr[0];x++)
	{
		Eigen::Vector2f ssc(x,y);
		ssc.array()/=isz.cast<float>();	//move pixel to relative coordinates
		ssc.array()-=0.5f;
		ssc.array()*=2.0f;

		//Compute barycentric coordinates
		Eigen::Vector3f bary;
		bary.head<2>()=Ti*(ssc-epoints[2].head<2>());
		bary[2]=1.0f-bary[0]-bary[1];

		if((bary.array() < 1.0f).all() && (bary.array() > 0.0f).all())
		{
			float d=bary[0]*epoints[0][2]+bary[1]*epoints[1][2]+bary[2]*epoints[2][2];
			PixelOut& po=fb(x,y);
			if(po.depth() < d && d < 1.0) //depth test
			{
				VertexVsOut v;
				for(int i=0;i<3;i++)
				{
					VertexVsOut vt=verts[i];
					vt*=bary[i];
					v+=vt;	//interpolate varying parameters
				}
				po=fragment_shader(v);
				po.depth()=d;
			}
		}
	}
}

template<class PixelOut,class VertexVsOut,class FragShader>
void rasterize(Framebuffer<PixelOut>& fb,const std::size_t* ib,const std::size_t* ie,const VertexVsOut* verts,
	FragShader fragment_shader)
{
	std::size_t n=ie-ib;
	#pragma omp parallel for
	for(std::size_t i=0;i<n;i+=3)
	{
		const std::size_t* ti=ib+i;
		std::array<VertexVsOut,3> tri{{verts[ti[0]],verts[ti[1]],verts[ti[2]]}};
		rasterize_triangle(fb,tri,fragment_shader);
	}
}

template<class PixelOut,class VertexVsOut,class VertexVsIn,class VertShader, class FragShader>
void draw(	Framebuffer<PixelOut>& fb,
		const VertexVsIn* vertexbuffer_b,const VertexVsIn* vertexbuffer_e,
		const std::size_t* indexbuffer_b,const std::size_t* indexbuffer_e,
		VertexVsOut* vcache_b,VertexVsOut* vcache_e,
		VertShader vertex_shader,
		FragShader fragment_shader)
{
	std::unique_ptr<VertexVsOut[]> vc;
	if(vcache_b==NULL || (vcache_e-vcache_b) != (vertexbuffer_e-vertexbuffer_b))
	{
		vcache_b=new VertexVsOut[(vertexbuffer_e-vertexbuffer_b)];
		vc.reset(vcache_b);
	}
	run_vertex_shader(vertexbuffer_b,vertexbuffer_e,vcache_b,vertex_shader);
	rasterize(fb,indexbuffer_b,indexbuffer_e,vcache_b,fragment_shader);
}

}

#endif
<commit_msg>Comments<commit_after>#ifndef URASTER_HPP
#define URASTER_HPP

#include<iostream>
#include<Eigen/Dense>
#include<Eigen/LU>	//for .inverse().  Probably not needed
#include<vector>
#include<array>
#include<memory>
#include<functional>

namespace uraster
{

//This is the framebuffer class.  It's a part of namespace uraster because the uraster needs to have a well-defined image class to render to.
//It is templated because the output type need not be only colors, could contain anything (like a stencil buffer or depth buffer or gbuffer for deferred rendering)
template<class PixelType>
class Framebuffer
{
protected:
	std::vector<PixelType> data;
	std::size_t fw,fh;
public:
	const std::size_t& width;
	const std::size_t& height;
	//constructor initializes the array
	Framebuffer(std::size_t w,std::size_t h):
		data(w*h),
		fw(w),fh(h),
		width(fw),height(fh)
	{}
	//2D pixel access
	PixelType& operator()(std::size_t x,std::size_t y)
	{
		return data[y*width+x];
	}
	//const version
	const PixelType& operator()(std::size_t x,std::size_t y) const
	{
		return data[y*width+x];
	}
	void clear(const PixelType& pt=PixelType())
	{
		std::fill(data.begin(),data.end(),pt);
	}
};

//This function runs the vertex shader on all the vertices, producing the varyings that will be interpolated by the rasterizer.
//VertexVsIn can be anything, VertexVsOut MUST have a position() method that returns a 4D vector, and it must have an overloaded *= and += operator for the interpolation
//The right way to think of VertexVsOut is that it is the class you write containing the varying outputs from the vertex shader.
template<class VertexVsIn,class VertexVsOut,class VertShader>
void run_vertex_shader(const VertexVsIn* b,const VertexVsIn* e,VertexVsOut* o,
	VertShader vertex_shader)
{
	std::size_t n=e-b;
	#pragma omp parallel for
	for(std::size_t i=0;i<n;i++)
	{
		o[i]=vertex_shader(b[i]);
	}
}
//This function takes in 3 varyings vertices from the fragment shader that make up a triangle,
//rasterizes the triangle and runs the fragment shader on each resulting pixel.
template<class PixelOut,class VertexVsOut,class FragShader>
void rasterize_triangle(Framebuffer<PixelOut>& fb,const std::array<VertexVsOut,3>& verts,FragShader fragment_shader)
{
	std::array<Eigen::Vector4f,3> points{{verts[0].position(),verts[1].position(),verts[2].position()}};
	//Do the perspective divide by w to get screen space coordinates.
	std::array<Eigen::Vector4f,3> epoints{{points[0]/points[0][3],points[1]/points[1][3],points[2]/points[2][3]}};
	auto ss1=epoints[0].head<2>().array(),ss2=epoints[1].head<2>().array(),ss3=epoints[2].head<2>().array();

	//calculate the bounding box of the triangle in screen space floating point.
	Eigen::Array2f bb_ul=ss1.min(ss2).min(ss3);
	Eigen::Array2f bb_lr=ss1.max(ss2).max(ss3);
	Eigen::Array2i isz(fb.width,fb.height);

	//convert bounding box to fixed point.
	//move bounding box from (-1.0,1.0)->(0,imgdim)
	Eigen::Array2i ibb_ul=((bb_ul*0.5f+0.5f)*isz.cast<float>()).cast<int>();
	Eigen::Array2i ibb_lr=((bb_lr*0.5f+0.5f)*isz.cast<float>()).cast<int>();
	ibb_lr+=1;	//add one pixel of coverage

	//clamp the bounding box to the framebuffer size if necessary (this is clipping.  Not quite how the GPU actually does it but same effect sorta).
	ibb_ul=ibb_ul.max(Eigen::Array2i(0,0));
	ibb_lr=ibb_lr.min(isz);

	//Pre-compute barycentric transform to the resulting triangle.
	Eigen::Matrix2f T;
	T << (ss1-ss3).matrix(),(ss2-ss3).matrix();
	Eigen::Matrix2f Ti=T.inverse();

	//for all the pixels in the bounding box
	for(int y=ibb_ul[1];y<ibb_lr[1];y++)
	for(int x=ibb_ul[0];x<ibb_lr[0];x++)
	{
		Eigen::Vector2f ssc(x,y);
		ssc.array()/=isz.cast<float>();	//move pixel to relative coordinates
		ssc.array()-=0.5f;
		ssc.array()*=2.0f;

		//Compute barycentric coordinates
		Eigen::Vector3f bary;
		bary.head<2>()=Ti*(ssc-epoints[2].head<2>());
		bary[2]=1.0f-bary[0]-bary[1];

		//if the pixel has valid barycentric coordinates, the pixel is in the triangle
		if((bary.array() < 1.0f).all() && (bary.array() > 0.0f).all())
		{
			float d=bary[0]*epoints[0][2]+bary[1]*epoints[1][2]+bary[2]*epoints[2][2];
			//Reference the current pixel at that coordinate
			PixelOut& po=fb(x,y);
			// if the interpolated depth passes the depth test
			if(po.depth() < d && d < 1.0)
			{
				//interpolate varying parameters
				VertexVsOut v;
				for(int i=0;i<3;i++)
				{
					VertexVsOut vt=verts[i];
					vt*=bary[i];
					v+=vt;
				}
				//call the fragment shader
				po=fragment_shader(v);
				po.depth()=d; //write the depth buffer
			}
		}
	}
}

//This function rasterizes a set of triangles determined by an index buffer and a buffer of output verts.
template<class PixelOut,class VertexVsOut,class FragShader>
void rasterize(Framebuffer<PixelOut>& fb,const std::size_t* ib,const std::size_t* ie,const VertexVsOut* verts,
	FragShader fragment_shader)
{
	std::size_t n=ie-ib;
	#pragma omp parallel for
	for(std::size_t i=0;i<n;i+=3)
	{
		const std::size_t* ti=ib+i;
		std::array<VertexVsOut,3> tri{{verts[ti[0]],verts[ti[1]],verts[ti[2]]}};
		rasterize_triangle(fb,tri,fragment_shader);
	}
}

//This function does a draw call from an indexed buffer
template<class PixelOut,class VertexVsOut,class VertexVsIn,class VertShader, class FragShader>
void draw(	Framebuffer<PixelOut>& fb,
		const VertexVsIn* vertexbuffer_b,const VertexVsIn* vertexbuffer_e,
		const std::size_t* indexbuffer_b,const std::size_t* indexbuffer_e,
		VertexVsOut* vcache_b,VertexVsOut* vcache_e,
		VertShader vertex_shader,
		FragShader fragment_shader)
{
	std::unique_ptr<VertexVsOut[]> vc;
	if(vcache_b==NULL || (vcache_e-vcache_b) != (vertexbuffer_e-vertexbuffer_b))
	{
		vcache_b=new VertexVsOut[(vertexbuffer_e-vertexbuffer_b)];
		vc.reset(vcache_b);
	}
	run_vertex_shader(vertexbuffer_b,vertexbuffer_e,vcache_b,vertex_shader);
	rasterize(fb,indexbuffer_b,indexbuffer_e,vcache_b,fragment_shader);
}

}

#endif
<|endoftext|>


<commit_before>// Copyright (c) 2020 by Robert Bosch GmbH. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef IOX_UTILS_MAC_PLATFORM_SIGNAL_HPP
#define IOX_UTILS_MAC_PLATFORM_SIGNAL_HPP

#include <signal.h>

inline void psignal(int sig, const char *s)
{
    psignal(static_cast<uint>(sig), const char *s)
}

#endif // IOX_UTILS_MAC_PLATFORM_SIGNAL_HPP
<commit_msg>iox-#163 fix psignal<commit_after>// Copyright (c) 2020 by Robert Bosch GmbH. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef IOX_UTILS_MAC_PLATFORM_SIGNAL_HPP
#define IOX_UTILS_MAC_PLATFORM_SIGNAL_HPP

#include <signal.h>

inline void psignal(int sig, const char *s)
{
    psignal(static_cast<unsigned int>(sig), s);
}

#endif // IOX_UTILS_MAC_PLATFORM_SIGNAL_HPP
<|endoftext|>


<commit_before>/*
 *  OpenDBX - A simple but extensible database abstraction layer
 *  Copyright (C) 2004-2008 Norbert Sendetzky and others
 *
 *  Distributed under the terms of the GNU Library General Public Licence
 * version 2 or (at your option) any later version.
 */

#include <string>
#include <vector>
#include <iostream>
#include <cstdlib>
#include <opendbx/api>

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#ifdef HAVE_GETOPT_H
#include <getopt.h>
#endif

#include "odbx-regression.h"

using std::cout;
using std::cerr;
using std::endl;
using std::string;
using OpenDBX::Conn;
using OpenDBX::Stmt;
using OpenDBX::Result;
using OpenDBX::Lob;

void exec( Conn conn[], struct odbxstmt* qptr, int verbose );
void lob_read( Result& result, int pos );

void help( char* name )
{
	cout << "Usage: " << name << " <options>" << endl;
	cout << "   -b <backend>    Database backend (mysql, pgsql, sqlite, sqlite3, firebird, freetds, sybase)" << endl;
	cout << "   -h <server>     Server name, IP address or directory" << endl;
	cout << "   -p <port>       Server port" << endl;
	cout << "   -d <database>   Database or file name" << endl;
	cout << "   -u <user>       User name for authentication" << endl;
	cout << "   -w <password>   Password for authentication" << endl;
	cout << "   -e              Force encrypted connection" << endl;
	cout << "   -r              Number of runs" << endl;
	cout << "   -v              Verbose mode" << endl;
}

int main( int argc, char* argv[] )
{
	int i, j, k;
	struct odbxstmt** stmts = NULL;
	struct odbxstmt* queries = NULL;
	string backend, host, port, db, user, pass;
	int param, verbose = 0, encrypt = 0, runs = 1;
	Conn conn[2];

	while( ( param = getopt( argc, argv, "b:h:p:d:u:w:e:r:v" ) ) != -1 )
	{
		switch( param )
		{
			case 'b':
				backend = string( optarg );
				break;
			case 'h':
				host = string( optarg );
				break;
			case 'p':
				port = string( optarg );
				break;
			case 'd':
				db = string( optarg );
				break;
			case 'u':
				user = string( optarg );
				break;
			case 'w':
				pass = string( optarg );
				break;
			case 'v':
				verbose = 1;
				break;
			case 'e':
				if( optarg != NULL ) { encrypt = (int) strtol( optarg, NULL, 10 ); }
				break;
			case 'r':
				if( optarg != NULL ) { runs = (int) strtol( optarg, NULL, 10 ); }
				break;
			default:
				cerr << "Unknown option '" << (char) param << "' with arg '" << (char*) optarg << "'" << endl;
				return 1;
		}
	}

	if( !backend.size() ) { help( argv[0] ); return 1; }

	if( backend.find( "firebird", 0 ) != string::npos ) { stmts = firebird_stmt; }
	if( backend.find( "mssql", 0 ) != string::npos ) { stmts = mssql_stmt; }
	if( backend.find( "mysql", 0 ) != string::npos ) { stmts = mysql_stmt; }
	if( backend.find( "odbc", 0 ) != string::npos ) { stmts = odbc_stmt; }
	if( backend.find( "oracle", 0 ) != string::npos ) { stmts = oracle_stmt; }
	if( backend.find( "pgsql", 0 ) != string::npos ) { stmts = pgsql_stmt; }
	if( backend.find( "sqlite", 0 ) != string::npos ) { stmts = sqlite_stmt; }
	if( backend.find( "sqlite3", 0 ) != string::npos ) { stmts = sqlite3_stmt; }
	if( backend.find( "sybase", 0 ) != string::npos ) { stmts = sybase_stmt; }

	if( stmts == NULL )
	{
		cerr << "Invalid backend: " << backend << endl;
		return 1;
	}
	queries = stmts[0];

	if( verbose )
	{
		cout << endl << "Parameter:" << endl;
		if( !backend.empty() ) { cout << "  backend=" << backend << endl; }
		if( !host.empty() ) { cout << "  host=" << host << endl; }
		if( !port.empty() ) { cout << "  port=" << port << endl; }
		if( !db.empty() ) { cout << "  database=" << db << endl; }
		if( !user.empty() ) { cout << "  user=" << user << endl; }
		if( !pass.empty() ) { cout << "  password=" << pass << endl; }
		if( encrypt ) { cout << "  encrypt=" << encrypt << endl; }
		if( runs ) { cout << "  runs=" << runs << endl; }
		if( verbose ) { cout << "  verbose=" << verbose << endl; }
	}

	for( j = 0; j < runs; j++ )
	{
		try
		{
			if( verbose ) { cout << endl << j+1 << ". Run:" << endl; }

			for( k = 0; k < 2; k++ )
			{
				if( verbose ) { cout << "  Conn::Conn()" << endl; }
				conn[k] = Conn( backend, host, port );

				if( verbose ) { cout << "  Conn::getCapability()" << endl; }
				for( i = 0; i < CAPMAX; i++ )
				{
					cap[i].result = (int) conn[k].getCapability( (odbxcap) cap[i].value );
					cout << "    " << cap[i].name << ": " << cap[i].result << endl;
				}

				if( verbose ) { cout << "  Conn::{get/set}Option()" << endl; }
				for( i = 0; i < OPTMAX; i++ )
				{
					conn[k].getOption( (odbxopt) opt[i].value, (void*) &(opt[i].result) );
					cout << "    " << opt[i].name << ": " << opt[i].result << " " << ( ( opt[i].result && opt[i].tryit ) ? "(using)" : "" ) << endl;

					if( opt[i].result && opt[i].tryit ) { conn[k].setOption( (odbxopt) opt[i].value, (void*) &(opt[i].tryit) ); }

					if( opt[i].value == ODBX_OPT_MULTI_STATEMENTS && opt[i].tryit && opt[i].result ) { queries = stmts[1]; }
				}

				if( encrypt ) { conn[k].setOption( ODBX_OPT_TLS, (void*) &encrypt ); }

				if( verbose ) { cout << "  Conn::bind()" << endl; }
				conn[k].bind( db, user, pass );
			}

			for( i = 0; i < runs; i++ )
			{
				exec( conn, queries, verbose );
			}

			for( k = 0; k < 2; k++ )
			{
				if( verbose ) { cout << "  Conn::finish()" << endl; }
				conn[k].finish();
			}
		}
		catch( OpenDBX::Exception& oe )
		{
			cerr << "Caught exception: " << oe.what() << endl;
			return 1;
		}
		catch( std::exception& e )
		{
			cerr << "Caught STL exception: " << e.what() << endl;
			return 1;
		}
		catch( ... )
		{
			cerr << "Caught unknown exception" << endl;
			return 1;
		}
	}

	return 0;
}

void exec( Conn conn[], struct odbxstmt* qptr, int verbose )
{
	odbxres stat;
	unsigned long fields, i;
	struct timeval tv;

	int cap = conn[qptr->num].getCapability( ODBX_CAP_LO );

	while( qptr->str != NULL )
	{
		try
		{
			if( verbose ) { cout << "  Stmt::execute(" << qptr->num << "): '" << qptr->str << "'" << endl; }

			Stmt stmt = conn[qptr->num].create( string( qptr->str ) );
			Result result = stmt.execute();

			tv.tv_sec = 3;
			tv.tv_usec = 0;

			while( ( stat = result.getResult( &tv, 5 ) ) != ODBX_RES_DONE )
			{
				if( verbose ) { cout << "  Result::getResult()" << endl; }

				tv.tv_sec = 3;
				tv.tv_usec = 0;

				switch( stat )
				{
					case ODBX_RES_TIMEOUT:
						cout << "    Result::getResult(): Timeout" << endl;
						continue;
					case ODBX_RES_NOROWS:
						cout << "    Affected rows: " << result.rowsAffected() << endl;
						continue;
					default:
						break;
				}

				if( verbose ) { cout << "  Result::getColumnCount()" << endl; }
				fields = result.columnCount();

				while( result.getRow() != ODBX_ROW_DONE )
				{
					if( verbose ) { cout << "  Result::getRow()" << endl; }

					for( i = 0; i < fields; i++ )
					{
						cout << "    column " << result.columnPos( result.columnName( i ) ) << " (type " << result.columnType( i ) << "): " << result.columnName( i ) << " = ";

						switch( result.columnType( i ) )
						{
							case ODBX_TYPE_BLOB:
							case ODBX_TYPE_CLOB:

								if( cap == ODBX_ENABLE )
								{
									lob_read( result, i );
									break;
								}

							default:

								if( result.fieldValue( i ) == NULL ) { cout << "NULL" << endl; }
								else { cout << "'" << string( result.fieldValue( i ) ) << "'" << endl; }
						}
					}
				}

				// Test case:  Calling columnPos() with non-existing column name
				try {
					result.columnPos( "non-existing" );
					throw std::runtime_error( string( "No exception thrown using columnPos() for non-exising column name" ) );
				} catch( OpenDBX::Exception& oe ) {
					if( oe.getType() < 0 ) { throw oe; }
				}

				// Test case:  Calling getRow() more often must not result in error
				result.getRow();
			}

			// Test case:  Calling getResult() more often must not result in error
			result.getResult();

			result.finish();
		}
		catch( OpenDBX::Exception& oe )
		{
			if( oe.getType() < 0 ) { throw oe; }
			cerr << "Error in exec(): " << oe.what() << endl;
		}

		qptr++;
	}
}

void lob_read( Result& result, int pos )
{
	char buffer[64];
	ssize_t bytes;

	Lob lob = result.getLob( result.fieldValue( pos ) );

	cout << "'";

	while( ( bytes = lob.read( buffer, sizeof( buffer ) - 1 ) ) != 0 )
	{
		buffer[bytes] = 0;
		cout << buffer;
	}

	cout << "'" << endl;

	lob.close();
}
<commit_msg>fixed missing unbinding of connections<commit_after>/*
 *  OpenDBX - A simple but extensible database abstraction layer
 *  Copyright (C) 2004-2008 Norbert Sendetzky and others
 *
 *  Distributed under the terms of the GNU Library General Public Licence
 * version 2 or (at your option) any later version.
 */

#include <string>
#include <vector>
#include <iostream>
#include <cstdlib>
#include <opendbx/api>

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#ifdef HAVE_GETOPT_H
#include <getopt.h>
#endif

#include "odbx-regression.h"

using std::cout;
using std::cerr;
using std::endl;
using std::string;
using OpenDBX::Conn;
using OpenDBX::Stmt;
using OpenDBX::Result;
using OpenDBX::Lob;

void exec( Conn conn[], struct odbxstmt* qptr, int verbose );
void lob_read( Result& result, int pos );

void help( char* name )
{
	cout << "Usage: " << name << " <options>" << endl;
	cout << "   -b <backend>    Database backend (mysql, pgsql, sqlite, sqlite3, firebird, freetds, sybase)" << endl;
	cout << "   -h <server>     Server name, IP address or directory" << endl;
	cout << "   -p <port>       Server port" << endl;
	cout << "   -d <database>   Database or file name" << endl;
	cout << "   -u <user>       User name for authentication" << endl;
	cout << "   -w <password>   Password for authentication" << endl;
	cout << "   -e              Force encrypted connection" << endl;
	cout << "   -r              Number of runs" << endl;
	cout << "   -v              Verbose mode" << endl;
}

int main( int argc, char* argv[] )
{
	int i, j, k;
	struct odbxstmt** stmts = NULL;
	struct odbxstmt* queries = NULL;
	string backend, host, port, db, user, pass;
	int param, verbose = 0, encrypt = 0, runs = 1;
	Conn conn[2];

	while( ( param = getopt( argc, argv, "b:h:p:d:u:w:e:r:v" ) ) != -1 )
	{
		switch( param )
		{
			case 'b':
				backend = string( optarg );
				break;
			case 'h':
				host = string( optarg );
				break;
			case 'p':
				port = string( optarg );
				break;
			case 'd':
				db = string( optarg );
				break;
			case 'u':
				user = string( optarg );
				break;
			case 'w':
				pass = string( optarg );
				break;
			case 'v':
				verbose = 1;
				break;
			case 'e':
				if( optarg != NULL ) { encrypt = (int) strtol( optarg, NULL, 10 ); }
				break;
			case 'r':
				if( optarg != NULL ) { runs = (int) strtol( optarg, NULL, 10 ); }
				break;
			default:
				cerr << "Unknown option '" << (char) param << "' with arg '" << (char*) optarg << "'" << endl;
				return 1;
		}
	}

	if( !backend.size() ) { help( argv[0] ); return 1; }

	if( backend.find( "firebird", 0 ) != string::npos ) { stmts = firebird_stmt; }
	if( backend.find( "mssql", 0 ) != string::npos ) { stmts = mssql_stmt; }
	if( backend.find( "mysql", 0 ) != string::npos ) { stmts = mysql_stmt; }
	if( backend.find( "odbc", 0 ) != string::npos ) { stmts = odbc_stmt; }
	if( backend.find( "oracle", 0 ) != string::npos ) { stmts = oracle_stmt; }
	if( backend.find( "pgsql", 0 ) != string::npos ) { stmts = pgsql_stmt; }
	if( backend.find( "sqlite", 0 ) != string::npos ) { stmts = sqlite_stmt; }
	if( backend.find( "sqlite3", 0 ) != string::npos ) { stmts = sqlite3_stmt; }
	if( backend.find( "sybase", 0 ) != string::npos ) { stmts = sybase_stmt; }

	if( stmts == NULL )
	{
		cerr << "Invalid backend: " << backend << endl;
		return 1;
	}
	queries = stmts[0];

	if( verbose )
	{
		cout << endl << "Parameter:" << endl;
		if( !backend.empty() ) { cout << "  backend=" << backend << endl; }
		if( !host.empty() ) { cout << "  host=" << host << endl; }
		if( !port.empty() ) { cout << "  port=" << port << endl; }
		if( !db.empty() ) { cout << "  database=" << db << endl; }
		if( !user.empty() ) { cout << "  user=" << user << endl; }
		if( !pass.empty() ) { cout << "  password=" << pass << endl; }
		if( encrypt ) { cout << "  encrypt=" << encrypt << endl; }
		if( runs ) { cout << "  runs=" << runs << endl; }
		if( verbose ) { cout << "  verbose=" << verbose << endl; }
	}

	for( j = 0; j < runs; j++ )
	{
		try
		{
			if( verbose ) { cout << endl << j+1 << ". Run:" << endl; }

			for( k = 0; k < 2; k++ )
			{
				if( verbose ) { cout << "  Conn::Conn()" << endl; }
				conn[k] = Conn( backend, host, port );

				if( verbose ) { cout << "  Conn::getCapability()" << endl; }
				for( i = 0; i < CAPMAX; i++ )
				{
					cap[i].result = (int) conn[k].getCapability( (odbxcap) cap[i].value );
					cout << "    " << cap[i].name << ": " << cap[i].result << endl;
				}

				if( verbose ) { cout << "  Conn::{get/set}Option()" << endl; }
				for( i = 0; i < OPTMAX; i++ )
				{
					conn[k].getOption( (odbxopt) opt[i].value, (void*) &(opt[i].result) );
					cout << "    " << opt[i].name << ": " << opt[i].result << " " << ( ( opt[i].result && opt[i].tryit ) ? "(using)" : "" ) << endl;

					if( opt[i].result && opt[i].tryit ) { conn[k].setOption( (odbxopt) opt[i].value, (void*) &(opt[i].tryit) ); }

					if( opt[i].value == ODBX_OPT_MULTI_STATEMENTS && opt[i].tryit && opt[i].result ) { queries = stmts[1]; }
				}

				if( encrypt ) { conn[k].setOption( ODBX_OPT_TLS, (void*) &encrypt ); }

				if( verbose ) { cout << "  Conn::bind()" << endl; }
				conn[k].bind( db, user, pass );
			}

			for( i = 0; i < runs; i++ )
			{
				exec( conn, queries, verbose );
			}

			for( k = 0; k < 2; k++ )
			{
				if( verbose ) { cout << "  Conn::unbind()" << endl; }
				conn[k].unbind();

				if( verbose ) { cout << "  Conn::finish()" << endl; }
				conn[k].finish();
			}
		}
		catch( OpenDBX::Exception& oe )
		{
			cerr << "Caught exception: " << oe.what() << endl;
			return 1;
		}
		catch( std::exception& e )
		{
			cerr << "Caught STL exception: " << e.what() << endl;
			return 1;
		}
		catch( ... )
		{
			cerr << "Caught unknown exception" << endl;
			return 1;
		}
	}

	return 0;
}

void exec( Conn conn[], struct odbxstmt* qptr, int verbose )
{
	odbxres stat;
	unsigned long fields, i;
	struct timeval tv;

	int cap = conn[qptr->num].getCapability( ODBX_CAP_LO );

	while( qptr->str != NULL )
	{
		try
		{
			if( verbose ) { cout << "  Stmt::execute(" << qptr->num << "): '" << qptr->str << "'" << endl; }

			Stmt stmt = conn[qptr->num].create( qptr->str );
			Result result = stmt.execute();

			tv.tv_sec = 3;
			tv.tv_usec = 0;

			while( ( stat = result.getResult( &tv, 5 ) ) != ODBX_RES_DONE )
			{
				if( verbose ) { cout << "  Result::getResult()" << endl; }

				tv.tv_sec = 3;
				tv.tv_usec = 0;

				switch( stat )
				{
					case ODBX_RES_TIMEOUT:
						cout << "    Result::getResult(): Timeout" << endl;
						continue;
					case ODBX_RES_NOROWS:
						cout << "    Affected rows: " << result.rowsAffected() << endl;
						continue;
					default:
						break;
				}

				if( verbose ) { cout << "  Result::getColumnCount()" << endl; }
				fields = result.columnCount();

				while( result.getRow() != ODBX_ROW_DONE )
				{
					if( verbose ) { cout << "  Result::getRow()" << endl; }

					for( i = 0; i < fields; i++ )
					{
						cout << "    column " << result.columnPos( result.columnName( i ) ) << " (type " << result.columnType( i ) << "): " << result.columnName( i ) << " = ";

						switch( result.columnType( i ) )
						{
							case ODBX_TYPE_BLOB:
							case ODBX_TYPE_CLOB:

								if( cap == ODBX_ENABLE )
								{
									lob_read( result, i );
									break;
								}

							default:

								if( result.fieldValue( i ) == NULL ) { cout << "NULL" << endl; }
								else { cout << "'" << string( result.fieldValue( i ) ) << "'" << endl; }
						}
					}
				}

				// Test case:  Calling columnPos() with non-existing column name
				try {
					result.columnPos( "non-existing" );
					throw std::runtime_error( string( "No exception thrown using columnPos() for non-exising column name" ) );
				} catch( OpenDBX::Exception& oe ) {
					if( oe.getType() < 0 ) { throw oe; }
				}

				// Test case:  Calling getRow() more often must not result in error
				result.getRow();
			}

			// Test case:  Calling getResult() more often must not result in error
			result.getResult();

			result.finish();
		}
		catch( OpenDBX::Exception& oe )
		{
			if( oe.getType() < 0 ) { throw oe; }
			cout << "Error in exec(): " << oe.what() << endl;
		}

		qptr++;
	}
}

void lob_read( Result& result, int pos )
{
	char buffer[64];
	ssize_t bytes;

	Lob lob = result.getLob( result.fieldValue( pos ) );

	cout << "'";

	while( ( bytes = lob.read( buffer, sizeof( buffer ) - 1 ) ) != 0 )
	{
		buffer[bytes] = 0;
		cout << buffer;
	}

	cout << "'" << endl;

	lob.close();
}
<|endoftext|>


<commit_before>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/sync/notifier/registration_manager.h"

#include <cstddef>
#include <deque>
#include <vector>

#include "base/basictypes.h"
#include "chrome/browser/sync/notifier/invalidation_util.h"
#include "chrome/browser/sync/syncable/model_type.h"
#include "google/cacheinvalidation/invalidation-client.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace sync_notifier {
namespace {

// Fake invalidation client that just stores the args of calls to
// Register().
class FakeInvalidationClient : public invalidation::InvalidationClient {
 public:
  FakeInvalidationClient() {}

  virtual ~FakeInvalidationClient() {}

  virtual void Register(const invalidation::ObjectId& oid) {
    registered_oids.push_back(oid);
  }

  virtual void Unregister(const invalidation::ObjectId& oid) {
    ADD_FAILURE();
  }

  virtual invalidation::NetworkEndpoint* network_endpoint() {
    ADD_FAILURE();
    return NULL;
  }

  std::deque<invalidation::ObjectId> registered_oids;

 private:
  DISALLOW_COPY_AND_ASSIGN(FakeInvalidationClient);
};

class RegistrationManagerTest : public testing::Test {
 protected:
  RegistrationManagerTest()
      : registration_manager_(&fake_invalidation_client_) {}

  virtual ~RegistrationManagerTest() {}

  FakeInvalidationClient fake_invalidation_client_;
  RegistrationManager registration_manager_;

 private:
  DISALLOW_COPY_AND_ASSIGN(RegistrationManagerTest);
};

invalidation::ObjectId ModelTypeToObjectId(
    syncable::ModelType model_type) {
  invalidation::ObjectId object_id;
  EXPECT_TRUE(RealModelTypeToObjectId(model_type, &object_id));
  return object_id;
}

syncable::ModelType ObjectIdToModelType(
    const invalidation::ObjectId& object_id) {
  syncable::ModelType model_type = syncable::UNSPECIFIED;
  EXPECT_TRUE(ObjectIdToRealModelType(object_id, &model_type));
  return model_type;
}

invalidation::RegistrationUpdateResult MakeRegistrationUpdateResult(
    syncable::ModelType model_type) {
  invalidation::RegistrationUpdateResult result;
  result.mutable_operation()->
      set_type(invalidation::RegistrationUpdate::REGISTER);
  *result.mutable_operation()->mutable_object_id() =
      ModelTypeToObjectId(model_type);
  result.mutable_status()->set_code(invalidation::Status::SUCCESS);
  return result;
}

TEST_F(RegistrationManagerTest, RegisterType) {
  const syncable::ModelType kModelTypes[] = {
    syncable::BOOKMARKS,
    syncable::PREFERENCES,
    syncable::THEMES,
    syncable::AUTOFILL,
    syncable::EXTENSIONS,
  };
  const size_t kModelTypeCount = arraysize(kModelTypes);

  // Register types.
  for (size_t i = 0; i < kModelTypeCount; ++i) {
    // Register twice; it shouldn't matter.
    registration_manager_.RegisterType(kModelTypes[i]);
    registration_manager_.RegisterType(kModelTypes[i]);
  }

  ASSERT_EQ(kModelTypeCount,
            fake_invalidation_client_.registered_oids.size());

  // Everything should be registered.
  for (size_t i = 0; i < kModelTypeCount; ++i) {
    EXPECT_TRUE(registration_manager_.IsRegistered(kModelTypes[i]));
  }

  // Check object IDs.
  for (size_t i = 0; i < kModelTypeCount; ++i) {
    EXPECT_EQ(kModelTypes[i],
              ObjectIdToModelType(
                  fake_invalidation_client_.registered_oids[i]));
  }
}

TEST_F(RegistrationManagerTest, MarkRegistrationLost) {
  const syncable::ModelType kModelTypes[] = {
    syncable::BOOKMARKS,
    syncable::PREFERENCES,
    syncable::THEMES,
    syncable::AUTOFILL,
    syncable::EXTENSIONS,
  };
  const size_t kModelTypeCount = arraysize(kModelTypes);

  // Register types.
  for (size_t i = 0; i < kModelTypeCount; ++i) {
    registration_manager_.RegisterType(kModelTypes[i]);
  }

  ASSERT_EQ(kModelTypeCount,
            fake_invalidation_client_.registered_oids.size());

  // All should be registered.
  for (size_t i = 0; i < kModelTypeCount; ++i) {
    EXPECT_TRUE(registration_manager_.IsRegistered(kModelTypes[i]));
  }

  // Mark the registrations of all but the first one lost.
  for (size_t i = 1; i < kModelTypeCount; ++i) {
    registration_manager_.MarkRegistrationLost(kModelTypes[i]);
  }

  ASSERT_EQ(2 * kModelTypeCount - 1,
            fake_invalidation_client_.registered_oids.size());

  // All should still be registered.
  for (size_t i = 0; i < kModelTypeCount; ++i) {
    EXPECT_TRUE(registration_manager_.IsRegistered(kModelTypes[i]));
  }
}

TEST_F(RegistrationManagerTest, MarkAllRegistrationsLost) {
  const syncable::ModelType kModelTypes[] = {
    syncable::BOOKMARKS,
    syncable::PREFERENCES,
    syncable::THEMES,
    syncable::AUTOFILL,
    syncable::EXTENSIONS,
  };
  const size_t kModelTypeCount = arraysize(kModelTypes);

  // Register types.
  for (size_t i = 0; i < kModelTypeCount; ++i) {
    registration_manager_.RegisterType(kModelTypes[i]);
  }

  ASSERT_EQ(kModelTypeCount,
            fake_invalidation_client_.registered_oids.size());

  // All should be registered.
  for (size_t i = 0; i < kModelTypeCount; ++i) {
    EXPECT_TRUE(registration_manager_.IsRegistered(kModelTypes[i]));
  }

  // Mark the registrations of all but the first one lost.  Then mark
  // everything lost.
  for (size_t i = 1; i < kModelTypeCount; ++i) {
    registration_manager_.MarkRegistrationLost(kModelTypes[i]);
  }
  registration_manager_.MarkAllRegistrationsLost();

  ASSERT_EQ(3 * kModelTypeCount - 1,
            fake_invalidation_client_.registered_oids.size());

  // All should still be registered.
  for (size_t i = 0; i < kModelTypeCount; ++i) {
    EXPECT_TRUE(registration_manager_.IsRegistered(kModelTypes[i]));
  }
}

}  // namespace
}  // namespace notifier
<commit_msg>[Sync] Removed unused function causing clang build to fail<commit_after>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/sync/notifier/registration_manager.h"

#include <cstddef>
#include <deque>
#include <vector>

#include "base/basictypes.h"
#include "chrome/browser/sync/notifier/invalidation_util.h"
#include "chrome/browser/sync/syncable/model_type.h"
#include "google/cacheinvalidation/invalidation-client.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace sync_notifier {
namespace {

// Fake invalidation client that just stores the args of calls to
// Register().
class FakeInvalidationClient : public invalidation::InvalidationClient {
 public:
  FakeInvalidationClient() {}

  virtual ~FakeInvalidationClient() {}

  virtual void Register(const invalidation::ObjectId& oid) {
    registered_oids.push_back(oid);
  }

  virtual void Unregister(const invalidation::ObjectId& oid) {
    ADD_FAILURE();
  }

  virtual invalidation::NetworkEndpoint* network_endpoint() {
    ADD_FAILURE();
    return NULL;
  }

  std::deque<invalidation::ObjectId> registered_oids;

 private:
  DISALLOW_COPY_AND_ASSIGN(FakeInvalidationClient);
};

class RegistrationManagerTest : public testing::Test {
 protected:
  RegistrationManagerTest()
      : registration_manager_(&fake_invalidation_client_) {}

  virtual ~RegistrationManagerTest() {}

  FakeInvalidationClient fake_invalidation_client_;
  RegistrationManager registration_manager_;

 private:
  DISALLOW_COPY_AND_ASSIGN(RegistrationManagerTest);
};

invalidation::ObjectId ModelTypeToObjectId(
    syncable::ModelType model_type) {
  invalidation::ObjectId object_id;
  EXPECT_TRUE(RealModelTypeToObjectId(model_type, &object_id));
  return object_id;
}

syncable::ModelType ObjectIdToModelType(
    const invalidation::ObjectId& object_id) {
  syncable::ModelType model_type = syncable::UNSPECIFIED;
  EXPECT_TRUE(ObjectIdToRealModelType(object_id, &model_type));
  return model_type;
}

TEST_F(RegistrationManagerTest, RegisterType) {
  const syncable::ModelType kModelTypes[] = {
    syncable::BOOKMARKS,
    syncable::PREFERENCES,
    syncable::THEMES,
    syncable::AUTOFILL,
    syncable::EXTENSIONS,
  };
  const size_t kModelTypeCount = arraysize(kModelTypes);

  // Register types.
  for (size_t i = 0; i < kModelTypeCount; ++i) {
    // Register twice; it shouldn't matter.
    registration_manager_.RegisterType(kModelTypes[i]);
    registration_manager_.RegisterType(kModelTypes[i]);
  }

  ASSERT_EQ(kModelTypeCount,
            fake_invalidation_client_.registered_oids.size());

  // Everything should be registered.
  for (size_t i = 0; i < kModelTypeCount; ++i) {
    EXPECT_TRUE(registration_manager_.IsRegistered(kModelTypes[i]));
  }

  // Check object IDs.
  for (size_t i = 0; i < kModelTypeCount; ++i) {
    EXPECT_EQ(kModelTypes[i],
              ObjectIdToModelType(
                  fake_invalidation_client_.registered_oids[i]));
  }
}

TEST_F(RegistrationManagerTest, MarkRegistrationLost) {
  const syncable::ModelType kModelTypes[] = {
    syncable::BOOKMARKS,
    syncable::PREFERENCES,
    syncable::THEMES,
    syncable::AUTOFILL,
    syncable::EXTENSIONS,
  };
  const size_t kModelTypeCount = arraysize(kModelTypes);

  // Register types.
  for (size_t i = 0; i < kModelTypeCount; ++i) {
    registration_manager_.RegisterType(kModelTypes[i]);
  }

  ASSERT_EQ(kModelTypeCount,
            fake_invalidation_client_.registered_oids.size());

  // All should be registered.
  for (size_t i = 0; i < kModelTypeCount; ++i) {
    EXPECT_TRUE(registration_manager_.IsRegistered(kModelTypes[i]));
  }

  // Mark the registrations of all but the first one lost.
  for (size_t i = 1; i < kModelTypeCount; ++i) {
    registration_manager_.MarkRegistrationLost(kModelTypes[i]);
  }

  ASSERT_EQ(2 * kModelTypeCount - 1,
            fake_invalidation_client_.registered_oids.size());

  // All should still be registered.
  for (size_t i = 0; i < kModelTypeCount; ++i) {
    EXPECT_TRUE(registration_manager_.IsRegistered(kModelTypes[i]));
  }
}

TEST_F(RegistrationManagerTest, MarkAllRegistrationsLost) {
  const syncable::ModelType kModelTypes[] = {
    syncable::BOOKMARKS,
    syncable::PREFERENCES,
    syncable::THEMES,
    syncable::AUTOFILL,
    syncable::EXTENSIONS,
  };
  const size_t kModelTypeCount = arraysize(kModelTypes);

  // Register types.
  for (size_t i = 0; i < kModelTypeCount; ++i) {
    registration_manager_.RegisterType(kModelTypes[i]);
  }

  ASSERT_EQ(kModelTypeCount,
            fake_invalidation_client_.registered_oids.size());

  // All should be registered.
  for (size_t i = 0; i < kModelTypeCount; ++i) {
    EXPECT_TRUE(registration_manager_.IsRegistered(kModelTypes[i]));
  }

  // Mark the registrations of all but the first one lost.  Then mark
  // everything lost.
  for (size_t i = 1; i < kModelTypeCount; ++i) {
    registration_manager_.MarkRegistrationLost(kModelTypes[i]);
  }
  registration_manager_.MarkAllRegistrationsLost();

  ASSERT_EQ(3 * kModelTypeCount - 1,
            fake_invalidation_client_.registered_oids.size());

  // All should still be registered.
  for (size_t i = 0; i < kModelTypeCount; ++i) {
    EXPECT_TRUE(registration_manager_.IsRegistered(kModelTypes[i]));
  }
}

}  // namespace
}  // namespace notifier
<|endoftext|>


<commit_before>//  (C) Copyright Gennadiy Rozental 2001-2005.
//  Distributed under the Boost Software License, Version 1.0.
//  (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)

//  See http://www.boost.org/libs/test for the library home page.
//
//  File        : $RCSfile$
//
//  Version     : $Revision$
//
//  Description : tests floating point comparison algorithms
// ***************************************************************************

// Boost.Test
#include <boost/test/floating_point_comparison.hpp>
#define BOOST_AUTO_TEST_MAIN
#include <boost/test/auto_unit_test.hpp>
#include <boost/test/test_case_template.hpp>
#include <boost/test/output/compiler_log_formatter.hpp>
#include <boost/test/framework.hpp>
#include <boost/test/unit_test_log.hpp>
#include <boost/test/output_test_stream.hpp>
#include <boost/test/detail/unit_test_parameters.hpp>
using namespace boost::unit_test;
using namespace boost::test_tools;

// STL
#include <iostream>
#include <stdio.h>

// Boost
#include <boost/mpl/list.hpp>

namespace boost { namespace test_tools { namespace tt_detail {
template<>
struct print_log_value<float> {
    void operator()( std::ostream& ostr, float t )
    {
        ostr.precision( 6 );

        ostr << t;
    }
};
}}}

namespace boost { namespace test_tools { namespace tt_detail {
template<>
struct print_log_value<double> {
    void operator()( std::ostream& ostr, double t )
    {
        ostr.precision( 10 );
        ostr << t;
    }
};
}}}

namespace boost { namespace test_tools { namespace tt_detail {
template<>
struct print_log_value<long double> {
    void operator()( std::ostream& ostr, long double t )
    {
        ostr.precision( 10 );
        ostr << t;
    }
};
}}}

//____________________________________________________________________________//

struct shorten_lf : public boost::unit_test::output::compiler_log_formatter
{
    void    print_prefix( std::ostream& output, boost::unit_test::const_string, std::size_t line )
    {
        output << line << ": ";
    }
};

//____________________________________________________________________________//

std::string match_file_name( "./test_files/test_fp_comparisons.pattern" );
std::string save_file_name( "test_fp_comparisons.pattern" );

output_test_stream& ots()
{
    static boost::shared_ptr<output_test_stream> inst;

    if( !inst ) {
        inst.reset(
            auto_unit_test_suite()->argc <= 1
                ? new output_test_stream( runtime_config::save_pattern() ? save_file_name : match_file_name, !runtime_config::save_pattern() )
                : new output_test_stream( auto_unit_test_suite()->argv[1], !runtime_config::save_pattern() ) );
    }

    return *inst;
}

//____________________________________________________________________________//

#define TEST_CASE( name )                                   \
void name ## _impl();                                       \
void name ## _impl_defer();                                 \
                                                            \
BOOST_AUTO_TEST_CASE( name )                                \
{                                                           \
    test_case* impl = make_test_case( &name ## _impl, #name ); \
                                                            \
    unit_test_log.set_stream( ots() );                      \
    unit_test_log.set_threshold_level( log_nothing );       \
    unit_test_log.set_formatter( new shorten_lf );          \
    framework::run( impl );                                 \
                                                            \
    unit_test_log.set_threshold_level(                      \
        runtime_config::log_level() != invalid_log_level    \
            ? runtime_config::log_level()                   \
            : log_all_errors );                             \
    unit_test_log.set_format( runtime_config::log_format());\
    unit_test_log.set_stream( std::cout );                  \
    BOOST_CHECK( ots().match_pattern() );                   \
}                                                           \
                                                            \
void name ## _impl()                                        \
{                                                           \
    unit_test_log.set_threshold_level( log_all_errors );    \
                                                            \
    name ## _impl_defer();                                  \
                                                            \
    unit_test_log.set_threshold_level( log_nothing );       \
}                                                           \
                                                            \
void name ## _impl_defer()                                  \
/**/

//____________________________________________________________________________//

template<typename FPT>
struct test_BOOST_CHECK_CLOSE_body {
    void operator()() {
#define DO_BOOST_CHECK_CLOSE( first, second, e )   \
        fp1     = static_cast<FPT>(first);         \
        fp2     = static_cast<FPT>(second);        \
        epsilon = static_cast<FPT>(e);             \
                                                   \
        BOOST_CHECK_CLOSE( fp1, fp2, epsilon );    \
/**/
        unit_test_log.set_threshold_level( log_all_errors );

        FPT fp1, fp2, epsilon;

        DO_BOOST_CHECK_CLOSE( 1, 1, 0 );

        DO_BOOST_CHECK_CLOSE( 0, 1e-20, 1e-5 );
        DO_BOOST_CHECK_CLOSE( 0, 1e-30, 1e-5 );
        DO_BOOST_CHECK_CLOSE( 0, -1e-10, 0.1 );
        DO_BOOST_CHECK_CLOSE( 0.123456, 0.123457, 1e-4 );

        DO_BOOST_CHECK_CLOSE( 0.123456, 0.123457, 1e-3 );

        DO_BOOST_CHECK_CLOSE( 0.123456, -0.123457, 1e-3 );

        DO_BOOST_CHECK_CLOSE( 1.23456e28, 1.23457e28, 1e-3 );

        DO_BOOST_CHECK_CLOSE( 1.23456e-10, 1.23457e-11, 1e-3 );
        DO_BOOST_CHECK_CLOSE( 1.111e-10, 1.112e-10, 0.08999 );
        DO_BOOST_CHECK_CLOSE( 1.112e-10, 1.111e-10, 0.08999 );

        DO_BOOST_CHECK_CLOSE( 1     , 1.0001, 1.1e-2 );
        DO_BOOST_CHECK_CLOSE( 1.0002, 1.0001, 1.1e-2 );

        DO_BOOST_CHECK_CLOSE( 1     , 1.0002, 1.1e-2 );

        unit_test_log.set_threshold_level( log_nothing );
    }
};

//____________________________________________________________________________//

typedef boost::mpl::list<float,double,long double> test_types;

BOOST_AUTO_TEST_CASE_TEMPLATE( test_BOOST_CHECK_CLOSE, FPT, test_types )
{
    test_case* impl = make_test_case( test_BOOST_CHECK_CLOSE_body<FPT>(), "test_BOOST_CHECK_CLOSE" );

    unit_test_log.set_stream( ots() );
    unit_test_log.set_threshold_level( log_nothing );
    unit_test_log.set_formatter( new shorten_lf );

    framework::run( impl );

    unit_test_log.set_threshold_level(
        runtime_config::log_level() != invalid_log_level
            ? runtime_config::log_level()
            : log_all_errors );
    unit_test_log.set_format( runtime_config::log_format());
    unit_test_log.set_stream( std::cout );
    BOOST_CHECK( ots().match_pattern() );
}

//____________________________________________________________________________//

TEST_CASE( test_CHECK_SMALL )
{
    BOOST_CHECK_SMALL( 1e-6, 1e-5 );
    BOOST_CHECK_SMALL( 1e-6, 1e-7 );
    BOOST_CHECK_SMALL( -1e-6, 1e-5 );
}

//____________________________________________________________________________//

TEST_CASE( test_close_at_tolerance )
{
    double fp1     = 1.00000001;
    double fp2     = 1.00000002;
    double epsilon = 1e-6;

    close_at_tolerance<double> pred( epsilon, FPC_WEAK );
    BOOST_CHECK_PREDICATE( pred, (fp1)(fp2) );

    BOOST_CHECK_CLOSE( fp1, fp2, epsilon );

    fp1     = 1.23456e-10;
    fp2     = 1.23457e-10;
    epsilon = 8.1e-4;

    BOOST_CHECK_PREDICATE( close_at_tolerance<double>( epsilon, FPC_WEAK ), (fp1)(fp2) );
    BOOST_CHECK_PREDICATE( close_at_tolerance<double>( epsilon ), (fp1)(fp2) );
}

//____________________________________________________________________________//

// ***************************************************************************
//  Revision History :
//
//  $Log$
//  Revision 1.21  2005/05/11 05:07:57  rogeeff
//  licence update
//
//  Revision 1.20  2005/04/17 15:49:17  rogeeff
//  *** empty log message ***
//
//  Revision 1.19  2005/03/22 07:14:44  rogeeff
//  no message
//
//  Revision 1.18  2005/02/21 10:29:04  rogeeff
//  no message
//
//  Revision 1.17  2005/02/20 08:28:34  rogeeff
//  This a major update for Boost.Test framework. See release docs for complete list of fixes/updates
//
// ***************************************************************************

// EOF
<commit_msg>remove format testing<commit_after>//  (C) Copyright Gennadiy Rozental 2001-2005.
//  Distributed under the Boost Software License, Version 1.0.
//  (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)

//  See http://www.boost.org/libs/test for the library home page.
//
//  File        : $RCSfile$
//
//  Version     : $Revision$
//
//  Description : tests floating point comparison algorithms
// ***************************************************************************

// Boost.Test
#define BOOST_AUTO_TEST_MAIN
#include <boost/test/auto_unit_test.hpp>
#include <boost/test/test_case_template.hpp>
#include <boost/test/floating_point_comparison.hpp>

// Boost
#include <boost/mpl/list.hpp>
#include <boost/bind.hpp>

// STL
#include <functional>

using namespace boost;
using namespace boost::unit_test;
using namespace boost::test_tools;

bool not_func( bool arg ) { return !arg; }

//____________________________________________________________________________//

typedef boost::mpl::list<float,double,long double> test_types;

BOOST_AUTO_TEST_CASE_TEMPLATE( test_BOOST_CHECK_CLOSE, FPT, test_types )
{
#define CHECK_CLOSE( first, second, e )     \
    fp1     = static_cast<FPT>(first);      \
    fp2     = static_cast<FPT>(second);     \
    epsilon = static_cast<FPT>(e);          \
                                            \
    BOOST_CHECK_CLOSE( fp1, fp2, epsilon ); \
/**/

#define CHECK_NOT_CLOSE( first, second, e ) \
    fp1     = static_cast<FPT>(first);      \
    fp2     = static_cast<FPT>(second);     \
    epsilon = static_cast<FPT>(e);          \
                                            \
    BOOST_CHECK_PREDICATE( bind(not_func, bind(check_is_close, _1, _2, _3)), (fp1)(fp2)(epsilon) ); \
/**/

    FPT fp1, fp2, epsilon;

    CHECK_CLOSE( 1, 1, 0 );

    CHECK_NOT_CLOSE( 0, 1e-20, 1e-5 );
    CHECK_NOT_CLOSE( 0, 1e-30, 1e-5 );
    CHECK_NOT_CLOSE( 0, -1e-10, 0.1 );
    CHECK_NOT_CLOSE( 0.123456, 0.123457, 1e-4 );

    CHECK_CLOSE( 0.123456, 0.123457, 1e-3 );

    CHECK_NOT_CLOSE( 0.123456, -0.123457, 1e-3 );

    CHECK_CLOSE( 1.23456e28, 1.23457e28, 1e-3 );

    CHECK_CLOSE( 1.23456e-10, 1.23457e-10, 1e-3 );
    CHECK_NOT_CLOSE( 1.111e-10, 1.112e-10, 0.08999 );
    CHECK_CLOSE( 1.112e-10, 1.111e-10, 0.1 );

    CHECK_CLOSE( 1, 1.0001, 1.1e-2 );
    CHECK_CLOSE( 1.0002, 1.0001, 1.1e-2 );

    CHECK_NOT_CLOSE( 1, 1.0002, 1.1e-2 );
}

//____________________________________________________________________________//

BOOST_AUTO_TEST_CASE( test_CHECK_SMALL )
{
    BOOST_CHECK_SMALL( 1e-6, 1e-5 );
    BOOST_CHECK_SMALL( -1e-6, 1e-5 );

    BOOST_CHECK_PREDICATE( bind(not_func, bind(check_is_small, _1, _2 )), (1e-6)(1e-7) );
}

//____________________________________________________________________________//

BOOST_AUTO_TEST_CASE( test_close_at_tolerance )
{
    double fp1     = 1.00000001;
    double fp2     = 1.00000002;
    double epsilon = 1e-6;

    close_at_tolerance<double> pred( epsilon, FPC_WEAK );
    BOOST_CHECK_PREDICATE( pred, (fp1)(fp2) );

    BOOST_CHECK_PREDICATE( bind(not_func, bind(check_is_close, _1, _2, _3)), (fp1)(fp2)(epsilon) );

    fp1     = 1.23456e-10;
    fp2     = 1.23457e-10;
    epsilon = 8.1e-4;

    BOOST_CHECK_PREDICATE( close_at_tolerance<double>( epsilon, FPC_WEAK ), (fp1)(fp2) );
    BOOST_CHECK_PREDICATE( bind(not_func, bind(close_at_tolerance<double>( epsilon ), _1, _2)), (fp1)(fp2) );
}

//____________________________________________________________________________//

// ***************************************************************************
//  Revision History :
//
//  $Log$
//  Revision 1.22  2005/05/29 08:54:04  rogeeff
//  remove format testing
//
//  Revision 1.17  2005/02/20 08:28:34  rogeeff
//  This a major update for Boost.Test framework. See release docs for complete list of fixes/updates
//
// ***************************************************************************

// EOF
<|endoftext|>