<commit_before>#include "stdafx.h"
#include "FileManager.h"
#include "Misc.h"
#include "Common.h"

inline u64 swapEndianness64(u64 value)
{
	return ((value & 0xFF) << 56) | ((value & 0xFF00) << 40) | ((value & 0xFF0000) << 24) | ((value & 0xFF000000) << 8) |
	((value & 0xFF00000000) >> 8) | ((value & 0xFF0000000000) >> 24) |
	((value & 0xFF000000000000) >> 40) | ((value & 0xFF00000000000000) >> 56);
}

inline u32 swapEndianness32(u32 value)
{
	return ((value & 0xFF) << 24) | ((value & 0xFF00) << 8) | ((value & 0xFF0000) >> 8) | ((value & 0xFF000000) >> 24);
}

inline u16 swapEndianness16(u16 value)
{
	return ((value & 0xFF) << 8) | ((value & 0xFF00) >> 8);
}

GenericAssemblerFile::GenericAssemblerFile(const std::wstring& fileName, u32 headerSize, bool overwrite)
{
	this->fileName = fileName;
	this->headerSize = headerSize;
	this->originalHeaderSize = headerSize;
	this->virtualAddress = headerSize;
	mode = overwrite == true ? Create : Open;
}

GenericAssemblerFile::GenericAssemblerFile(const std::wstring& fileName, const std::wstring& originalFileName, u32 headerSize)
{
	this->fileName = fileName;
	this->originalName = originalFileName;
	this->headerSize = headerSize;
	this->virtualAddress = headerSize;
	originalHeaderSize = headerSize;
	mode = Copy;
}

bool GenericAssemblerFile::open(bool onlyCheck)
{
	headerSize = originalHeaderSize;
	virtualAddress = headerSize;

	if (onlyCheck == false)
	{
		// actually open the file
		bool success;
		switch (mode)
		{
		case Open:
			success = handle.open(fileName,BinaryFile::ReadWrite);
			if (success == false)
			{
				Logger::printError(Logger::FatalError,L"Could not open file %s",fileName);
				return false;
			}
			return true;

		case Create:
			success = handle.open(fileName,BinaryFile::Write);
			if (success == false)
			{
				Logger::printError(Logger::FatalError,L"Could not create file %s",fileName);
				return false;
			}
			return true;

		case Copy:
			success = copyFile(originalName,fileName);
			if (success == false)
			{
				Logger::printError(Logger::FatalError,L"Could not copy file %s",originalName);
				return false;
			}

			success = handle.open(fileName,BinaryFile::ReadWrite);
			if (success == false)
			{
				Logger::printError(Logger::FatalError,L"Could not open file %s",fileName);
				return false;
			}
			return true;

		default:
			return false;
		}
	}

	// else only check if it can be done, don't actually do it permanently
	bool success, exists;
	BinaryFile temp;
	switch (mode)
	{
	case Open:
		success = temp.open(fileName,BinaryFile::ReadWrite);
		if (success == false)
		{
			Logger::queueError(Logger::FatalError,L"Could not open file %s",fileName);
			return false;
		}
		temp.close();
		return true;

	case Create:
		// if it exists, check if you can open it with read/write access
		// otherwise open it with write access and remove it afterwards
		exists = fileExists(fileName);
		success = temp.open(fileName,exists ? BinaryFile::ReadWrite : BinaryFile::Write);
		if (success == false)
		{
			Logger::queueError(Logger::FatalError,L"Could not create file %s",fileName);
			return false;
		}
		temp.close();

		if (exists == false)
			deleteFile(fileName);

		return true;

	case Copy:
		// check original file
		success = temp.open(originalName,BinaryFile::ReadWrite);
		if (success == false)
		{
			Logger::queueError(Logger::FatalError,L"Could not open file %s",originalName);
			return false;
		}
		temp.close();

		// check new file, same as create
		exists = fileExists(fileName);
		success = temp.open(fileName,exists ? BinaryFile::ReadWrite : BinaryFile::Write);
		if (success == false)
		{
			Logger::queueError(Logger::FatalError,L"Could not open file %s",fileName);
			return false;
		}
		temp.close();

		if (exists == false)
			deleteFile(fileName);

		return true;

	default:
		return false;
	};

	return false;
}

bool GenericAssemblerFile::write(void* data, size_t length)
{
	if (isOpen() == false)
		return false;

	size_t len = handle.write(data,length);
	virtualAddress += len;
	return len == length;
}

bool GenericAssemblerFile::seekVirtual(u64 virtualAddress)
{
	if (virtualAddress < headerSize)
	{
		Logger::queueError(Logger::Error,L"Seeking to invalid address");
		return false;
	}

	this->virtualAddress = virtualAddress;
	u64 physicalAddress = virtualAddress-headerSize;

	if (isOpen())
		handle.setPos((long)physicalAddress);

	return true;
}

bool GenericAssemblerFile::seekPhysical(u64 physicalAddress)
{
	if ((signed)physicalAddress < 0)
	{
		Logger::queueError(Logger::Error,L"Seeking to invalid address");
		return false;
	}

	virtualAddress = physicalAddress+headerSize;

	if (isOpen())
		handle.setPos((long)physicalAddress);

	return true;
}

FileManager::FileManager()
{
	// detect own endianness
	volatile union
	{
		u32 i;
		u8 c[4];
	} u;
	u.c[3] = 0xAA;
	u.c[2] = 0xBB;
	u.c[1] = 0xCC;
	u.c[0] = 0xDD;

	if (u.i == 0xDDCCBBAA)
		ownEndianness = Endianness::Big;
	else if (u.i == 0xAABBCCDD)
		ownEndianness = Endianness::Little;
	else
		Logger::printError(Logger::Error,L"Running on unknown endianness");

	reset();
}

FileManager::~FileManager()
{

}

void FileManager::reset()
{
	activeFile = NULL;
	setEndianness(Endianness::Little);
}

bool FileManager::checkActiveFile()
{
	if (activeFile == NULL)
	{
		Logger::queueError(Logger::Error,L"No file opened");
		return false;
	}
	return true;
}

bool FileManager::openFile(AssemblerFile* file, bool onlyCheck)
{
	if (activeFile != NULL)
	{
		Logger::queueError(Logger::Warning,L"File not closed before opening a new one");
		activeFile->close();
	}

	activeFile = file;
	return activeFile->open(onlyCheck);
}

void FileManager::addFile(AssemblerFile* file)
{
	files.push_back(file);
	activeFile = file;
}

void FileManager::closeFile()
{
	if (activeFile == NULL)
	{
		Logger::queueError(Logger::Warning,L"No file opened");
		return;
	}

	activeFile->close();
	activeFile = NULL;
}

bool FileManager::write(void* data, size_t length)
{
	if (checkActiveFile() == false)
		return false;

	if (activeFile->isOpen() == false)
	{
		Logger::queueError(Logger::Error,L"No file opened");
		return false;
	}

	return activeFile->write(data,length);
}

bool FileManager::writeU8(u8 data)
{
	return write(&data,1);
}

bool FileManager::writeU16(u16 data)
{
	if (endianness != ownEndianness)
		data = swapEndianness16(data);

	return write(&data,2);
}

bool FileManager::writeU32(u32 data)
{
	if (endianness != ownEndianness)
		data = swapEndianness32(data);

	return write(&data,4);
}

bool FileManager::writeU64(u64 data)
{
	if (endianness != ownEndianness)
		data = swapEndianness64(data);

	return write(&data,8);
}

u64 FileManager::getVirtualAddress()
{
	if (activeFile == NULL)
		return -1;
	return activeFile->getVirtualAddress();
}

u64 FileManager::getPhysicalAddress()
{
	if (activeFile == NULL)
		return -1;
	return activeFile->getPhysicalAddress();
}

bool FileManager::seekVirtual(u64 virtualAddress)
{
	if (checkActiveFile() == false)
		return false;

	bool result = activeFile->seekVirtual(virtualAddress);
	if (result && Global.memoryMode)
	{
		int sec = Global.symbolTable.findSection(virtualAddress);
		if (sec != -1)
			Global.Section = sec;
	}

	return result;
}

bool FileManager::seekPhysical(u64 virtualAddress)
{
	if (checkActiveFile() == false)
		return false;
	return activeFile->seekPhysical(virtualAddress);
}

bool FileManager::advanceMemory(size_t bytes)
{
	if (checkActiveFile() == false)
		return false;

	u64 pos = activeFile->getVirtualAddress();
	return activeFile->seekVirtual(pos+bytes);
}
<commit_msg>Improve error message when target file could not be opened for writing by a copy command<commit_after>#include "stdafx.h"
#include "FileManager.h"
#include "Misc.h"
#include "Common.h"

inline u64 swapEndianness64(u64 value)
{
	return ((value & 0xFF) << 56) | ((value & 0xFF00) << 40) | ((value & 0xFF0000) << 24) | ((value & 0xFF000000) << 8) |
	((value & 0xFF00000000) >> 8) | ((value & 0xFF0000000000) >> 24) |
	((value & 0xFF000000000000) >> 40) | ((value & 0xFF00000000000000) >> 56);
}

inline u32 swapEndianness32(u32 value)
{
	return ((value & 0xFF) << 24) | ((value & 0xFF00) << 8) | ((value & 0xFF0000) >> 8) | ((value & 0xFF000000) >> 24);
}

inline u16 swapEndianness16(u16 value)
{
	return ((value & 0xFF) << 8) | ((value & 0xFF00) >> 8);
}

GenericAssemblerFile::GenericAssemblerFile(const std::wstring& fileName, u32 headerSize, bool overwrite)
{
	this->fileName = fileName;
	this->headerSize = headerSize;
	this->originalHeaderSize = headerSize;
	this->virtualAddress = headerSize;
	mode = overwrite == true ? Create : Open;
}

GenericAssemblerFile::GenericAssemblerFile(const std::wstring& fileName, const std::wstring& originalFileName, u32 headerSize)
{
	this->fileName = fileName;
	this->originalName = originalFileName;
	this->headerSize = headerSize;
	this->virtualAddress = headerSize;
	originalHeaderSize = headerSize;
	mode = Copy;
}

bool GenericAssemblerFile::open(bool onlyCheck)
{
	headerSize = originalHeaderSize;
	virtualAddress = headerSize;

	if (onlyCheck == false)
	{
		// actually open the file
		bool success;
		switch (mode)
		{
		case Open:
			success = handle.open(fileName,BinaryFile::ReadWrite);
			if (success == false)
			{
				Logger::printError(Logger::FatalError,L"Could not open file %s",fileName);
				return false;
			}
			return true;

		case Create:
			success = handle.open(fileName,BinaryFile::Write);
			if (success == false)
			{
				Logger::printError(Logger::FatalError,L"Could not create file %s",fileName);
				return false;
			}
			return true;

		case Copy:
			success = copyFile(originalName,fileName);
			if (success == false)
			{
				Logger::printError(Logger::FatalError,L"Could not copy file %s",originalName);
				return false;
			}

			success = handle.open(fileName,BinaryFile::ReadWrite);
			if (success == false)
			{
				Logger::printError(Logger::FatalError,L"Could not create file %s",fileName);
				return false;
			}
			return true;

		default:
			return false;
		}
	}

	// else only check if it can be done, don't actually do it permanently
	bool success, exists;
	BinaryFile temp;
	switch (mode)
	{
	case Open:
		success = temp.open(fileName,BinaryFile::ReadWrite);
		if (success == false)
		{
			Logger::queueError(Logger::FatalError,L"Could not open file %s",fileName);
			return false;
		}
		temp.close();
		return true;

	case Create:
		// if it exists, check if you can open it with read/write access
		// otherwise open it with write access and remove it afterwards
		exists = fileExists(fileName);
		success = temp.open(fileName,exists ? BinaryFile::ReadWrite : BinaryFile::Write);
		if (success == false)
		{
			Logger::queueError(Logger::FatalError,L"Could not create file %s",fileName);
			return false;
		}
		temp.close();

		if (exists == false)
			deleteFile(fileName);

		return true;

	case Copy:
		// check original file
		success = temp.open(originalName,BinaryFile::ReadWrite);
		if (success == false)
		{
			Logger::queueError(Logger::FatalError,L"Could not open file %s",originalName);
			return false;
		}
		temp.close();

		// check new file, same as create
		exists = fileExists(fileName);
		success = temp.open(fileName,exists ? BinaryFile::ReadWrite : BinaryFile::Write);
		if (success == false)
		{
			Logger::queueError(Logger::FatalError,L"Could not create file %s",fileName);
			return false;
		}
		temp.close();

		if (exists == false)
			deleteFile(fileName);

		return true;

	default:
		return false;
	};

	return false;
}

bool GenericAssemblerFile::write(void* data, size_t length)
{
	if (isOpen() == false)
		return false;

	size_t len = handle.write(data,length);
	virtualAddress += len;
	return len == length;
}

bool GenericAssemblerFile::seekVirtual(u64 virtualAddress)
{
	if (virtualAddress < headerSize)
	{
		Logger::queueError(Logger::Error,L"Seeking to invalid address");
		return false;
	}

	this->virtualAddress = virtualAddress;
	u64 physicalAddress = virtualAddress-headerSize;

	if (isOpen())
		handle.setPos((long)physicalAddress);

	return true;
}

bool GenericAssemblerFile::seekPhysical(u64 physicalAddress)
{
	if ((signed)physicalAddress < 0)
	{
		Logger::queueError(Logger::Error,L"Seeking to invalid address");
		return false;
	}

	virtualAddress = physicalAddress+headerSize;

	if (isOpen())
		handle.setPos((long)physicalAddress);

	return true;
}

FileManager::FileManager()
{
	// detect own endianness
	volatile union
	{
		u32 i;
		u8 c[4];
	} u;
	u.c[3] = 0xAA;
	u.c[2] = 0xBB;
	u.c[1] = 0xCC;
	u.c[0] = 0xDD;

	if (u.i == 0xDDCCBBAA)
		ownEndianness = Endianness::Big;
	else if (u.i == 0xAABBCCDD)
		ownEndianness = Endianness::Little;
	else
		Logger::printError(Logger::Error,L"Running on unknown endianness");

	reset();
}

FileManager::~FileManager()
{

}

void FileManager::reset()
{
	activeFile = NULL;
	setEndianness(Endianness::Little);
}

bool FileManager::checkActiveFile()
{
	if (activeFile == NULL)
	{
		Logger::queueError(Logger::Error,L"No file opened");
		return false;
	}
	return true;
}

bool FileManager::openFile(AssemblerFile* file, bool onlyCheck)
{
	if (activeFile != NULL)
	{
		Logger::queueError(Logger::Warning,L"File not closed before opening a new one");
		activeFile->close();
	}

	activeFile = file;
	return activeFile->open(onlyCheck);
}

void FileManager::addFile(AssemblerFile* file)
{
	files.push_back(file);
	activeFile = file;
}

void FileManager::closeFile()
{
	if (activeFile == NULL)
	{
		Logger::queueError(Logger::Warning,L"No file opened");
		return;
	}

	activeFile->close();
	activeFile = NULL;
}

bool FileManager::write(void* data, size_t length)
{
	if (checkActiveFile() == false)
		return false;

	if (activeFile->isOpen() == false)
	{
		Logger::queueError(Logger::Error,L"No file opened");
		return false;
	}

	return activeFile->write(data,length);
}

bool FileManager::writeU8(u8 data)
{
	return write(&data,1);
}

bool FileManager::writeU16(u16 data)
{
	if (endianness != ownEndianness)
		data = swapEndianness16(data);

	return write(&data,2);
}

bool FileManager::writeU32(u32 data)
{
	if (endianness != ownEndianness)
		data = swapEndianness32(data);

	return write(&data,4);
}

bool FileManager::writeU64(u64 data)
{
	if (endianness != ownEndianness)
		data = swapEndianness64(data);

	return write(&data,8);
}

u64 FileManager::getVirtualAddress()
{
	if (activeFile == NULL)
		return -1;
	return activeFile->getVirtualAddress();
}

u64 FileManager::getPhysicalAddress()
{
	if (activeFile == NULL)
		return -1;
	return activeFile->getPhysicalAddress();
}

bool FileManager::seekVirtual(u64 virtualAddress)
{
	if (checkActiveFile() == false)
		return false;

	bool result = activeFile->seekVirtual(virtualAddress);
	if (result && Global.memoryMode)
	{
		int sec = Global.symbolTable.findSection(virtualAddress);
		if (sec != -1)
			Global.Section = sec;
	}

	return result;
}

bool FileManager::seekPhysical(u64 virtualAddress)
{
	if (checkActiveFile() == false)
		return false;
	return activeFile->seekPhysical(virtualAddress);
}

bool FileManager::advanceMemory(size_t bytes)
{
	if (checkActiveFile() == false)
		return false;

	u64 pos = activeFile->getVirtualAddress();
	return activeFile->seekVirtual(pos+bytes);
}
<|endoftext|>


<commit_before>#include "domain/definition.h"

#include <functional>
#include <memory>

#include <gtest/gtest.h>

#include <deal.II/grid/tria.h>
#include <deal.II/fe/fe_q.h>
#include <deal.II/grid/grid_generator.h>

#include "test_helpers/gmock_wrapper.h"
#include "domain/tests/mesh_mock.h"
#include "domain/tests/finite_element_mock.h"

namespace {

using ::testing::_;
using ::testing::NiceMock;

template <typename DimensionWrapper>
class DefinitionTest : public ::testing::Test {
 protected:
  static constexpr int dim = DimensionWrapper::value;
  std::unique_ptr<bart::domain::MeshMock<dim>> mesh_ptr;
  std::unique_ptr<NiceMock<bart::domain::MeshMock<dim>>> nice_mesh_ptr;
  std::shared_ptr<bart::domain::FiniteElementMock<dim>> fe_ptr;

  void SetUp() override;
};

TYPED_TEST_CASE(DefinitionTest, bart::testing::AllDimensions);

template <typename DimensionWrapper>
void DefinitionTest<DimensionWrapper>::SetUp() {
  mesh_ptr = std::make_unique<bart::domain::MeshMock<dim>>();
  nice_mesh_ptr = std::make_unique<NiceMock<bart::domain::MeshMock<dim>>>();
  fe_ptr = std::make_shared<bart::domain::FiniteElementMock<dim>>();
}

TYPED_TEST(DefinitionTest, Constructor) {
  bart::domain::Definition<this->dim> test_domain(std::move(this->mesh_ptr),
                                                  this->fe_ptr);
  // Verify ownership has been taken by constructor
  EXPECT_EQ(this->mesh_ptr, nullptr);
  EXPECT_EQ(this->fe_ptr.use_count(), 2);
}

TYPED_TEST(DefinitionTest, SetUpMesh) {
  EXPECT_CALL(*this->mesh_ptr, FillTriangulation(_));
  EXPECT_CALL(*this->mesh_ptr, FillMaterialID(_));
  EXPECT_CALL(*this->mesh_ptr, has_material_mapping()).
      WillOnce(::testing::Return(true));
  EXPECT_CALL(*this->mesh_ptr, FillBoundaryID(_));

  bart::domain::Definition<this->dim> test_domain(std::move(this->mesh_ptr),
                                          this->fe_ptr);

  EXPECT_NO_THROW(test_domain.SetUpMesh(););
}

TYPED_TEST(DefinitionTest, SetUpMeshMaterialMappingError) {
  EXPECT_CALL(*this->nice_mesh_ptr, has_material_mapping()).
      WillOnce(::testing::Return(false));

  bart::domain::Definition<this->dim> test_domain(std::move(this->nice_mesh_ptr),
                                            this->fe_ptr);
  EXPECT_ANY_THROW(test_domain.SetUpMesh(););
}

template <typename DimensionWrapper>
class DOFTest : public DefinitionTest<DimensionWrapper> {
 protected:
  static constexpr int dim = DimensionWrapper::value;
  DOFTest() : fe(1) {};
  dealii::Triangulation<dim> triangulation;
  dealii::FE_Q<dim> fe;
  int n_cells_;

  void SetUp() override;
  static void SetTriangulation(dealii::Triangulation<dim> &to_fill) {
    dealii::GridGenerator::hyper_cube(to_fill, -1, 1);
    to_fill.refine_global(2);
  }
};

TYPED_TEST_CASE(DOFTest, bart::testing::AllDimensions);

template <typename DimensionWrapper>
void DOFTest<DimensionWrapper>::SetUp() {
  DefinitionTest<DimensionWrapper>::SetUp();
}

TYPED_TEST(DOFTest, SetUpDOFTest) {
  EXPECT_CALL(*this->nice_mesh_ptr, has_material_mapping()).
      WillOnce(::testing::Return(true));
  EXPECT_CALL(*this->nice_mesh_ptr, FillTriangulation(_))
      .WillOnce(::testing::Invoke(this->SetTriangulation));
  EXPECT_CALL(*this->fe_ptr, finite_element())
      .WillOnce(::testing::Return(&this->fe));
  EXPECT_CALL(*this->fe_ptr, dofs_per_cell())
      .Times(2)
      .WillRepeatedly(::testing::Return(4));

  bart::domain::Definition<this->dim> test_domain(std::move(this->nice_mesh_ptr),
                                                  this->fe_ptr);
  test_domain.SetUpMesh();
  test_domain.SetUpDOF();

  EXPECT_EQ(test_domain.total_degrees_of_freedom(), 25);
  EXPECT_EQ(test_domain.Cells().size(), 16);

  auto matrix = test_domain.GetCellMatrix();
  EXPECT_EQ(matrix.n_rows(), 4);
  EXPECT_EQ(matrix.n_cols(), 4);

  auto vector = test_domain.GetCellVector();
  EXPECT_EQ(vector.size(), 4);

}

} // namespace<commit_msg>added tests in all 3 dimensions for domain::Definition<commit_after>#include "domain/definition.h"

#include <cmath>
#include <functional>
#include <memory>

#include <gtest/gtest.h>

#include <deal.II/grid/tria.h>
#include <deal.II/fe/fe_q.h>
#include <deal.II/grid/grid_generator.h>

#include "data/matrix_parameters.h"
#include "test_helpers/gmock_wrapper.h"
#include "domain/tests/mesh_mock.h"
#include "domain/tests/finite_element_mock.h"

namespace {

using ::testing::_;
using ::testing::NiceMock;

template <typename DimensionWrapper>
class DefinitionTest : public ::testing::Test {
 protected:
  static constexpr int dim = DimensionWrapper::value;
  std::unique_ptr<bart::domain::MeshMock<dim>> mesh_ptr;
  std::unique_ptr<NiceMock<bart::domain::MeshMock<dim>>> nice_mesh_ptr;
  std::shared_ptr<bart::domain::FiniteElementMock<dim>> fe_ptr;

  void SetUp() override;
};

TYPED_TEST_CASE(DefinitionTest, bart::testing::AllDimensions);

template <typename DimensionWrapper>
void DefinitionTest<DimensionWrapper>::SetUp() {
  mesh_ptr = std::make_unique<bart::domain::MeshMock<dim>>();
  nice_mesh_ptr = std::make_unique<NiceMock<bart::domain::MeshMock<dim>>>();
  fe_ptr = std::make_shared<bart::domain::FiniteElementMock<dim>>();
}

TYPED_TEST(DefinitionTest, Constructor) {
  bart::domain::Definition<this->dim> test_domain(std::move(this->mesh_ptr),
                                                  this->fe_ptr);
  // Verify ownership has been taken by constructor
  EXPECT_EQ(this->mesh_ptr, nullptr);
  EXPECT_EQ(this->fe_ptr.use_count(), 2);
}

TYPED_TEST(DefinitionTest, SetUpMesh) {
  EXPECT_CALL(*this->mesh_ptr, FillTriangulation(_));
  EXPECT_CALL(*this->mesh_ptr, FillMaterialID(_));
  EXPECT_CALL(*this->mesh_ptr, has_material_mapping()).
      WillOnce(::testing::Return(true));
  EXPECT_CALL(*this->mesh_ptr, FillBoundaryID(_));

  bart::domain::Definition<this->dim> test_domain(std::move(this->mesh_ptr),
                                          this->fe_ptr);

  EXPECT_NO_THROW(test_domain.SetUpMesh(););
}

TYPED_TEST(DefinitionTest, SetUpMeshMaterialMappingError) {
  EXPECT_CALL(*this->nice_mesh_ptr, has_material_mapping()).
      WillOnce(::testing::Return(false));

  bart::domain::Definition<this->dim> test_domain(std::move(this->nice_mesh_ptr),
                                            this->fe_ptr);
  EXPECT_ANY_THROW(test_domain.SetUpMesh(););
}

template <typename DimensionWrapper>
class DOFTest : public DefinitionTest<DimensionWrapper> {
 protected:
  static constexpr int dim = DimensionWrapper::value;
  DOFTest() : fe(1) {};
  dealii::Triangulation<dim> triangulation;
  dealii::FE_Q<dim> fe;
  int n_cells_;

  void SetUp() override;
  static void SetTriangulation(dealii::Triangulation<dim> &to_fill) {
    dealii::GridGenerator::hyper_cube(to_fill, -1, 1);
    if (dim == 1) {
      to_fill.refine_global(4);
    } else {
      to_fill.refine_global(2);
    }
  }
};

TYPED_TEST_CASE(DOFTest, bart::testing::AllDimensions);

template <typename DimensionWrapper>
void DOFTest<DimensionWrapper>::SetUp() {
  DefinitionTest<DimensionWrapper>::SetUp();
}

TYPED_TEST(DOFTest, SetUpDOFTestMPI) {
  EXPECT_CALL(*this->nice_mesh_ptr, has_material_mapping()).
      WillOnce(::testing::Return(true));
  EXPECT_CALL(*this->nice_mesh_ptr, FillTriangulation(_))
      .WillOnce(::testing::Invoke(this->SetTriangulation));
  EXPECT_CALL(*this->fe_ptr, finite_element())
      .WillOnce(::testing::Return(&this->fe));

  bart::domain::Definition<this->dim> test_domain(std::move(this->nice_mesh_ptr),
                                                  this->fe_ptr);
  test_domain.SetUpMesh();
  test_domain.SetUpDOF();

  EXPECT_EQ(test_domain.total_degrees_of_freedom(),
            test_domain.dof_handler().n_dofs());

  int total_cells = 0;
  for (auto cell = test_domain.dof_handler().begin_active();
       cell != test_domain.dof_handler().end(); ++cell) {
    if (cell->is_locally_owned())
      ++total_cells;
  }

  EXPECT_EQ(test_domain.Cells().size(), total_cells);

  EXPECT_CALL(*this->fe_ptr, dofs_per_cell())
      .Times(2)
      .WillRepeatedly(::testing::Return(4));

  auto matrix = test_domain.GetCellMatrix();
  EXPECT_EQ(matrix.n_rows(), 4);
  EXPECT_EQ(matrix.n_cols(), 4);

  auto vector = test_domain.GetCellVector();
  EXPECT_EQ(vector.size(), 4);
}

TYPED_TEST(DOFTest, MatrixParametersMPI) {
  EXPECT_CALL(*this->nice_mesh_ptr, has_material_mapping()).
      WillOnce(::testing::Return(true));
  EXPECT_CALL(*this->nice_mesh_ptr, FillTriangulation(_))
      .WillOnce(::testing::Invoke(this->SetTriangulation));
  EXPECT_CALL(*this->fe_ptr, finite_element())
      .WillOnce(::testing::Return(&this->fe));

  bart::domain::Definition<this->dim> test_domain(std::move(this->nice_mesh_ptr),
                                                  this->fe_ptr);
  test_domain.SetUpMesh();
  test_domain.SetUpDOF();

  bart::data::MatrixParameters test_parameters;
  test_domain.FillMatrixParameters(test_parameters,
      bart::problem::DiscretizationType::kContinuousFEM);

  EXPECT_EQ(test_parameters.rows, test_domain.locally_owned_dofs());
  EXPECT_EQ(test_parameters.columns, test_domain.locally_owned_dofs());
}

} // namespace<|endoftext|>


<commit_before>#pragma once
#include "coordinate_transform.hpp"
#include "grad_shape.hpp"
#include "integrate.hpp"
#include "shape.hpp"
#include <Eigen/Core>
#include <Eigen/Dense>

//----------------compMatrixBegin----------------
//! Evaluate the stiffness matrix on the triangle spanned by
//! the points (a, b, c).
//!
//! Here, the stiffness matrix A is a 6x6 matrix
//!
//! $$A_{ij} = \int_{K} ( \nabla \lambda_i^K(x, y) \cdot  \nabla \lambda_j^K(x, y)\; dV$$
//!
//! where $K$ is the triangle spanned by (a, b, c).
//!
//! @param[out] stiffnessMatrix should be a 6x6 matrix
//!                        At the end, will contain the integrals above.
//!
//! @param[in] a the first corner of the triangle
//! @param[in] b the second corner of the triangle
//! @param[in] c the third corner of the triangle
template <class MatrixType, class Point>
void computeStiffnessMatrix(MatrixType & stiffnessMatrix,
                            const Point &a,
                            const Point &b,
                            const Point &c) {
	Eigen::Matrix2d coordinateTransform = makeCoordinateTransform(b - a, c - a);
	double          volumeFactor        = std::abs(coordinateTransform.determinant());
	Eigen::Matrix2d elementMap          = coordinateTransform.inverse().transpose();
	// (write your solution here)
	stiffnessMatrix.resize(6, 6);

	for (int i = 0; i < 6; ++i) {
		for (int j = 0; j < 6; ++j) {
			auto f = [&](double x, double y) -> double {
				Eigen::Vector2d gradLambdaI = elementMap * gradientShapeFun(i, x, y);
				Eigen::Vector2d gradLambdaJ = elementMap * gradientShapeFun(j, x, y);

				return gradLambdaI.dot(gradLambdaJ);
			};

			stiffnessMatrix(i, j) = volumeFactor * integrate(f);
		}
	}
}
//----------------compMatrixEnd----------------
<commit_msg>Fixed typo<commit_after>#pragma once
#include "coordinate_transform.hpp"
#include "grad_shape.hpp"
#include "integrate.hpp"
#include "shape.hpp"
#include <Eigen/Core>
#include <Eigen/Dense>

//----------------compMatrixBegin----------------
//! Evaluate the stiffness matrix on the triangle spanned by
//! the points (a, b, c).
//!
//! Here, the stiffness matrix A is a 6x6 matrix
//!
//! $$A_{ij} = \int_{K} ( \nabla \lambda_i^K(x, y) \cdot  \nabla \lambda_j^K(x, y)\; dV$$
//!
//! where $K$ is the triangle spanned by (a, b, c).
//!
//! @param[out] stiffnessMatrix should be a 6x6 matrix
//!                        At the end, will contain the integrals above.
//!
//! @param[in] a the first corner of the triangle
//! @param[in] b the second corner of the triangle
//! @param[in] c the third corner of the triangle
template <class MatrixType, class Point>
void computeStiffnessMatrix(MatrixType & stiffnessMatrix,
                            const Point &a,
                            const Point &b,
                            const Point &c) {
	Eigen::Matrix2d coordinateTransform = makeCoordinateTransform(b - a, c - a);
	double          volumeFactor        = std::abs(coordinateTransform.determinant());
	Eigen::Matrix2d elementMap          = coordinateTransform.inverse().transpose();
	// (write your solution here)
	stiffnessMatrix.resize(6, 6);

	for (int i = 0; i < 6; ++i) {
		for (int j = 0; j < 6; ++j) {
			auto f = [&](double x, double y) -> double {
				Eigen::Vector2d gradLambdaI = elementMap * gradientShapefun(i, x, y);
				Eigen::Vector2d gradLambdaJ = elementMap * gradientShapefun(j, x, y);

				return gradLambdaI.dot(gradLambdaJ);
			};

			stiffnessMatrix(i, j) = volumeFactor * integrate(f);
		}
	}
}
//----------------compMatrixEnd----------------
<|endoftext|>


<commit_before>/****************************************************************************
 *
 *   Copyright (c) 2015, 2016 Airmind Development Team. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 * 3. Neither the name Airmind nor the names of its contributors may be
 *    used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 ****************************************************************************/

/**
* @file drv_led_pwm.cpp
*
*
*/

#include <px4_config.h>
#include <systemlib/px4_macros.h>
#include <nuttx/arch.h>
#include <nuttx/irq.h>

#include <sys/types.h>
#include <stdbool.h>

#include <assert.h>
#include <debug.h>
#include <time.h>
#include <queue.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>

#include <arch/board/board.h>
#include <drivers/drv_pwm_output.h>

#include "drv_io_timer.h"

#include <kinetis.h>
#include "chip/kinetis_sim.h"
#include "chip/kinetis_ftm.h"

#if defined(BOARD_HAS_LED_PWM)

#define FTM_SRC_CLOCK_FREQ 16000000
#define LED_PWM_FREQ        1000000

#if (BOARD_LED_PWM_RATE)
#  define LED_PWM_RATE BOARD_LED_PWM_RATE
#else
#  define LED_PWM_RATE 50
#endif

#define _REG(_addr)	(*(volatile uint32_t *)(_addr))
#define _REG32(_base, _reg)	(*(volatile uint32_t *)(_base + _reg))
#define REG(_tmr, _reg)		_REG32(led_pwm_timers[_tmr].base, _reg)

/* Timer register accessors */

#define rSC(_tmr)         REG(_tmr,KINETIS_FTM_SC_OFFSET)
#define rCNT(_tmr)        REG(_tmr,KINETIS_FTM_CNT_OFFSET)
#define rMOD(_tmr)        REG(_tmr,KINETIS_FTM_MOD_OFFSET)
#define rC0SC(_tmr)       REG(_tmr,KINETIS_FTM_C0SC_OFFSET)
#define rC0V(_tmr)        REG(_tmr,KINETIS_FTM_C0V_OFFSET)
#define rC1SC(_tmr)       REG(_tmr,KINETIS_FTM_C1SC_OFFSET)
#define rC1V(_tmr)        REG(_tmr,KINETIS_FTM_C1V_OFFSET)
#define rC2SC(_tmr)       REG(_tmr,KINETIS_FTM_C2SC_OFFSET)
#define rC2V(_tmr)        REG(_tmr,KINETIS_FTM_C2V_OFFSET)
#define rC3SC(_tmr)       REG(_tmr,KINETIS_FTM_C3SC_OFFSET)
#define rC3V(_tmr)        REG(_tmr,KINETIS_FTM_C3V_OFFSET)
#define rC4SC(_tmr)       REG(_tmr,KINETIS_FTM_C4SC_OFFSET)
#define rC4V(_tmr)        REG(_tmr,KINETIS_FTM_C4V_OFFSET)
#define rC5SC(_tmr)       REG(_tmr,KINETIS_FTM_C5SC_OFFSET)
#define rC5V(_tmr)        REG(_tmr,KINETIS_FTM_C5V_OFFSET)
#define rC6SC(_tmr)       REG(_tmr,KINETIS_FTM_C6SC_OFFSET)
#define rC6V(_tmr)        REG(_tmr,KINETIS_FTM_C6V_OFFSET)
#define rC7SC(_tmr)       REG(_tmr,KINETIS_FTM_C7SC_OFFSET)
#define rC7V(_tmr)        REG(_tmr,KINETIS_FTM_C7V_OFFSET)

#define rCNTIN(_tmr)      REG(_tmr,KINETIS_FTM_CNTIN_OFFSET)
#define rSTATUS(_tmr)     REG(_tmr,KINETIS_FTM_STATUS_OFFSET)
#define rMODE(_tmr)       REG(_tmr,KINETIS_FTM_MODE_OFFSET)
#define rSYNC(_tmr)       REG(_tmr,KINETIS_FTM_SYNC_OFFSET)
#define rOUTINIT(_tmr)    REG(_tmr,KINETIS_FTM_OUTINIT_OFFSET)
#define rOUTMASK(_tmr)    REG(_tmr,KINETIS_FTM_OUTMASK_OFFSET)
#define rCOMBINE(_tmr)    REG(_tmr,KINETIS_FTM_COMBINE_OFFSET)
#define rDEADTIME(_tmr)   REG(_tmr,KINETIS_FTM_DEADTIME_OFFSET)
#define rEXTTRIG(_tmr)    REG(_tmr,KINETIS_FTM_EXTTRIG_OFFSET)
#define rPOL(_tmr)        REG(_tmr,KINETIS_FTM_POL_OFFSET)
#define rFMS(_tmr)        REG(_tmr,KINETIS_FTM_FMS_OFFSET)
#define rFILTER(_tmr)     REG(_tmr,KINETIS_FTM_FILTER_OFFSET)
#define rFLTCTRL(_tmr)    REG(_tmr,KINETIS_FTM_FLTCTRL_OFFSET)
#define rQDCTRL(_tmr)     REG(_tmr,KINETIS_FTM_QDCTRL_OFFSET)
#define rCONF(_tmr)       REG(_tmr,KINETIS_FTM_CONF_OFFSET)
#define rFLTPOL(_tmr)     REG(_tmr,KINETIS_FTM_FLTPOL_OFFSET)
#define rSYNCONF(_tmr)    REG(_tmr,KINETIS_FTM_SYNCONF_OFFSET)
#define rINVCTRL(_tmr)    REG(_tmr,KINETIS_FTM_INVCTRL_OFFSET)
#define rSWOCTRL(_tmr)    REG(_tmr,KINETIS_FTM_SWOCTRL_OFFSET)
#define rPWMLOAD(_tmr)    REG(_tmr,KINETIS_FTM_PWMLOAD_OFFSET)

#define CnSC_RESET          (FTM_CSC_CHF|FTM_CSC_CHIE|FTM_CSC_MSB|FTM_CSC_MSA|FTM_CSC_ELSB|FTM_CSC_ELSA|FTM_CSC_DMA)
#define CnSC_CAPTURE_INIT   (FTM_CSC_CHIE|FTM_CSC_ELSB|FTM_CSC_ELSA) // Both

#if defined(BOARD_LED_PWM_DRIVE_ACTIVE_LOW)
#define CnSC_PWMOUT_INIT    (FTM_CSC_MSB|FTM_CSC_ELSA)
#else
#define CnSC_PWMOUT_INIT    (FTM_CSC_MSB|FTM_CSC_ELSB)
#endif

#define FTM_SYNC (FTM_SYNC_SWSYNC)

static void             led_pwm_timer_init(unsigned timer);
static void             led_pwm_timer_set_rate(unsigned timer, unsigned rate);
static void             led_pwm_channel_init(unsigned channel);

int led_pwm_servo_set(unsigned channel, uint8_t  value);
unsigned led_pwm_servo_get(unsigned channel);
int led_pwm_servo_init(void);
void led_pwm_servo_deinit(void);
void led_pwm_servo_arm(bool armed);
unsigned led_pwm_timer_get_period(unsigned timer);

static void led_pwm_timer_set_rate(unsigned timer, unsigned rate)
{

	irqstate_t flags = px4_enter_critical_section();

	uint32_t save = rSC(timer);
	rSC(timer) = save & ~(FTM_SC_CLKS_MASK);

	/* configure the timer to update at the desired rate */
	rMOD(timer) = (LED_PWM_FREQ / rate) - 1;
	rSC(timer) = save;

	px4_leave_critical_section(flags);
}

static inline uint32_t div2psc(int div)
{
	return 31 - __builtin_clz(div);
}

static inline void led_pwm_timer_set_PWM_mode(unsigned timer)
{
	irqstate_t flags = px4_enter_critical_section();
	rSC(timer) &= ~(FTM_SC_CLKS_MASK | FTM_SC_PS_MASK);
	rSC(timer) |= (FTM_SC_CLKS_EXTCLK | div2psc(FTM_SRC_CLOCK_FREQ / LED_PWM_FREQ));
	px4_leave_critical_section(flags);
}

static void
led_pwm_timer_init(unsigned timer)
{
	/* valid Timer */

	if (led_pwm_timers[timer].base != 0) {

		/* enable the timer clock before we try to talk to it */

		uint32_t regval = _REG(led_pwm_timers[timer].clock_register);
		regval |= led_pwm_timers[timer].clock_bit;
		_REG(led_pwm_timers[timer].clock_register) = regval;

		/* disable and configure the timer */

		rSC(timer)    = FTM_SC_CLKS_NONE;
		rCNT(timer)   = 0;

		rMODE(timer) = 0;
		rSYNCONF(timer)   = (FTM_SYNCONF_SYNCMODE | FTM_SYNCONF_SWWRBUF | FTM_SYNCONF_SWRSTCNT);

		/* Set to run in debug mode */

		rCONF(timer)   |= FTM_CONF_BDMMODE_MASK;

		/* enable the timer */

		led_pwm_timer_set_PWM_mode(timer);

		/*
		 * Note we do the Standard PWM Out init here
		 * default to updating at LED_PWM_RATE
		 */

		led_pwm_timer_set_rate(timer, LED_PWM_RATE);
	}
}
unsigned
led_pwm_timer_get_period(unsigned timer)
{
	// MOD is a 16 bit reg
	unsigned mod = rMOD(timer);

	if (mod == 0) {
		return 1 << 16;
	}

	return (uint16_t)(mod + 1);
}

static void
led_pwm_channel_init(unsigned channel)
{
	/* Only initialize used channels */

	if (led_pwm_channels[channel].timer_channel) {
		unsigned timer = led_pwm_channels[channel].timer_index;

		irqstate_t flags = px4_enter_critical_section();

		/* configure the GPIO first */

		px4_arch_configgpio(led_pwm_channels[channel].gpio_out);

		/* configure the channel */

		uint32_t chan = led_pwm_channels[channel].timer_channel - 1;

		uint16_t rvalue = REG(timer, KINETIS_FTM_CSC_OFFSET(chan));
		rvalue &= ~CnSC_RESET;
		rvalue |=  CnSC_PWMOUT_INIT;
		REG(timer, KINETIS_FTM_CSC_OFFSET(chan)) = rvalue;
		REG(timer, KINETIS_FTM_CV_OFFSET(0)) = 0;
		px4_leave_critical_section(flags);
	}
}

int
led_pwm_servo_set(unsigned channel, uint8_t  cvalue)
{
	if (channel >= arraySize(led_pwm_channels)) {
		return -1;
	}

	unsigned timer = led_pwm_channels[channel].timer_index;

	/* test timer for validity */
	if ((led_pwm_timers[timer].base == 0) ||
	    (led_pwm_channels[channel].gpio_out == 0)) {
		return -1;
	}

	unsigned period = led_pwm_timer_get_period(timer);

	unsigned value = (unsigned)cvalue * period / 255;

	/* configure the channel */
	if (value > 0) {
		value--;
	}

	REG(timer, KINETIS_FTM_CV_OFFSET(led_pwm_channels[channel].timer_channel - 1)) = value;

	return 0;
}
unsigned
led_pwm_servo_get(unsigned channel)
{
	if (channel >= 3) {
		return 0;
	}

	unsigned timer = led_pwm_channels[channel].timer_index;
	servo_position_t value = 0;

	/* test timer for validity */
	if ((led_pwm_timers[timer].base == 0) ||
	    (led_pwm_channels[channel].timer_channel == 0)) {
		return value;
	}

	value = REG(timer, KINETIS_FTM_CV_OFFSET(led_pwm_channels[channel].timer_channel - 1));
	unsigned period = led_pwm_timer_get_period(timer);
	return ((value + 1) * 255 / period);
}
int
led_pwm_servo_init(void)
{
	/* do basic timer initialisation first */
	for (unsigned i = 0; i < arraySize(led_pwm_timers); i++) {
		led_pwm_timer_init(i);
	}

	/* now init channels */
	for (unsigned i = 0; i < arraySize(led_pwm_channels); i++) {
		led_pwm_channel_init(i);
	}

	led_pwm_servo_arm(true);
	return OK;
}

void
led_pwm_servo_deinit(void)
{
	/* disable the timers */
	led_pwm_servo_arm(false);
}

void
led_pwm_servo_arm(bool armed)
{
	/* iterate timers and arm/disarm appropriately */
	for (unsigned i = 0; i < arraySize(led_pwm_timers); i++) {
		if (led_pwm_timers[i].base != 0) {
			if (armed) {
				/* force an update to preload all registers */
				led_pwm_timer_set_PWM_mode(i);

			} else {
				/* disable and configure the timer */

				rSC(i)    = FTM_SC_CLKS_NONE;
				rCNT(i)   = 0;
			}
		}
	}
}

#endif // BOARD_HAS_LED_PWM
<commit_msg>drv_led_pwm:Compile for either BOARD_HAS_LED_PWM or BOARD_HAS_UI_LED_PWM<commit_after>/****************************************************************************
 *
 *   Copyright (c) 2015, 2016 Airmind Development Team. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 * 3. Neither the name Airmind nor the names of its contributors may be
 *    used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 ****************************************************************************/

/**
* @file drv_led_pwm.cpp
*
*
*/

#include <px4_config.h>
#include <systemlib/px4_macros.h>
#include <nuttx/arch.h>
#include <nuttx/irq.h>

#include <sys/types.h>
#include <stdbool.h>

#include <assert.h>
#include <debug.h>
#include <time.h>
#include <queue.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>

#include <arch/board/board.h>
#include <drivers/drv_pwm_output.h>

#include "drv_io_timer.h"

#include <kinetis.h>
#include "chip/kinetis_sim.h"
#include "chip/kinetis_ftm.h"

#if defined(BOARD_HAS_LED_PWM) || defined(BOARD_HAS_UI_LED_PWM)

#define FTM_SRC_CLOCK_FREQ 16000000
#define LED_PWM_FREQ        1000000

#if (BOARD_LED_PWM_RATE)
#  define LED_PWM_RATE BOARD_LED_PWM_RATE
#else
#  define LED_PWM_RATE 50
#endif

#define _REG(_addr)	(*(volatile uint32_t *)(_addr))
#define _REG32(_base, _reg)	(*(volatile uint32_t *)(_base + _reg))
#define REG(_tmr, _reg)		_REG32(led_pwm_timers[_tmr].base, _reg)

/* Timer register accessors */

#define rSC(_tmr)         REG(_tmr,KINETIS_FTM_SC_OFFSET)
#define rCNT(_tmr)        REG(_tmr,KINETIS_FTM_CNT_OFFSET)
#define rMOD(_tmr)        REG(_tmr,KINETIS_FTM_MOD_OFFSET)
#define rC0SC(_tmr)       REG(_tmr,KINETIS_FTM_C0SC_OFFSET)
#define rC0V(_tmr)        REG(_tmr,KINETIS_FTM_C0V_OFFSET)
#define rC1SC(_tmr)       REG(_tmr,KINETIS_FTM_C1SC_OFFSET)
#define rC1V(_tmr)        REG(_tmr,KINETIS_FTM_C1V_OFFSET)
#define rC2SC(_tmr)       REG(_tmr,KINETIS_FTM_C2SC_OFFSET)
#define rC2V(_tmr)        REG(_tmr,KINETIS_FTM_C2V_OFFSET)
#define rC3SC(_tmr)       REG(_tmr,KINETIS_FTM_C3SC_OFFSET)
#define rC3V(_tmr)        REG(_tmr,KINETIS_FTM_C3V_OFFSET)
#define rC4SC(_tmr)       REG(_tmr,KINETIS_FTM_C4SC_OFFSET)
#define rC4V(_tmr)        REG(_tmr,KINETIS_FTM_C4V_OFFSET)
#define rC5SC(_tmr)       REG(_tmr,KINETIS_FTM_C5SC_OFFSET)
#define rC5V(_tmr)        REG(_tmr,KINETIS_FTM_C5V_OFFSET)
#define rC6SC(_tmr)       REG(_tmr,KINETIS_FTM_C6SC_OFFSET)
#define rC6V(_tmr)        REG(_tmr,KINETIS_FTM_C6V_OFFSET)
#define rC7SC(_tmr)       REG(_tmr,KINETIS_FTM_C7SC_OFFSET)
#define rC7V(_tmr)        REG(_tmr,KINETIS_FTM_C7V_OFFSET)

#define rCNTIN(_tmr)      REG(_tmr,KINETIS_FTM_CNTIN_OFFSET)
#define rSTATUS(_tmr)     REG(_tmr,KINETIS_FTM_STATUS_OFFSET)
#define rMODE(_tmr)       REG(_tmr,KINETIS_FTM_MODE_OFFSET)
#define rSYNC(_tmr)       REG(_tmr,KINETIS_FTM_SYNC_OFFSET)
#define rOUTINIT(_tmr)    REG(_tmr,KINETIS_FTM_OUTINIT_OFFSET)
#define rOUTMASK(_tmr)    REG(_tmr,KINETIS_FTM_OUTMASK_OFFSET)
#define rCOMBINE(_tmr)    REG(_tmr,KINETIS_FTM_COMBINE_OFFSET)
#define rDEADTIME(_tmr)   REG(_tmr,KINETIS_FTM_DEADTIME_OFFSET)
#define rEXTTRIG(_tmr)    REG(_tmr,KINETIS_FTM_EXTTRIG_OFFSET)
#define rPOL(_tmr)        REG(_tmr,KINETIS_FTM_POL_OFFSET)
#define rFMS(_tmr)        REG(_tmr,KINETIS_FTM_FMS_OFFSET)
#define rFILTER(_tmr)     REG(_tmr,KINETIS_FTM_FILTER_OFFSET)
#define rFLTCTRL(_tmr)    REG(_tmr,KINETIS_FTM_FLTCTRL_OFFSET)
#define rQDCTRL(_tmr)     REG(_tmr,KINETIS_FTM_QDCTRL_OFFSET)
#define rCONF(_tmr)       REG(_tmr,KINETIS_FTM_CONF_OFFSET)
#define rFLTPOL(_tmr)     REG(_tmr,KINETIS_FTM_FLTPOL_OFFSET)
#define rSYNCONF(_tmr)    REG(_tmr,KINETIS_FTM_SYNCONF_OFFSET)
#define rINVCTRL(_tmr)    REG(_tmr,KINETIS_FTM_INVCTRL_OFFSET)
#define rSWOCTRL(_tmr)    REG(_tmr,KINETIS_FTM_SWOCTRL_OFFSET)
#define rPWMLOAD(_tmr)    REG(_tmr,KINETIS_FTM_PWMLOAD_OFFSET)

#define CnSC_RESET          (FTM_CSC_CHF|FTM_CSC_CHIE|FTM_CSC_MSB|FTM_CSC_MSA|FTM_CSC_ELSB|FTM_CSC_ELSA|FTM_CSC_DMA)
#define CnSC_CAPTURE_INIT   (FTM_CSC_CHIE|FTM_CSC_ELSB|FTM_CSC_ELSA) // Both

#if defined(BOARD_LED_PWM_DRIVE_ACTIVE_LOW)
#define CnSC_PWMOUT_INIT    (FTM_CSC_MSB|FTM_CSC_ELSA)
#else
#define CnSC_PWMOUT_INIT    (FTM_CSC_MSB|FTM_CSC_ELSB)
#endif

#define FTM_SYNC (FTM_SYNC_SWSYNC)

static void             led_pwm_timer_init(unsigned timer);
static void             led_pwm_timer_set_rate(unsigned timer, unsigned rate);
static void             led_pwm_channel_init(unsigned channel);

int led_pwm_servo_set(unsigned channel, uint8_t  value);
unsigned led_pwm_servo_get(unsigned channel);
int led_pwm_servo_init(void);
void led_pwm_servo_deinit(void);
void led_pwm_servo_arm(bool armed);
unsigned led_pwm_timer_get_period(unsigned timer);

static void led_pwm_timer_set_rate(unsigned timer, unsigned rate)
{

	irqstate_t flags = px4_enter_critical_section();

	uint32_t save = rSC(timer);
	rSC(timer) = save & ~(FTM_SC_CLKS_MASK);

	/* configure the timer to update at the desired rate */
	rMOD(timer) = (LED_PWM_FREQ / rate) - 1;
	rSC(timer) = save;

	px4_leave_critical_section(flags);
}

static inline uint32_t div2psc(int div)
{
	return 31 - __builtin_clz(div);
}

static inline void led_pwm_timer_set_PWM_mode(unsigned timer)
{
	irqstate_t flags = px4_enter_critical_section();
	rSC(timer) &= ~(FTM_SC_CLKS_MASK | FTM_SC_PS_MASK);
	rSC(timer) |= (FTM_SC_CLKS_EXTCLK | div2psc(FTM_SRC_CLOCK_FREQ / LED_PWM_FREQ));
	px4_leave_critical_section(flags);
}

static void
led_pwm_timer_init(unsigned timer)
{
	/* valid Timer */

	if (led_pwm_timers[timer].base != 0) {

		/* enable the timer clock before we try to talk to it */

		uint32_t regval = _REG(led_pwm_timers[timer].clock_register);
		regval |= led_pwm_timers[timer].clock_bit;
		_REG(led_pwm_timers[timer].clock_register) = regval;

		/* disable and configure the timer */

		rSC(timer)    = FTM_SC_CLKS_NONE;
		rCNT(timer)   = 0;

		rMODE(timer) = 0;
		rSYNCONF(timer)   = (FTM_SYNCONF_SYNCMODE | FTM_SYNCONF_SWWRBUF | FTM_SYNCONF_SWRSTCNT);

		/* Set to run in debug mode */

		rCONF(timer)   |= FTM_CONF_BDMMODE_MASK;

		/* enable the timer */

		led_pwm_timer_set_PWM_mode(timer);

		/*
		 * Note we do the Standard PWM Out init here
		 * default to updating at LED_PWM_RATE
		 */

		led_pwm_timer_set_rate(timer, LED_PWM_RATE);
	}
}
unsigned
led_pwm_timer_get_period(unsigned timer)
{
	// MOD is a 16 bit reg
	unsigned mod = rMOD(timer);

	if (mod == 0) {
		return 1 << 16;
	}

	return (uint16_t)(mod + 1);
}

static void
led_pwm_channel_init(unsigned channel)
{
	/* Only initialize used channels */

	if (led_pwm_channels[channel].timer_channel) {
		unsigned timer = led_pwm_channels[channel].timer_index;

		irqstate_t flags = px4_enter_critical_section();

		/* configure the GPIO first */

		px4_arch_configgpio(led_pwm_channels[channel].gpio_out);

		/* configure the channel */

		uint32_t chan = led_pwm_channels[channel].timer_channel - 1;

		uint16_t rvalue = REG(timer, KINETIS_FTM_CSC_OFFSET(chan));
		rvalue &= ~CnSC_RESET;
		rvalue |=  CnSC_PWMOUT_INIT;
		REG(timer, KINETIS_FTM_CSC_OFFSET(chan)) = rvalue;
		REG(timer, KINETIS_FTM_CV_OFFSET(0)) = 0;
		px4_leave_critical_section(flags);
	}
}

int
led_pwm_servo_set(unsigned channel, uint8_t  cvalue)
{
	if (channel >= arraySize(led_pwm_channels)) {
		return -1;
	}

	unsigned timer = led_pwm_channels[channel].timer_index;

	/* test timer for validity */
	if ((led_pwm_timers[timer].base == 0) ||
	    (led_pwm_channels[channel].gpio_out == 0)) {
		return -1;
	}

	unsigned period = led_pwm_timer_get_period(timer);

	unsigned value = (unsigned)cvalue * period / 255;

	/* configure the channel */
	if (value > 0) {
		value--;
	}

	REG(timer, KINETIS_FTM_CV_OFFSET(led_pwm_channels[channel].timer_channel - 1)) = value;

	return 0;
}
unsigned
led_pwm_servo_get(unsigned channel)
{
	if (channel >= 3) {
		return 0;
	}

	unsigned timer = led_pwm_channels[channel].timer_index;
	servo_position_t value = 0;

	/* test timer for validity */
	if ((led_pwm_timers[timer].base == 0) ||
	    (led_pwm_channels[channel].timer_channel == 0)) {
		return value;
	}

	value = REG(timer, KINETIS_FTM_CV_OFFSET(led_pwm_channels[channel].timer_channel - 1));
	unsigned period = led_pwm_timer_get_period(timer);
	return ((value + 1) * 255 / period);
}
int
led_pwm_servo_init(void)
{
	/* do basic timer initialisation first */
	for (unsigned i = 0; i < arraySize(led_pwm_timers); i++) {
		led_pwm_timer_init(i);
	}

	/* now init channels */
	for (unsigned i = 0; i < arraySize(led_pwm_channels); i++) {
		led_pwm_channel_init(i);
	}

	led_pwm_servo_arm(true);
	return OK;
}

void
led_pwm_servo_deinit(void)
{
	/* disable the timers */
	led_pwm_servo_arm(false);
}

void
led_pwm_servo_arm(bool armed)
{
	/* iterate timers and arm/disarm appropriately */
	for (unsigned i = 0; i < arraySize(led_pwm_timers); i++) {
		if (led_pwm_timers[i].base != 0) {
			if (armed) {
				/* force an update to preload all registers */
				led_pwm_timer_set_PWM_mode(i);

			} else {
				/* disable and configure the timer */

				rSC(i)    = FTM_SC_CLKS_NONE;
				rCNT(i)   = 0;
			}
		}
	}
}

#endif // BOARD_HAS_LED_PWM || BOARD_HAS_UI_LED_PWM
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: slidebitmap.cxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: thb $ $Date: 2004-03-18 10:44:36 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library 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
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _OSL_DIAGNOSE_H_
#include <osl/diagnose.h>
#endif

#ifndef _DRAFTS_COM_SUN_STAR_RENDERING_XCANVAS_HPP_
#include <drafts/com/sun/star/rendering/XCanvas.hpp>
#endif
#ifndef _DRAFTS_COM_SUN_STAR_RENDERING_XBITMAP_HPP_
#include <drafts/com/sun/star/rendering/XBitmap.hpp>
#endif

#include <canvas/canvastools.hxx>
#include <basegfx/tools/canvastools.hxx>

#include "slidebitmap.hxx"

using namespace ::drafts::com::sun::star;
using namespace ::com::sun::star;

namespace presentation
{
    namespace internal
    {

        SlideBitmap::SlideBitmap( const ::cppcanvas::BitmapSharedPtr& rBitmap ) :
            mxBitmap( rBitmap.get() != NULL ? rBitmap->getUNOBitmap() : NULL )
        {
            OSL_ENSURE( mxBitmap.is(), "SlideBitmap::SlideBitmap(): Invalid bitmap" );
        }

        bool SlideBitmap::draw( const ::cppcanvas::CanvasSharedPtr& rCanvas ) const
        {
            OSL_ENSURE( rCanvas.get() != NULL && rCanvas->getUNOCanvas().is(),
                        "SlideBitmap::draw(): Invalid canvas" );

            if( rCanvas.get() == NULL || !rCanvas->getUNOCanvas().is() )
                return false;

            rendering::RenderState aRenderState;
            ::canvas::tools::initRenderState( aRenderState );

            rCanvas->getUNOCanvas()->drawBitmap( mxBitmap,
                                                 rCanvas->getViewState(),
                                                 aRenderState );
            return true;
        }

        ::basegfx::B2ISize SlideBitmap::getSize() const
        {
            return ::basegfx::unotools::b2ISizeFromIntegerSize2D( mxBitmap->getSize() );
        }

    }
}
<commit_msg>INTEGRATION: CWS presentationengine01 (1.2.2); FILE MERGED 2004/11/10 11:58:59 thb 1.2.2.7: #i1000# Solaris compiler glitch: ternary ? not handled correctly, re-phrased code 2004/09/30 15:01:00 thb 1.2.2.6: #110496# Added another special transition effect (comb transition); sorted out various gcc -Wall warnings; improved docs 2004/08/19 00:17:17 thb 1.2.2.5: #110496# Mostly fixes for correct text animation and iteration, plus a first working version of an optimized redraw 2004/08/03 19:46:36 thb 1.2.2.4: #110496# Properly clearing the views before the slideshow, setting a clipping the size of the slides 2004/07/22 19:42:12 thb 1.2.2.3: #110496# Slideshow milestone, all smil attributes implemented, effects basically working, UI events basically working, text iterations working 2004/05/27 15:05:02 thb 1.2.2.2: Initial revision 2004/04/05 16:06:09 thb 1.2.2.1: Resync with canvas01 changes<commit_after>/*************************************************************************
 *
 *  $RCSfile: slidebitmap.cxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: rt $ $Date: 2004-11-26 18:59:01 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library 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
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

// must be first
#include <canvas/debug.hxx>
#include <slidebitmap.hxx>

#ifndef _DRAFTS_COM_SUN_STAR_RENDERING_XCANVAS_HPP_
#include <drafts/com/sun/star/rendering/XCanvas.hpp>
#endif
#ifndef _DRAFTS_COM_SUN_STAR_RENDERING_XBITMAP_HPP_
#include <drafts/com/sun/star/rendering/XBitmap.hpp>
#endif

#ifndef _BGFX_MATRIX_B2DHOMMATRIX_HXX
#include <basegfx/matrix/b2dhommatrix.hxx>
#endif

#include <canvas/canvastools.hxx>
#include <basegfx/tools/canvastools.hxx>

using namespace ::drafts::com::sun::star;
using namespace ::com::sun::star;

namespace presentation
{
    namespace internal
    {

        SlideBitmap::SlideBitmap( const ::cppcanvas::BitmapSharedPtr& rBitmap ) :
            maOutputPos(),
            maClipPoly(),
            mxBitmap()
        {
            if( rBitmap.get() )
                mxBitmap = rBitmap->getUNOBitmap();

            ENSURE_AND_THROW( mxBitmap.is(), "SlideBitmap::SlideBitmap(): Invalid bitmap" );
        }

        bool SlideBitmap::draw( const ::cppcanvas::CanvasSharedPtr& rCanvas ) const
        {
            ENSURE_AND_RETURN( rCanvas.get() != NULL && rCanvas->getUNOCanvas().is(),
                               "SlideBitmap::draw(): Invalid canvas" );

            // selectively only copy the transformation from current viewstate,
            // don't want no clipping here.
            rendering::ViewState aViewState;
            aViewState.AffineTransform = rCanvas->getViewState().AffineTransform;

            rendering::RenderState aRenderState;
            ::canvas::tools::initRenderState( aRenderState );

            ::basegfx::B2DHomMatrix aTranslation;
            aTranslation.translate( maOutputPos.getX(),
                                    maOutputPos.getY() );
            ::canvas::tools::setRenderStateTransform( aRenderState, aTranslation );

            if( maClipPoly.count() )
            {
                // TODO(P1): Buffer the clip polygon
                aRenderState.Clip =
                    ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
                        rCanvas->getUNOCanvas()->getDevice(),
                        maClipPoly );
            }

            rCanvas->getUNOCanvas()->drawBitmap( mxBitmap,
                                                 aViewState,
                                                 aRenderState );
            return true;
        }

        ::basegfx::B2ISize SlideBitmap::getSize() const
        {
            return ::basegfx::unotools::b2ISizeFromIntegerSize2D( mxBitmap->getSize() );
        }

        void SlideBitmap::move( const ::basegfx::B2DPoint& rNewPos )
        {
            maOutputPos = rNewPos;
        }

        void SlideBitmap::clip( const ::basegfx::B2DPolyPolygon& rClipPoly )
        {
            maClipPoly = rClipPoly;
        }

    }
}
<|endoftext|>


<commit_before>/* Copyright 2015 The TensorFlow Authors. 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.
==============================================================================*/

#define EIGEN_USE_THREADS

#include <algorithm>
#include <numeric>
#include <unordered_map>
#include <utility>
#include <vector>

#include "tensorflow/core/framework/op_kernel.h"
#include "tensorflow/core/framework/register_types.h"
#include "tensorflow/core/framework/tensor.h"
#include "tensorflow/core/framework/tensor.pb.h"
#include "tensorflow/core/framework/tensor_util.h"
#include "tensorflow/core/framework/types.h"
#include "tensorflow/core/framework/variant.h"
#include "tensorflow/core/framework/variant_encode_decode.h"
#include "tensorflow/core/kernels/reshape_util.h"
#include "tensorflow/core/lib/gtl/inlined_vector.h"
#include "tensorflow/core/lib/gtl/optional.h"
#include "tensorflow/core/util/sparse/group_iterator.h"
#include "tensorflow/core/util/sparse/sparse_tensor.h"

namespace tensorflow {

namespace {

using sparse::SparseTensor;

template <typename T>
class SerializeSparseOp : public OpKernel {
 public:
  explicit SerializeSparseOp(OpKernelConstruction* context)
      : OpKernel(context) {}

  bool IsExpensive() override;

  Status Initialize(Tensor* result);
  Status Serialize(const Tensor& input, T* result);

  void Compute(OpKernelContext* context) override {
    const Tensor* input_indices;
    const Tensor* input_values;
    const Tensor* input_shape;

    OP_REQUIRES_OK(context, context->input("sparse_indices", &input_indices));
    OP_REQUIRES_OK(context, context->input("sparse_values", &input_values));
    OP_REQUIRES_OK(context, context->input("sparse_shape", &input_shape));
    OP_REQUIRES(context, TensorShapeUtils::IsMatrix(input_indices->shape()),
                errors::InvalidArgument(
                    "Input indices should be a matrix but received shape ",
                    input_indices->shape().DebugString()));

    OP_REQUIRES(context, TensorShapeUtils::IsVector(input_values->shape()),
                errors::InvalidArgument(
                    "Input values should be a vector but received shape ",
                    input_values->shape().DebugString()));

    OP_REQUIRES(context, TensorShapeUtils::IsVector(input_shape->shape()),
                errors::InvalidArgument(
                    "Input shape should be a vector but received shape ",
                    input_shape->shape().DebugString()));

    Tensor serialized_sparse;
    OP_REQUIRES_OK(context, Initialize(&serialized_sparse));

    auto serialized_sparse_t = serialized_sparse.vec<T>();
    OP_REQUIRES_OK(context, Serialize(*input_indices, &serialized_sparse_t(0)));
    OP_REQUIRES_OK(context, Serialize(*input_values, &serialized_sparse_t(1)));
    OP_REQUIRES_OK(context, Serialize(*input_shape, &serialized_sparse_t(2)));

    context->set_output(0, serialized_sparse);
  }
};

// NOTE(mrry): We specialize the IsExpensive() method differently for
// the string and variant cases, because (i) the string version
// actually performs memory copies as part of its serialization (and
// is hence potentially expensive), and (ii) the variant version
// performs O(1) shallow copies (and hence is much cheaper than
// dispatching to another thread would be).
template <>
bool SerializeSparseOp<tstring>::IsExpensive() {
  return true;
}
template <>
bool SerializeSparseOp<Variant>::IsExpensive() {
  return false;
}

template <>
Status SerializeSparseOp<tstring>::Initialize(Tensor* result) {
  *result = Tensor(DT_STRING, TensorShape({3}));
  return Status::OK();
}

template <>
Status SerializeSparseOp<tstring>::Serialize(const Tensor& input,
                                             tstring* result) {
  TensorProto proto;
  input.AsProtoTensorContent(&proto);
  *result = proto.SerializeAsString();
  return Status::OK();
}

REGISTER_KERNEL_BUILDER(Name("SerializeSparse")
                            .Device(DEVICE_CPU)
                            .TypeConstraint<tstring>("out_type"),
                        SerializeSparseOp<tstring>);

template <>
Status SerializeSparseOp<Variant>::Initialize(Tensor* result) {
  *result = Tensor(DT_VARIANT, TensorShape({3}));
  return Status::OK();
}

template <>
Status SerializeSparseOp<Variant>::Serialize(const Tensor& input,
                                             Variant* result) {
  *result = input;
  return Status::OK();
}

REGISTER_KERNEL_BUILDER(Name("SerializeSparse")
                            .Device(DEVICE_CPU)
                            .TypeConstraint<Variant>("out_type"),
                        SerializeSparseOp<Variant>);

template <typename T, typename U>
struct SerializeGroups {};

template <typename T>
struct SerializeGroups<T, tstring> {
  Status operator()(sparse::GroupIterable* minibatch,
                    const Tensor& output_shape, int64 N, int rank,
                    Tensor* serialized_sparse) {
    auto serialized_sparse_t = serialized_sparse->matrix<tstring>();

    int64 last_nonempty_group = -1;

    auto serialize = [](const Tensor& input, tstring* result) {
      TensorProto proto;
      input.AsProtoTensorContent(&proto);
      *result = proto.SerializeAsString();
    };

    tstring serialized_shape;
    serialize(output_shape, &serialized_shape);

    auto serialize_empty_element = [&](int64 b) {
      serialize(Tensor(DT_INT64, {0, rank - 1}), &serialized_sparse_t(b, 0));
      serialize(Tensor(DataTypeToEnum<T>::value, {0}),
                &serialized_sparse_t(b, 1));
      serialized_sparse_t(b, 2) = serialized_shape;
    };

    for (const auto& subset : *minibatch) {
      const int64 b = subset.group_at(0);
      if (b < 0 || b >= N) {
        return errors::InvalidArgument(
            "Received unexpected column 0 value in input SparseTensor: ", b,
            " < 0 or >= N (= ", N, ")");
      }

      // GroupIterable generates only the non-empty groups of rows, so we must
      // generate empty outputs for any empty rows since the last non-empty
      // group that was generated.
      for (int64 empty_b = last_nonempty_group + 1; empty_b < b; ++empty_b) {
        serialize_empty_element(empty_b);
      }

      last_nonempty_group = b;

      const auto indices = subset.indices();
      const auto values = subset.values<T>();
      const int64 num_entries = values.size();

      Tensor output_indices = Tensor(DT_INT64, {num_entries, rank - 1});
      Tensor output_values = Tensor(DataTypeToEnum<T>::value, {num_entries});

      auto output_indices_t = output_indices.matrix<int64>();
      auto output_values_t = output_values.vec<T>();

      for (int i = 0; i < num_entries; ++i) {
        for (int d = 1; d < rank; ++d) {
          output_indices_t(i, d - 1) = indices(i, d);
        }
        output_values_t(i) = values(i);
      }

      serialize(output_indices, &serialized_sparse_t(b, 0));
      serialize(output_values, &serialized_sparse_t(b, 1));
      serialized_sparse_t(b, 2) = serialized_shape;
    }

    for (int64 empty_b = last_nonempty_group + 1; empty_b < N; ++empty_b) {
      serialize_empty_element(empty_b);
    }

    return Status::OK();
  }
};

template <typename T>
struct SerializeGroups<T, Variant> {
  Status operator()(sparse::GroupIterable* minibatch,
                    const Tensor& output_shape, int64 N, int rank,
                    Tensor* serialized_sparse) {
    auto serialized_sparse_t = serialized_sparse->template matrix<Variant>();

    int64 last_nonempty_group = -1;

    auto serialize_empty_element = [&](int64 b) {
      serialized_sparse_t(b, 0).emplace<Tensor>(DT_INT64,
                                                TensorShape({0, rank - 1}));
      serialized_sparse_t(b, 1).emplace<Tensor>(DataTypeToEnum<T>::value,
                                                TensorShape({0}));
      serialized_sparse_t(b, 2).emplace<Tensor>(output_shape);
    };

    for (const auto& subset : *minibatch) {
      const int64 b = subset.group_at(0);
      if (b < 0 || b >= N) {
        return errors::InvalidArgument(
            "Received unexpected column 0 value in input SparseTensor: ", b,
            " < 0 or >= N (= ", N, ")");
      }

      // GroupIterable generates only the non-empty groups of rows, so we must
      // generate empty outputs for any empty rows since the last non-empty
      // group that was generated.
      for (int64 empty_b = last_nonempty_group + 1; empty_b < b; ++empty_b) {
        serialize_empty_element(empty_b);
      }

      last_nonempty_group = b;

      const auto indices = subset.indices();
      const auto values = subset.values<T>();
      const int64 num_entries = values.size();

      Tensor& output_indices = serialized_sparse_t(b, 0).emplace<Tensor>(
          DT_INT64, TensorShape({num_entries, rank - 1}));
      Tensor& output_values = serialized_sparse_t(b, 1).emplace<Tensor>(
          DataTypeToEnum<T>::value, TensorShape({num_entries}));

      auto output_indices_t = output_indices.matrix<int64>();
      auto output_values_t = output_values.vec<T>();

      for (int i = 0; i < num_entries; ++i) {
        for (int d = 1; d < rank; ++d) {
          output_indices_t(i, d - 1) = indices(i, d);
        }
        output_values_t(i) = values(i);
      }

      serialized_sparse_t(b, 2).emplace<Tensor>(output_shape);
    }

    for (int64 empty_b = last_nonempty_group + 1; empty_b < N; ++empty_b) {
      serialize_empty_element(empty_b);
    }

    return Status::OK();
  }
};

template <typename T, typename U>
class SerializeManySparseOp : public OpKernel {
 public:
  explicit SerializeManySparseOp(OpKernelConstruction* context)
      : OpKernel(context) {}

  void Compute(OpKernelContext* context) override {
    const Tensor* input_indices;
    const Tensor* input_values;
    const Tensor* input_shape;
    OP_REQUIRES_OK(context, context->input("sparse_indices", &input_indices));
    OP_REQUIRES_OK(context, context->input("sparse_values", &input_values));
    OP_REQUIRES_OK(context, context->input("sparse_shape", &input_shape));
    OP_REQUIRES(context, TensorShapeUtils::IsMatrix(input_indices->shape()),
                errors::InvalidArgument(
                    "Input indices should be a matrix but received shape ",
                    input_indices->shape().DebugString()));

    OP_REQUIRES(context, TensorShapeUtils::IsVector(input_values->shape()),
                errors::InvalidArgument(
                    "Input values should be a vector but received shape ",
                    input_values->shape().DebugString()));

    OP_REQUIRES(context, TensorShapeUtils::IsVector(input_shape->shape()),
                errors::InvalidArgument(
                    "Input shape should be a vector but received shape ",
                    input_shape->shape().DebugString()));

    int rank = input_shape->NumElements();

    OP_REQUIRES(
        context, rank > 1,
        errors::InvalidArgument(
            "Rank of input SparseTensor should be > 1, but saw rank: ", rank));

    TensorShape tensor_input_shape(input_shape->vec<int64>());
    gtl::InlinedVector<int64, 8> std_order(rank);
    std::iota(std_order.begin(), std_order.end(), 0);
    SparseTensor input_st;
    OP_REQUIRES_OK(context, SparseTensor::Create(*input_indices, *input_values,
                                                 tensor_input_shape, std_order,
                                                 &input_st));

    auto input_shape_t = input_shape->vec<int64>();
    const int64 N = input_shape_t(0);

    Tensor* serialized_sparse;
    OP_REQUIRES_OK(context,
                   context->allocate_output(0, {N, 3}, &serialized_sparse));

    OP_REQUIRES_OK(context, input_st.IndicesValid());

    Tensor output_shape(DT_INT64, {rank - 1});
    auto output_shape_t = output_shape.vec<int64>();
    for (int d = 1; d < rank; d++) output_shape_t(d - 1) = input_shape_t(d);

    // Get groups by minibatch dimension
    sparse::GroupIterable minibatch = input_st.group({0});

    OP_REQUIRES_OK(context, SerializeGroups<T, U>()(&minibatch, output_shape, N,
                                                    rank, serialized_sparse));
  }
};

#define REGISTER_KERNELS(type)                                      \
  REGISTER_KERNEL_BUILDER(Name("SerializeManySparse")               \
                              .Device(DEVICE_CPU)                   \
                              .TypeConstraint<type>("T")            \
                              .TypeConstraint<tstring>("out_type"), \
                          SerializeManySparseOp<type, tstring>)

TF_CALL_ALL_TYPES(REGISTER_KERNELS);
#undef REGISTER_KERNELS

#define REGISTER_KERNELS(type)                                      \
  REGISTER_KERNEL_BUILDER(Name("SerializeManySparse")               \
                              .Device(DEVICE_CPU)                   \
                              .TypeConstraint<type>("T")            \
                              .TypeConstraint<Variant>("out_type"), \
                          SerializeManySparseOp<type, Variant>)

TF_CALL_ALL_TYPES(REGISTER_KERNELS);
#undef REGISTER_KERNELS

}  // namespace

}  // namespace tensorflow
<commit_msg>The ROCm CSB was broken by the following commit :<commit_after>/* Copyright 2015 The TensorFlow Authors. 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.
==============================================================================*/

#define EIGEN_USE_THREADS

#include <algorithm>
#include <numeric>
#include <unordered_map>
#include <utility>
#include <vector>

#include "tensorflow/core/framework/op_kernel.h"
#include "tensorflow/core/framework/register_types.h"
#include "tensorflow/core/framework/tensor.h"
#include "tensorflow/core/framework/tensor.pb.h"
#include "tensorflow/core/framework/tensor_util.h"
#include "tensorflow/core/framework/types.h"
#include "tensorflow/core/framework/variant.h"
#include "tensorflow/core/framework/variant_encode_decode.h"
#include "tensorflow/core/kernels/reshape_util.h"
#include "tensorflow/core/lib/gtl/inlined_vector.h"
#include "tensorflow/core/lib/gtl/optional.h"
#include "tensorflow/core/util/sparse/group_iterator.h"
#include "tensorflow/core/util/sparse/sparse_tensor.h"

namespace tensorflow {

namespace {

using sparse::SparseTensor;

template <typename T>
class SerializeSparseOp : public OpKernel {
 public:
  explicit SerializeSparseOp(OpKernelConstruction* context)
      : OpKernel(context) {}

  bool IsExpensive() override;

  Status Initialize(Tensor* result);
  Status Serialize(const Tensor& input, T* result);

  void Compute(OpKernelContext* context) override {
    const Tensor* input_indices;
    const Tensor* input_values;
    const Tensor* input_shape;

    OP_REQUIRES_OK(context, context->input("sparse_indices", &input_indices));
    OP_REQUIRES_OK(context, context->input("sparse_values", &input_values));
    OP_REQUIRES_OK(context, context->input("sparse_shape", &input_shape));
    OP_REQUIRES(context, TensorShapeUtils::IsMatrix(input_indices->shape()),
                errors::InvalidArgument(
                    "Input indices should be a matrix but received shape ",
                    input_indices->shape().DebugString()));

    OP_REQUIRES(context, TensorShapeUtils::IsVector(input_values->shape()),
                errors::InvalidArgument(
                    "Input values should be a vector but received shape ",
                    input_values->shape().DebugString()));

    OP_REQUIRES(context, TensorShapeUtils::IsVector(input_shape->shape()),
                errors::InvalidArgument(
                    "Input shape should be a vector but received shape ",
                    input_shape->shape().DebugString()));

    Tensor serialized_sparse;
    OP_REQUIRES_OK(context, Initialize(&serialized_sparse));

    auto serialized_sparse_t = serialized_sparse.vec<T>();
    OP_REQUIRES_OK(context, Serialize(*input_indices, &serialized_sparse_t(0)));
    OP_REQUIRES_OK(context, Serialize(*input_values, &serialized_sparse_t(1)));
    OP_REQUIRES_OK(context, Serialize(*input_shape, &serialized_sparse_t(2)));

    context->set_output(0, serialized_sparse);
  }
};

// NOTE(mrry): We specialize the IsExpensive() method differently for
// the string and variant cases, because (i) the string version
// actually performs memory copies as part of its serialization (and
// is hence potentially expensive), and (ii) the variant version
// performs O(1) shallow copies (and hence is much cheaper than
// dispatching to another thread would be).
template <>
bool SerializeSparseOp<tstring>::IsExpensive() {
  return true;
}
template <>
bool SerializeSparseOp<Variant>::IsExpensive() {
  return false;
}

template <>
Status SerializeSparseOp<tstring>::Initialize(Tensor* result) {
  *result = Tensor(DT_STRING, TensorShape({3}));
  return Status::OK();
}

template <>
Status SerializeSparseOp<tstring>::Serialize(const Tensor& input,
                                             tstring* result) {
  TensorProto proto;
  input.AsProtoTensorContent(&proto);
  *result = proto.SerializeAsString();
  return Status::OK();
}

REGISTER_KERNEL_BUILDER(Name("SerializeSparse")
                            .Device(DEVICE_CPU)
                            .TypeConstraint<tstring>("out_type"),
                        SerializeSparseOp<tstring>);

template <>
Status SerializeSparseOp<Variant>::Initialize(Tensor* result) {
  *result = Tensor(DT_VARIANT, TensorShape({3}));
  return Status::OK();
}

template <>
Status SerializeSparseOp<Variant>::Serialize(const Tensor& input,
                                             Variant* result) {
  *result = input;
  return Status::OK();
}

REGISTER_KERNEL_BUILDER(Name("SerializeSparse")
                            .Device(DEVICE_CPU)
                            .TypeConstraint<Variant>("out_type"),
                        SerializeSparseOp<Variant>);

template <typename T, typename U>
struct SerializeGroups {};

template <typename T>
struct SerializeGroups<T, tstring> {
  Status operator()(sparse::GroupIterable* minibatch,
                    const Tensor& output_shape, int64 N, int rank,
                    Tensor* serialized_sparse) {
    auto serialized_sparse_t = serialized_sparse->matrix<tstring>();

    int64 last_nonempty_group = -1;

    auto serialize = [](const Tensor& input, tstring* result) {
      TensorProto proto;
      input.AsProtoTensorContent(&proto);
      *result = proto.SerializeAsString();
    };

    tstring serialized_shape;
    serialize(output_shape, &serialized_shape);

    auto serialize_empty_element = [&](int64 b) {
      serialize(Tensor(DT_INT64, {0, rank - 1}), &serialized_sparse_t(b, 0));
      serialize(Tensor(DataTypeToEnum<T>::value, {0}),
                &serialized_sparse_t(b, 1));
      serialized_sparse_t(b, 2) = serialized_shape;
    };

    for (const auto& subset : *minibatch) {
      const int64 b = subset.group_at(0);
      if (b < 0 || b >= N) {
        return errors::InvalidArgument(
            "Received unexpected column 0 value in input SparseTensor: ", b,
            " < 0 or >= N (= ", N, ")");
      }

      // GroupIterable generates only the non-empty groups of rows, so we must
      // generate empty outputs for any empty rows since the last non-empty
      // group that was generated.
      for (int64 empty_b = last_nonempty_group + 1; empty_b < b; ++empty_b) {
        serialize_empty_element(empty_b);
      }

      last_nonempty_group = b;

      const auto indices = subset.indices();
      const auto values = subset.values<T>();
      const int64 num_entries = values.size();

      Tensor output_indices = Tensor(DT_INT64, {num_entries, rank - 1});
      Tensor output_values = Tensor(DataTypeToEnum<T>::value, {num_entries});

      auto output_indices_t = output_indices.matrix<int64>();
      auto output_values_t = output_values.vec<T>();

      for (int i = 0; i < num_entries; ++i) {
        for (int d = 1; d < rank; ++d) {
          output_indices_t(i, d - 1) = indices(i, d);
        }
        output_values_t(i) = values(i);
      }

      serialize(output_indices, &serialized_sparse_t(b, 0));
      serialize(output_values, &serialized_sparse_t(b, 1));
      serialized_sparse_t(b, 2) = serialized_shape;
    }

    for (int64 empty_b = last_nonempty_group + 1; empty_b < N; ++empty_b) {
      serialize_empty_element(empty_b);
    }

    return Status::OK();
  }
};

template <typename T>
struct SerializeGroups<T, Variant> {
  Status operator()(sparse::GroupIterable* minibatch,
                    const Tensor& output_shape, int64 N, int rank,
                    Tensor* serialized_sparse) {
    auto serialized_sparse_t = serialized_sparse->template matrix<Variant>();

    int64 last_nonempty_group = -1;

    // The "DataTypeToEnum<T>::value" member is static and defined but not
    // declared.  This leads to linker errors when a "DataTypeToEnum<T>::value"
    // reference is passed to a routine. Creating a local variable here to
    // workaround the linker errors.
    DataType T_type = DataTypeToEnum<T>::value;

    auto serialize_empty_element = [&](int64 b) {
      serialized_sparse_t(b, 0).emplace<Tensor>(DT_INT64,
                                                TensorShape({0, rank - 1}));
      serialized_sparse_t(b, 1).emplace<Tensor>(T_type, TensorShape({0}));
      serialized_sparse_t(b, 2).emplace<Tensor>(output_shape);
    };

    for (const auto& subset : *minibatch) {
      const int64 b = subset.group_at(0);
      if (b < 0 || b >= N) {
        return errors::InvalidArgument(
            "Received unexpected column 0 value in input SparseTensor: ", b,
            " < 0 or >= N (= ", N, ")");
      }

      // GroupIterable generates only the non-empty groups of rows, so we must
      // generate empty outputs for any empty rows since the last non-empty
      // group that was generated.
      for (int64 empty_b = last_nonempty_group + 1; empty_b < b; ++empty_b) {
        serialize_empty_element(empty_b);
      }

      last_nonempty_group = b;

      const auto indices = subset.indices();
      const auto values = subset.values<T>();
      const int64 num_entries = values.size();

      Tensor& output_indices = serialized_sparse_t(b, 0).emplace<Tensor>(
          DT_INT64, TensorShape({num_entries, rank - 1}));
      Tensor& output_values = serialized_sparse_t(b, 1).emplace<Tensor>(
          T_type, TensorShape({num_entries}));

      auto output_indices_t = output_indices.matrix<int64>();
      auto output_values_t = output_values.vec<T>();

      for (int i = 0; i < num_entries; ++i) {
        for (int d = 1; d < rank; ++d) {
          output_indices_t(i, d - 1) = indices(i, d);
        }
        output_values_t(i) = values(i);
      }

      serialized_sparse_t(b, 2).emplace<Tensor>(output_shape);
    }

    for (int64 empty_b = last_nonempty_group + 1; empty_b < N; ++empty_b) {
      serialize_empty_element(empty_b);
    }

    return Status::OK();
  }
};

template <typename T, typename U>
class SerializeManySparseOp : public OpKernel {
 public:
  explicit SerializeManySparseOp(OpKernelConstruction* context)
      : OpKernel(context) {}

  void Compute(OpKernelContext* context) override {
    const Tensor* input_indices;
    const Tensor* input_values;
    const Tensor* input_shape;
    OP_REQUIRES_OK(context, context->input("sparse_indices", &input_indices));
    OP_REQUIRES_OK(context, context->input("sparse_values", &input_values));
    OP_REQUIRES_OK(context, context->input("sparse_shape", &input_shape));
    OP_REQUIRES(context, TensorShapeUtils::IsMatrix(input_indices->shape()),
                errors::InvalidArgument(
                    "Input indices should be a matrix but received shape ",
                    input_indices->shape().DebugString()));

    OP_REQUIRES(context, TensorShapeUtils::IsVector(input_values->shape()),
                errors::InvalidArgument(
                    "Input values should be a vector but received shape ",
                    input_values->shape().DebugString()));

    OP_REQUIRES(context, TensorShapeUtils::IsVector(input_shape->shape()),
                errors::InvalidArgument(
                    "Input shape should be a vector but received shape ",
                    input_shape->shape().DebugString()));

    int rank = input_shape->NumElements();

    OP_REQUIRES(
        context, rank > 1,
        errors::InvalidArgument(
            "Rank of input SparseTensor should be > 1, but saw rank: ", rank));

    TensorShape tensor_input_shape(input_shape->vec<int64>());
    gtl::InlinedVector<int64, 8> std_order(rank);
    std::iota(std_order.begin(), std_order.end(), 0);
    SparseTensor input_st;
    OP_REQUIRES_OK(context, SparseTensor::Create(*input_indices, *input_values,
                                                 tensor_input_shape, std_order,
                                                 &input_st));

    auto input_shape_t = input_shape->vec<int64>();
    const int64 N = input_shape_t(0);

    Tensor* serialized_sparse;
    OP_REQUIRES_OK(context,
                   context->allocate_output(0, {N, 3}, &serialized_sparse));

    OP_REQUIRES_OK(context, input_st.IndicesValid());

    Tensor output_shape(DT_INT64, {rank - 1});
    auto output_shape_t = output_shape.vec<int64>();
    for (int d = 1; d < rank; d++) output_shape_t(d - 1) = input_shape_t(d);

    // Get groups by minibatch dimension
    sparse::GroupIterable minibatch = input_st.group({0});

    OP_REQUIRES_OK(context, SerializeGroups<T, U>()(&minibatch, output_shape, N,
                                                    rank, serialized_sparse));
  }
};

#define REGISTER_KERNELS(type)                                      \
  REGISTER_KERNEL_BUILDER(Name("SerializeManySparse")               \
                              .Device(DEVICE_CPU)                   \
                              .TypeConstraint<type>("T")            \
                              .TypeConstraint<tstring>("out_type"), \
                          SerializeManySparseOp<type, tstring>)

TF_CALL_ALL_TYPES(REGISTER_KERNELS);
#undef REGISTER_KERNELS

#define REGISTER_KERNELS(type)                                      \
  REGISTER_KERNEL_BUILDER(Name("SerializeManySparse")               \
                              .Device(DEVICE_CPU)                   \
                              .TypeConstraint<type>("T")            \
                              .TypeConstraint<Variant>("out_type"), \
                          SerializeManySparseOp<type, Variant>)

TF_CALL_ALL_TYPES(REGISTER_KERNELS);
#undef REGISTER_KERNELS

}  // namespace

}  // namespace tensorflow
<|endoftext|>