<commit_before>//..............................................................................
//
//  This file is part of the Jancy toolkit.
//
//  Jancy is distributed under the MIT license.
//  For details see accompanying license.txt file,
//  the public copy of which is also available at:
//  http://tibbo.com/downloads/archive/jancy/license.txt
//
//..............................................................................

#include "pch.h"
#include "jnc_ct_Function.h"
#include "jnc_ct_Module.h"
#include "jnc_ct_ClassType.h"
#include "jnc_ct_Parser.llk.h"

namespace jnc {
namespace ct {

//..............................................................................

Function::Function ()
{
	m_itemKind = ModuleItemKind_Function;
	m_functionKind = FunctionKind_Undefined;
	m_type = NULL;
	m_castOpType = NULL;
	m_thisArgType = NULL;
	m_thisType = NULL;
	m_thisArgDelta = 0;
	m_thisArgTypeFlags = 0;
	m_virtualOriginClassType = NULL;
	m_property = NULL;
	m_extensionNamespace = NULL;
	m_classVTableIndex = -1;
	m_allocaBlock = NULL;
	m_prologueBlock = NULL;
	m_scope = NULL;
	m_llvmFunction = NULL;
	m_machineCode = NULL;
}

bool
Function::setBody (sl::BoxList <Token>* tokenList)
{
	if (!m_body.isEmpty ())
	{
		err::setFormatStringError ("'%s' already has a body", m_tag.sz ());
		return false;
	}

	if (m_storageKind == StorageKind_Abstract)
	{
		err::setFormatStringError ("'%s' is abstract and hence cannot have a body", m_tag.sz ());
		return false;
	}

	sl::takeOver (&m_body, tokenList);
	m_module->markForCompile (this);
	return true;
}

void
Function::addUsingSet (Namespace* anchorNamespace)
{
	NamespaceMgr* importNamespaceMgr = m_module->getCompileState () < ModuleCompileState_Linked ?
		&m_module->m_namespaceMgr :
		NULL;

	for (Namespace* nspace = anchorNamespace; nspace; nspace = nspace->getParentNamespace ())
		m_usingSet.append (importNamespaceMgr, nspace->getUsingSet ());
}

void
Function::addUsingSet (UsingSet* usingSet)
{
	NamespaceMgr* importNamespaceMgr = m_module->getCompileState () < ModuleCompileState_Linked ?
		&m_module->m_namespaceMgr :
		NULL;

	m_usingSet.append (NULL, usingSet);
}

llvm::Function*
Function::getLlvmFunction ()
{
	if (m_llvmFunction)
		return m_llvmFunction;

	sl::String llvmName;
	if (m_module->getCompileFlags () & ModuleCompileFlag_McJit)
	{
		llvmName = "?"; // as to avoid linking conflicts
		llvmName += m_tag;
	}
	else
	{
		llvmName = m_tag;
	}

	m_llvmFunction = m_type->getCallConv ()->createLlvmFunction (m_type, llvmName);
	return m_llvmFunction;
}

llvm::DISubprogram_vn
Function::getLlvmDiSubprogram ()
{
	if (m_llvmDiSubprogram)
		return m_llvmDiSubprogram;

	m_llvmDiSubprogram = m_module->m_llvmDiBuilder.createFunction (this);
	return m_llvmDiSubprogram;
}

void
Function::convertToMemberMethod (DerivableType* parentType)
{
	ASSERT (m_typeOverload.getOverloadCount () == 1);

	m_parentNamespace = parentType;
	m_type = parentType->getMemberMethodType (m_type, m_thisArgTypeFlags);
	m_typeOverload = m_type;

	ASSERT (!m_type->getArgArray ().isEmpty ());
	m_thisArgType = m_type->getArgArray () [0]->getType ();
	m_thisType = m_thisArgType;
}

size_t
Function::addOverload (Function* function)
{
	size_t overloadIdx = m_typeOverload.addOverload (function->m_type);
	if (overloadIdx == -1)
		return -1;

	m_overloadArray.append (function);
	ASSERT (overloadIdx == m_overloadArray.getCount ());
	return overloadIdx;
}

void
Function::addTlsVariable (Variable* variable)
{
	llvm::AllocaInst* llvmAlloca = (llvm::AllocaInst*) variable->getLlvmValue ();
	ASSERT (llvmAlloca && llvm::isa <llvm::AllocaInst> (*llvmAlloca));

	TlsVariable tlsVariable;
	tlsVariable.m_variable = variable;
	tlsVariable.m_llvmAlloca = llvmAlloca;
	m_tlsVariableArray.append (tlsVariable);
}

bool
Function::compile ()
{
	bool result;

	ASSERT (!m_body.isEmpty () || !m_initializer.isEmpty ()); // otherwise what are we doing here?
	ASSERT (!m_prologueBlock);

	if (m_parentUnit)
		m_module->m_unitMgr.setCurrentUnit (m_parentUnit);

	if (!m_body.isEmpty ())
	{
		// a function with a body

		Token::Pos beginPos = m_body.getHead ()->m_pos;
		Token::Pos endPos = m_body.getTail ()->m_pos;

		m_module->m_functionMgr.prologue (this, beginPos);
		m_module->m_namespaceMgr.getCurrentScope ()->getUsingSet ()->append (NULL, &m_usingSet);

		result = m_functionKind == FunctionKind_Constructor ?
			compileConstructorBody () :
			compileNormalBody ();

		if (!result)
			return false;

		m_module->m_namespaceMgr.setSourcePos (endPos);
		return m_module->m_functionMgr.epilogue ();
	}

	// redirected function

	Parser parser (m_module);
	result = parser.parseTokenList (SymbolKind_qualified_name_save_name, m_initializer);
	if (!result)
		return false;

	ModuleItem* item = m_parentNamespace->findItemTraverse (parser.m_qualifiedName);
	if (!item)
	{
		err::setFormatStringError ("name '%s' is not found", parser.m_qualifiedName.getFullName ().sz ());
		return false;
	}

	if (item->getItemKind () != ModuleItemKind_Function)
	{
		err::setFormatStringError ("'%s' is not function", parser.m_qualifiedName.getFullName ().sz ());
		return false;
	}

	Function* targetFunction = (Function*) item;

	if (m_functionKind < FunctionKind_PreConstructor || m_functionKind > FunctionKind_StaticDestructor)
	{
		Function* targetOverload = targetFunction->findOverload (m_type);
		if (targetOverload)
		{
			// can re-use the same function directly

			result = targetOverload->m_llvmFunction != NULL || targetOverload->compile ();
			if (!result)
				return false;

			m_llvmFunction = targetOverload->m_llvmFunction;
			return true;
		}
	}

	// have to make a call because of either conversion or extra prologue/epilogue actions (such as in constructor)

	size_t argCount = m_type->getArgArray ().getCount ();

	char buffer [256];
	sl::Array <Value> argValueArray (ref::BufKind_Stack, buffer, sizeof (buffer));
	argValueArray.setCount (argCount);

	m_module->m_functionMgr.internalPrologue (this, argValueArray, argCount);

	sl::BoxList <Value> argValueList;
	for (size_t i = 0; i < argCount; i++)
		argValueList.insertTail (argValueArray [i]);

	Value resultValue;
	result = m_module->m_operatorMgr.callOperator (targetFunction, &argValueList, &resultValue);
	if (!result)
		return false;

	if (m_type->getTypeKind () != TypeKind_Void)
	{
		result = m_module->m_controlFlowMgr.ret (resultValue);
		if (!result)
			return false;
	}

	m_module->m_functionMgr.internalEpilogue ();
	return true;
}

bool
Function::compileConstructorBody ()
{
	Parser parser (m_module);
	parser.m_stage = Parser::Stage_Pass2;

	NamespaceKind namespaceKind = m_parentNamespace->getNamespaceKind ();
	ASSERT (namespaceKind == NamespaceKind_Type || namespaceKind == NamespaceKind_Property);

	if (namespaceKind == NamespaceKind_Type)
		parser.m_constructorType = (DerivableType*) m_parentNamespace;
	else
		parser.m_constructorProperty = (Property*) m_parentNamespace;

	return parser.parseTokenList (SymbolKind_constructor_compound_stmt, m_body, true);
}

bool
Function::compileNormalBody ()
{
	Parser parser (m_module);
	parser.m_stage = Parser::Stage_Pass2;

	return parser.parseTokenList (SymbolKind_compound_stmt, m_body, true);
}

bool
Function::generateDocumentation (
	const sl::StringRef& outputDir,
	sl::String* itemXml,
	sl::String* indexXml
	)
{
	DoxyBlock* doxyBlock = getDoxyBlock ();

	itemXml->format ("<memberdef kind='function' id='%s'", doxyBlock->getRefId ().sz ());

	if (m_accessKind != AccessKind_Public)
		itemXml->appendFormat (" prot='%s'", getAccessKindString (m_accessKind));

	if (m_storageKind == StorageKind_Static)
		itemXml->append (" static='yes'");

	if (isMember () && (m_thisArgTypeFlags & PtrTypeFlag_Const))
		itemXml->append (" const='yes'");

	if (isVirtual ())
		itemXml->appendFormat (" virt='%s'", getStorageKindString (m_storageKind));

	itemXml->appendFormat (">\n<functionkind>%s</functionkind>\n", getFunctionKindString (m_functionKind));
	itemXml->appendFormat ("<name>%s</name>\n", !m_name.isEmpty () ? m_name.sz () : getFunctionKindString (m_functionKind));

	itemXml->append (m_type->getDoxyTypeString ());
	itemXml->append (doxyBlock->getImportString ());
	itemXml->append (doxyBlock->getDescriptionString ());
	itemXml->append (getDoxyLocationString ());
	itemXml->append ("</memberdef>\n");

	sl::String overloadXml;

	size_t overloadCount = m_overloadArray.getCount ();
	for (size_t i = 0; i < overloadCount; i++)
	{
		Function* overload = m_overloadArray [i];
		overload->generateDocumentation (outputDir, &overloadXml, indexXml);
		itemXml->append ('\n');
		itemXml->append (overloadXml);
	}

	return true;
}

//..............................................................................

} // namespace ct
} // namespace jnc
<commit_msg>[jnc_ct] typo fix in Function::addUsingSet<commit_after>//..............................................................................
//
//  This file is part of the Jancy toolkit.
//
//  Jancy is distributed under the MIT license.
//  For details see accompanying license.txt file,
//  the public copy of which is also available at:
//  http://tibbo.com/downloads/archive/jancy/license.txt
//
//..............................................................................

#include "pch.h"
#include "jnc_ct_Function.h"
#include "jnc_ct_Module.h"
#include "jnc_ct_ClassType.h"
#include "jnc_ct_Parser.llk.h"

namespace jnc {
namespace ct {

//..............................................................................

Function::Function ()
{
	m_itemKind = ModuleItemKind_Function;
	m_functionKind = FunctionKind_Undefined;
	m_type = NULL;
	m_castOpType = NULL;
	m_thisArgType = NULL;
	m_thisType = NULL;
	m_thisArgDelta = 0;
	m_thisArgTypeFlags = 0;
	m_virtualOriginClassType = NULL;
	m_property = NULL;
	m_extensionNamespace = NULL;
	m_classVTableIndex = -1;
	m_allocaBlock = NULL;
	m_prologueBlock = NULL;
	m_scope = NULL;
	m_llvmFunction = NULL;
	m_machineCode = NULL;
}

bool
Function::setBody (sl::BoxList <Token>* tokenList)
{
	if (!m_body.isEmpty ())
	{
		err::setFormatStringError ("'%s' already has a body", m_tag.sz ());
		return false;
	}

	if (m_storageKind == StorageKind_Abstract)
	{
		err::setFormatStringError ("'%s' is abstract and hence cannot have a body", m_tag.sz ());
		return false;
	}

	sl::takeOver (&m_body, tokenList);
	m_module->markForCompile (this);
	return true;
}

void
Function::addUsingSet (Namespace* anchorNamespace)
{
	NamespaceMgr* importNamespaceMgr = m_module->getCompileState () < ModuleCompileState_Linked ?
		&m_module->m_namespaceMgr :
		NULL;

	for (Namespace* nspace = anchorNamespace; nspace; nspace = nspace->getParentNamespace ())
		m_usingSet.append (importNamespaceMgr, nspace->getUsingSet ());
}

void
Function::addUsingSet (UsingSet* usingSet)
{
	NamespaceMgr* importNamespaceMgr = m_module->getCompileState () < ModuleCompileState_Linked ?
		&m_module->m_namespaceMgr :
		NULL;

	m_usingSet.append (importNamespaceMgr, usingSet);
}

llvm::Function*
Function::getLlvmFunction ()
{
	if (m_llvmFunction)
		return m_llvmFunction;

	sl::String llvmName;
	if (m_module->getCompileFlags () & ModuleCompileFlag_McJit)
	{
		llvmName = "?"; // as to avoid linking conflicts
		llvmName += m_tag;
	}
	else
	{
		llvmName = m_tag;
	}

	m_llvmFunction = m_type->getCallConv ()->createLlvmFunction (m_type, llvmName);
	return m_llvmFunction;
}

llvm::DISubprogram_vn
Function::getLlvmDiSubprogram ()
{
	if (m_llvmDiSubprogram)
		return m_llvmDiSubprogram;

	m_llvmDiSubprogram = m_module->m_llvmDiBuilder.createFunction (this);
	return m_llvmDiSubprogram;
}

void
Function::convertToMemberMethod (DerivableType* parentType)
{
	ASSERT (m_typeOverload.getOverloadCount () == 1);

	m_parentNamespace = parentType;
	m_type = parentType->getMemberMethodType (m_type, m_thisArgTypeFlags);
	m_typeOverload = m_type;

	ASSERT (!m_type->getArgArray ().isEmpty ());
	m_thisArgType = m_type->getArgArray () [0]->getType ();
	m_thisType = m_thisArgType;
}

size_t
Function::addOverload (Function* function)
{
	size_t overloadIdx = m_typeOverload.addOverload (function->m_type);
	if (overloadIdx == -1)
		return -1;

	m_overloadArray.append (function);
	ASSERT (overloadIdx == m_overloadArray.getCount ());
	return overloadIdx;
}

void
Function::addTlsVariable (Variable* variable)
{
	llvm::AllocaInst* llvmAlloca = (llvm::AllocaInst*) variable->getLlvmValue ();
	ASSERT (llvmAlloca && llvm::isa <llvm::AllocaInst> (*llvmAlloca));

	TlsVariable tlsVariable;
	tlsVariable.m_variable = variable;
	tlsVariable.m_llvmAlloca = llvmAlloca;
	m_tlsVariableArray.append (tlsVariable);
}

bool
Function::compile ()
{
	bool result;

	ASSERT (!m_body.isEmpty () || !m_initializer.isEmpty ()); // otherwise what are we doing here?
	ASSERT (!m_prologueBlock);

	if (m_parentUnit)
		m_module->m_unitMgr.setCurrentUnit (m_parentUnit);

	if (!m_body.isEmpty ())
	{
		// a function with a body

		Token::Pos beginPos = m_body.getHead ()->m_pos;
		Token::Pos endPos = m_body.getTail ()->m_pos;

		m_module->m_functionMgr.prologue (this, beginPos);
		m_module->m_namespaceMgr.getCurrentScope ()->getUsingSet ()->append (NULL, &m_usingSet);

		result = m_functionKind == FunctionKind_Constructor ?
			compileConstructorBody () :
			compileNormalBody ();

		if (!result)
			return false;

		m_module->m_namespaceMgr.setSourcePos (endPos);
		return m_module->m_functionMgr.epilogue ();
	}

	// redirected function

	Parser parser (m_module);
	result = parser.parseTokenList (SymbolKind_qualified_name_save_name, m_initializer);
	if (!result)
		return false;

	ModuleItem* item = m_parentNamespace->findItemTraverse (parser.m_qualifiedName);
	if (!item)
	{
		err::setFormatStringError ("name '%s' is not found", parser.m_qualifiedName.getFullName ().sz ());
		return false;
	}

	if (item->getItemKind () != ModuleItemKind_Function)
	{
		err::setFormatStringError ("'%s' is not function", parser.m_qualifiedName.getFullName ().sz ());
		return false;
	}

	Function* targetFunction = (Function*) item;

	if (m_functionKind < FunctionKind_PreConstructor || m_functionKind > FunctionKind_StaticDestructor)
	{
		Function* targetOverload = targetFunction->findOverload (m_type);
		if (targetOverload)
		{
			// can re-use the same function directly

			result = targetOverload->m_llvmFunction != NULL || targetOverload->compile ();
			if (!result)
				return false;

			m_llvmFunction = targetOverload->m_llvmFunction;
			return true;
		}
	}

	// have to make a call because of either conversion or extra prologue/epilogue actions (such as in constructor)

	size_t argCount = m_type->getArgArray ().getCount ();

	char buffer [256];
	sl::Array <Value> argValueArray (ref::BufKind_Stack, buffer, sizeof (buffer));
	argValueArray.setCount (argCount);

	m_module->m_functionMgr.internalPrologue (this, argValueArray, argCount);

	sl::BoxList <Value> argValueList;
	for (size_t i = 0; i < argCount; i++)
		argValueList.insertTail (argValueArray [i]);

	Value resultValue;
	result = m_module->m_operatorMgr.callOperator (targetFunction, &argValueList, &resultValue);
	if (!result)
		return false;

	if (m_type->getTypeKind () != TypeKind_Void)
	{
		result = m_module->m_controlFlowMgr.ret (resultValue);
		if (!result)
			return false;
	}

	m_module->m_functionMgr.internalEpilogue ();
	return true;
}

bool
Function::compileConstructorBody ()
{
	Parser parser (m_module);
	parser.m_stage = Parser::Stage_Pass2;

	NamespaceKind namespaceKind = m_parentNamespace->getNamespaceKind ();
	ASSERT (namespaceKind == NamespaceKind_Type || namespaceKind == NamespaceKind_Property);

	if (namespaceKind == NamespaceKind_Type)
		parser.m_constructorType = (DerivableType*) m_parentNamespace;
	else
		parser.m_constructorProperty = (Property*) m_parentNamespace;

	return parser.parseTokenList (SymbolKind_constructor_compound_stmt, m_body, true);
}

bool
Function::compileNormalBody ()
{
	Parser parser (m_module);
	parser.m_stage = Parser::Stage_Pass2;

	return parser.parseTokenList (SymbolKind_compound_stmt, m_body, true);
}

bool
Function::generateDocumentation (
	const sl::StringRef& outputDir,
	sl::String* itemXml,
	sl::String* indexXml
	)
{
	DoxyBlock* doxyBlock = getDoxyBlock ();

	itemXml->format ("<memberdef kind='function' id='%s'", doxyBlock->getRefId ().sz ());

	if (m_accessKind != AccessKind_Public)
		itemXml->appendFormat (" prot='%s'", getAccessKindString (m_accessKind));

	if (m_storageKind == StorageKind_Static)
		itemXml->append (" static='yes'");

	if (isMember () && (m_thisArgTypeFlags & PtrTypeFlag_Const))
		itemXml->append (" const='yes'");

	if (isVirtual ())
		itemXml->appendFormat (" virt='%s'", getStorageKindString (m_storageKind));

	itemXml->appendFormat (">\n<functionkind>%s</functionkind>\n", getFunctionKindString (m_functionKind));
	itemXml->appendFormat ("<name>%s</name>\n", !m_name.isEmpty () ? m_name.sz () : getFunctionKindString (m_functionKind));

	itemXml->append (m_type->getDoxyTypeString ());
	itemXml->append (doxyBlock->getImportString ());
	itemXml->append (doxyBlock->getDescriptionString ());
	itemXml->append (getDoxyLocationString ());
	itemXml->append ("</memberdef>\n");

	sl::String overloadXml;

	size_t overloadCount = m_overloadArray.getCount ();
	for (size_t i = 0; i < overloadCount; i++)
	{
		Function* overload = m_overloadArray [i];
		overload->generateDocumentation (outputDir, &overloadXml, indexXml);
		itemXml->append ('\n');
		itemXml->append (overloadXml);
	}

	return true;
}

//..............................................................................

} // namespace ct
} // namespace jnc
<|endoftext|>


<commit_before>#include "formulation/scalar/cfem_diffusion.h"

namespace bart {

namespace formulation {

namespace scalar {

template<int dim>
CFEM_Diffusion<dim>::CFEM_Diffusion(std::shared_ptr<domain::FiniteElementI<dim>> finite_element,
                                    std::shared_ptr<data::CrossSections> cross_sections)
    : finite_element_(finite_element),
      cross_sections_(cross_sections),
      cell_degrees_of_freedom_(finite_element->dofs_per_cell()),
      cell_quadrature_points_(finite_element->n_cell_quad_pts()),
      face_quadrature_points_(finite_element->n_face_quad_pts()) {}

template <int dim>
typename CFEM_Diffusion<dim>::InitializationToken
CFEM_Diffusion<dim>::Precalculate(const CellPtr& cell_ptr) {

  finite_element_->SetCell(cell_ptr);

  for (int q = 0; q < cell_quadrature_points_; ++q) {
    Matrix gradient_squared(cell_degrees_of_freedom_,
                            cell_degrees_of_freedom_);
    Matrix shape_squared(cell_degrees_of_freedom_,
                         cell_degrees_of_freedom_);

    for (int i = 0; i < cell_degrees_of_freedom_; ++i) {
      for (int j = 0; j < cell_degrees_of_freedom_; ++j) {
        shape_squared(i, j) =
            finite_element_->ShapeValue(i, q) *
            finite_element_->ShapeValue(j, q);
        gradient_squared(i, j) =
            finite_element_->ShapeGradient(i, q) *
            finite_element_->ShapeGradient(j, q);
      }
    }
    shape_squared_.push_back(shape_squared);
    gradient_squared_.push_back(gradient_squared);
  }
  InitializationToken token;
  return token;
}

template <int dim>
void CFEM_Diffusion<dim>::FillCellStreamingTerm(Matrix& to_fill,
                                                const InitializationToken,
                                                const CellPtr& cell_ptr,
                                                const MaterialID material_id,
                                                const GroupNumber group) const {

  finite_element_->SetCell(cell_ptr);

  const double diffusion_coef =
      cross_sections_->diffusion_coef.at(material_id)[group];

  for (int q = 0; q < cell_quadrature_points_; ++q) {
    double jacobian = finite_element_->Jacobian(q);
    for (int i = 0; i < cell_degrees_of_freedom_; ++i) {
      for (int j = 0; j < cell_degrees_of_freedom_; ++j) {
        to_fill(i, j) += diffusion_coef * gradient_squared_[q](i, j) *jacobian;
      }
    }
  }

}

template <int dim>
void CFEM_Diffusion<dim>::FillCellCollisionTerm(Matrix& to_fill,
                                                const InitializationToken,
                                                const CellPtr& cell_ptr,
                                                const MaterialID material_id,
                                                const GroupNumber group) const {

  finite_element_->SetCell(cell_ptr);

  const double sigma_t = cross_sections_->sigma_t.at(material_id)[group];
  const double sigma_s = cross_sections_->sigma_s.at(material_id)(group, group);
  double sigma_r = sigma_t - sigma_s;

  for (int q = 0; q < cell_quadrature_points_; ++q) {
    const double jacobian = finite_element_->Jacobian(q);
    for (int i = 0; i < cell_degrees_of_freedom_; ++i) {
      for (int j = 0; j < cell_degrees_of_freedom_; ++j) {
        to_fill(i, j) += sigma_r * shape_squared_[q](i, j) * jacobian;
      }
    }
  }
}

template <int dim>
void CFEM_Diffusion<dim>::FillBoundaryTerm(Matrix& to_fill,
                                           const InitializationToken,
                                           const CellPtr& cell_ptr,
                                           const FaceNumber face_number,
                                           const BoundaryType boundary_type) const {
  if (boundary_type == BoundaryType::kVacuum) {
    finite_element_->SetFace(cell_ptr, face_number);

    for (int q = 0; q < cell_quadrature_points_; ++q) {
      const double jacobian = finite_element_->Jacobian(q);
      for (int i = 0; i < cell_degrees_of_freedom_; ++i) {
        for (int j = 0; j < cell_degrees_of_freedom_; ++j) {
          to_fill(i, j) += 0.5 * shape_squared_[q](i, j) * jacobian;
        }
      }
    }
  }
}

template <int dim>
void CFEM_Diffusion<dim>::FillCellFixedSource(Vector& to_fill,
                                              const CellPtr& cell_ptr,
                                              const MaterialID material_id,
                                              const GroupNumber group) const {

  finite_element_->SetCell(cell_ptr);

  const double q{cross_sections_->q.at(material_id)[group]};
  std::vector<double> cell_fixed_source(cell_quadrature_points_, q);

  for (int q = 0; q < cell_quadrature_points_; ++q) {
    const double jacobian = finite_element_->Jacobian(q);
    for (int i = 0; i < cell_degrees_of_freedom_; ++i) {
      to_fill[i] += finite_element_->ShapeValue(i, q) * jacobian;
    }
  }
}

template <int dim>
void CFEM_Diffusion<dim>::FillCellFissionSource(
    Vector& to_fill,
    const CellPtr& cell_ptr,
    const MaterialID material_id,
    const GroupNumber group,
    const double k_effective,
    const data::MomentVector& in_group_moment,
    const data::MomentsMap& group_moments) const {

  if (cross_sections_->is_material_fissile.at(material_id)) {
    finite_element_->SetCell(cell_ptr);

    std::vector<double> fission_source_at_quad_points(cell_quadrature_points_);

    // Get fission source contribution from each group at each quadrature point
    for (const auto& moment_pair : group_moments) {
      auto &[index, moment] = moment_pair;
      int group_in = index[0];
      if (index[1] == 0 && index[2] == 0) {
        std::vector<double> scalar_flux_at_quad_points(cell_quadrature_points_);

        if (group_in == group) {
          scalar_flux_at_quad_points =
              finite_element_->ValueAtQuadrature(in_group_moment);
        } else {
          scalar_flux_at_quad_points =
              finite_element_->ValueAtQuadrature(moment);
        }

        auto fission_transfer =
            cross_sections_->fiss_transfer.at(material_id)(group, group_in);

        for (int q = 0; q < cell_quadrature_points_; ++q)
          fission_source_at_quad_points[q] +=
              fission_transfer * scalar_flux_at_quad_points[q];
      }
    }

    // Integrate for each degree of freedom
    for (int q = 0; q < cell_quadrature_points_; ++q) {
      fission_source_at_quad_points[q] *=
          finite_element_->Jacobian(q) / k_effective;

      for (int i = 0; i < cell_degrees_of_freedom_; ++i)
        to_fill(i) +=
            finite_element_->ShapeValue(i, q) * fission_source_at_quad_points[q];

    }
  }
}

template <int dim>
void CFEM_Diffusion<dim>::FillCellScatteringSource(
      Vector& to_fill,
      const CellPtr& cell_ptr,
      const MaterialID material_id,
      const GroupNumber group,
      const data::MomentVector& in_group_moment,
      const data::MomentsMap& group_moments) const {
  finite_element_->SetCell(cell_ptr);

  std::vector<double> scattering_source_at_quad_points(cell_quadrature_points_);

  // Get fission source contribution from each group at each quadrature point
  for (const auto& moment_pair : group_moments) {
    auto &[index, moment] = moment_pair;
    int group_in = index[0];
    if (index[1] == 0 && index[2] == 0) {
      std::vector<double> scalar_flux_at_quad_points(cell_quadrature_points_);

      if (group_in == group) {
        scalar_flux_at_quad_points =
            finite_element_->ValueAtQuadrature(in_group_moment);
      } else {
        scalar_flux_at_quad_points =
            finite_element_->ValueAtQuadrature(moment);
      }

      const auto sigma_s =
          cross_sections_->sigma_s.at(material_id)(group, group_in);

      for (int q = 0; q < cell_quadrature_points_; ++q)
        scattering_source_at_quad_points[q] +=
            sigma_s * scalar_flux_at_quad_points[q];
    }
  }

  // Integrate for each degree of freedom
  for (int q = 0; q < cell_quadrature_points_; ++q) {
    scattering_source_at_quad_points[q] *= finite_element_->Jacobian(q);

    for (int i = 0; i < cell_degrees_of_freedom_; ++i)
      to_fill(i) +=
          finite_element_->ShapeValue(i, q) * scattering_source_at_quad_points[q];

  }
}

template class CFEM_Diffusion<1>;
template class CFEM_Diffusion<2>;
template class CFEM_Diffusion<3>;

} // namespace scalar

} // namespace formulation

} // namespace bart<commit_msg>moved all material_id queries in CFEM_Diffusion into the function, removing the need for the argument<commit_after>#include "formulation/scalar/cfem_diffusion.h"

namespace bart {

namespace formulation {

namespace scalar {

template<int dim>
CFEM_Diffusion<dim>::CFEM_Diffusion(std::shared_ptr<domain::FiniteElementI<dim>> finite_element,
                                    std::shared_ptr<data::CrossSections> cross_sections)
    : finite_element_(finite_element),
      cross_sections_(cross_sections),
      cell_degrees_of_freedom_(finite_element->dofs_per_cell()),
      cell_quadrature_points_(finite_element->n_cell_quad_pts()),
      face_quadrature_points_(finite_element->n_face_quad_pts()) {}

template <int dim>
typename CFEM_Diffusion<dim>::InitializationToken
CFEM_Diffusion<dim>::Precalculate(const CellPtr& cell_ptr) {

  finite_element_->SetCell(cell_ptr);

  for (int q = 0; q < cell_quadrature_points_; ++q) {
    Matrix gradient_squared(cell_degrees_of_freedom_,
                            cell_degrees_of_freedom_);
    Matrix shape_squared(cell_degrees_of_freedom_,
                         cell_degrees_of_freedom_);

    for (int i = 0; i < cell_degrees_of_freedom_; ++i) {
      for (int j = 0; j < cell_degrees_of_freedom_; ++j) {
        shape_squared(i, j) =
            finite_element_->ShapeValue(i, q) *
            finite_element_->ShapeValue(j, q);
        gradient_squared(i, j) =
            finite_element_->ShapeGradient(i, q) *
            finite_element_->ShapeGradient(j, q);
      }
    }
    shape_squared_.push_back(shape_squared);
    gradient_squared_.push_back(gradient_squared);
  }
  InitializationToken token;
  return token;
}

template <int dim>
void CFEM_Diffusion<dim>::FillCellStreamingTerm(Matrix& to_fill,
                                                const InitializationToken,
                                                const CellPtr& cell_ptr,
                                                const MaterialID,
                                                const GroupNumber group) const {

  finite_element_->SetCell(cell_ptr);
  int material_id = cell_ptr->material_id();

  const double diffusion_coef =
      cross_sections_->diffusion_coef.at(material_id)[group];

  for (int q = 0; q < cell_quadrature_points_; ++q) {
    double jacobian = finite_element_->Jacobian(q);
    for (int i = 0; i < cell_degrees_of_freedom_; ++i) {
      for (int j = 0; j < cell_degrees_of_freedom_; ++j) {
        to_fill(i, j) += diffusion_coef * gradient_squared_[q](i, j) *jacobian;
      }
    }
  }

}

template <int dim>
void CFEM_Diffusion<dim>::FillCellCollisionTerm(Matrix& to_fill,
                                                const InitializationToken,
                                                const CellPtr& cell_ptr,
                                                const MaterialID,
                                                const GroupNumber group) const {

  finite_element_->SetCell(cell_ptr);
  int material_id = cell_ptr->material_id();

  const double sigma_t = cross_sections_->sigma_t.at(material_id)[group];
  const double sigma_s = cross_sections_->sigma_s.at(material_id)(group, group);
  double sigma_r = sigma_t - sigma_s;

  for (int q = 0; q < cell_quadrature_points_; ++q) {
    const double jacobian = finite_element_->Jacobian(q);
    for (int i = 0; i < cell_degrees_of_freedom_; ++i) {
      for (int j = 0; j < cell_degrees_of_freedom_; ++j) {
        to_fill(i, j) += sigma_r * shape_squared_[q](i, j) * jacobian;
      }
    }
  }
}

template <int dim>
void CFEM_Diffusion<dim>::FillBoundaryTerm(Matrix& to_fill,
                                           const InitializationToken,
                                           const CellPtr& cell_ptr,
                                           const FaceNumber face_number,
                                           const BoundaryType boundary_type) const {
  if (boundary_type == BoundaryType::kVacuum) {
    finite_element_->SetFace(cell_ptr, face_number);

    for (int q = 0; q < cell_quadrature_points_; ++q) {
      const double jacobian = finite_element_->Jacobian(q);
      for (int i = 0; i < cell_degrees_of_freedom_; ++i) {
        for (int j = 0; j < cell_degrees_of_freedom_; ++j) {
          to_fill(i, j) += 0.5 * shape_squared_[q](i, j) * jacobian;
        }
      }
    }
  }
}

template <int dim>
void CFEM_Diffusion<dim>::FillCellFixedSource(Vector& to_fill,
                                              const CellPtr& cell_ptr,
                                              const MaterialID,
                                              const GroupNumber group) const {

  finite_element_->SetCell(cell_ptr);
  int material_id = cell_ptr->material_id();

  const double q{cross_sections_->q.at(material_id)[group]};
  std::vector<double> cell_fixed_source(cell_quadrature_points_, q);

  for (int q = 0; q < cell_quadrature_points_; ++q) {
    const double jacobian = finite_element_->Jacobian(q);
    for (int i = 0; i < cell_degrees_of_freedom_; ++i) {
      to_fill[i] += finite_element_->ShapeValue(i, q) * jacobian;
    }
  }
}

template <int dim>
void CFEM_Diffusion<dim>::FillCellFissionSource(
    Vector& to_fill,
    const CellPtr& cell_ptr,
    const MaterialID,
    const GroupNumber group,
    const double k_effective,
    const data::MomentVector& in_group_moment,
    const data::MomentsMap& group_moments) const {

  int material_id = cell_ptr->material_id();
  if (cross_sections_->is_material_fissile.at(material_id)) {
    finite_element_->SetCell(cell_ptr);

    std::vector<double> fission_source_at_quad_points(cell_quadrature_points_);

    // Get fission source contribution from each group at each quadrature point
    for (const auto& moment_pair : group_moments) {
      auto &[index, moment] = moment_pair;
      int group_in = index[0];
      if (index[1] == 0 && index[2] == 0) {
        std::vector<double> scalar_flux_at_quad_points(cell_quadrature_points_);

        if (group_in == group) {
          scalar_flux_at_quad_points =
              finite_element_->ValueAtQuadrature(in_group_moment);
        } else {
          scalar_flux_at_quad_points =
              finite_element_->ValueAtQuadrature(moment);
        }

        auto fission_transfer =
            cross_sections_->fiss_transfer.at(material_id)(group, group_in);

        for (int q = 0; q < cell_quadrature_points_; ++q)
          fission_source_at_quad_points[q] +=
              fission_transfer * scalar_flux_at_quad_points[q];
      }
    }

    // Integrate for each degree of freedom
    for (int q = 0; q < cell_quadrature_points_; ++q) {
      fission_source_at_quad_points[q] *=
          finite_element_->Jacobian(q) / k_effective;

      for (int i = 0; i < cell_degrees_of_freedom_; ++i)
        to_fill(i) +=
            finite_element_->ShapeValue(i, q) * fission_source_at_quad_points[q];

    }
  }
}

template <int dim>
void CFEM_Diffusion<dim>::FillCellScatteringSource(
      Vector& to_fill,
      const CellPtr& cell_ptr,
      const MaterialID,
      const GroupNumber group,
      const data::MomentVector& in_group_moment,
      const data::MomentsMap& group_moments) const {

  finite_element_->SetCell(cell_ptr);
  int material_id = cell_ptr->material_id();

  std::vector<double> scattering_source_at_quad_points(cell_quadrature_points_);

  // Get fission source contribution from each group at each quadrature point
  for (const auto& moment_pair : group_moments) {
    auto &[index, moment] = moment_pair;
    int group_in = index[0];
    if (index[1] == 0 && index[2] == 0) {
      std::vector<double> scalar_flux_at_quad_points(cell_quadrature_points_);

      if (group_in == group) {
        scalar_flux_at_quad_points =
            finite_element_->ValueAtQuadrature(in_group_moment);
      } else {
        scalar_flux_at_quad_points =
            finite_element_->ValueAtQuadrature(moment);
      }

      const auto sigma_s =
          cross_sections_->sigma_s.at(material_id)(group, group_in);

      for (int q = 0; q < cell_quadrature_points_; ++q)
        scattering_source_at_quad_points[q] +=
            sigma_s * scalar_flux_at_quad_points[q];
    }
  }

  // Integrate for each degree of freedom
  for (int q = 0; q < cell_quadrature_points_; ++q) {
    scattering_source_at_quad_points[q] *= finite_element_->Jacobian(q);

    for (int i = 0; i < cell_degrees_of_freedom_; ++i)
      to_fill(i) +=
          finite_element_->ShapeValue(i, q) * scattering_source_at_quad_points[q];

  }
}

template class CFEM_Diffusion<1>;
template class CFEM_Diffusion<2>;
template class CFEM_Diffusion<3>;

} // namespace scalar

} // namespace formulation

} // namespace bart<|endoftext|>


<commit_before>#include "../checkpoint/checkpoint.h"
#include "myrandom/myrand.h"
#include <algorithm>                            // for std::shuffle
#include <cstdint>                              // for std::int32_t
#include <iostream>                             // for std::cout
#include <random>                               // for std::mt19937
#include <utility>                              // for std::make_pair
#include <vector>                               // for std::vector
#include <boost/algorithm/cxx11/iota.hpp>       // for boost::algorithm::iota
#include <boost/format.hpp>                     // for boost::format
#include <boost/range/algorithm.hpp>            // for boost::find, boost::transform
#include <tbb/concurrent_vector.h>              // for tbb::concurrent_vector
#include <tbb/parallel_for.h>                   // for tbb::parallel_for

namespace {
    // ビンゴボードのマス数
    static auto constexpr BOARDSIZE = 25U;

    // モンテカルロシミュレーションの試行回数
    static auto constexpr MCMAX = 100000;

    // 行・列の総数
    static auto constexpr ROWCOLUMNSIZE = 10U;

    //! A typedef.
    /*!
        そのマスに書かれてある番号と、そのマスが当たったかどうかを示すフラグ
        のstd::pair
    */
    using mypair = std::pair<std::int32_t, bool>;

    //! A typedef.
    /*!
        行・列が埋まるまでに要した回数と、その時点で埋まったマスのstd::pair
    */
    using mypair2 = std::pair<std::int32_t, std::int32_t>;

    //! A function.
    /*!
        ビンゴボードを生成する
        \return ビンゴボードが格納された可変長配列
    */
    std::vector<mypair> makeBoard();

    //! A function.
    /*!
        モンテカルロ・シミュレーションを行う
        \return モンテカルロ法の結果が格納された二次元可変長配列
    */
    std::vector< std::vector<mypair2> > montecarlo();

    //! A function.
    /*!
        モンテカルロ・シミュレーションの実装
        \return モンテカルロ法の結果が格納された可変長配列
    */
    std::vector<mypair2> montecarloImpl();

    //! A function.
    /*!
        モンテカルロ・シミュレーションをTBBで並列化して行う
        \return モンテカルロ法の結果が格納された可変長配列
    */
    tbb::concurrent_vector< std::vector<mypair2> > montecarloTBB();
}

int main()
{
    checkpoint::CheckPoint cp;

    cp.checkpoint("処理開始", __LINE__);

    // モンテカルロ・シミュレーションの結果を代入
    auto const mcresult(montecarlo());

    cp.checkpoint("並列化無効", __LINE__);

    // TBBで並列化したモンテカルロ・シミュレーションの結果を代入
    auto const mcresult2(montecarloTBB());

    cp.checkpoint("並列化有効", __LINE__);

    // モンテカルロ・シミュレーションの平均試行回数の結果を格納した可変長配列
    std::vector<double> trialavg(ROWCOLUMNSIZE);

    // モンテカルロ・シミュレーションのi回目の試行で、埋まっているマスの数を格納した可変長配列
    std::vector<double> fillavg(ROWCOLUMNSIZE);

    // 行・列の総数分繰り返す
    for (auto i = 0; i < ROWCOLUMNSIZE; i++) {
        // 総和を0で初期化
        auto trialsum = 0;
        auto fillsum = 0;

        // 試行回数分繰り返す
        for (auto j = 0; j < MCMAX; j++) {
            // j回目の結果を加える
            trialsum += mcresult[j][i].first;
            fillsum += mcresult[j][i].second;
        }

        // 平均を算出してi行・列目のtrialavg、fillavgに代入
        trialavg[i] = static_cast<double>(trialsum) / static_cast<double>(MCMAX);
        fillavg[i] = static_cast<double>(fillsum) / static_cast<double>(MCMAX);
    }

    for (auto i = 0U; i < ROWCOLUMNSIZE; i++) {
        auto const efficiency = trialavg[i] / static_cast<double>(i + 1);
        std::cout
            << boost::format("%d個目に必要な平均試行回数：%.1f回, 効率 = %.1f（回/個）, ")
            % (i + 1) % trialavg[i] % efficiency
            << boost::format("埋まっているマスの平均個数：%.1f個\n")
            % fillavg[i];
    }

    cp.checkpoint_print();

    return 0;
}

namespace {
    std::vector<mypair> makeBoard()
    {
        // 仮のビンゴボードを生成
        std::vector<std::int32_t> boardtmp(BOARDSIZE);

        // 仮のビンゴボードに1～25の数字を代入
        boost::algorithm::iota(boardtmp, 1);

        // 仮のビンゴボードの数字をシャッフル
        std::shuffle(boardtmp.begin(), boardtmp.end(), std::mt19937());

        // ビンゴボードを生成
        std::vector<mypair> board(BOARDSIZE);

        // 仮のビンゴボードからビンゴボードを生成する
        boost::transform(
            boardtmp,
            board.begin(),
            [](auto n) { return std::make_pair(n, false); });

        // ビンゴボードを返す
        return board;
    }

    std::vector< std::vector<mypair2> > montecarlo()
    {
        // モンテカルロ・シミュレーションの結果を格納するための二次元可変長配列
        std::vector< std::vector<mypair2> > mcresult;

        // MCMAX個の容量を確保
        mcresult.reserve(MCMAX);

        // 試行回数分繰り返す
        for (auto i = 0; i < MCMAX; i++) {
            // モンテカルロ・シミュレーションの結果を代入
            mcresult.push_back(montecarloImpl());
        }

        // モンテカルロ・シミュレーションの結果を返す
        return mcresult;
    }

    std::vector<mypair2> montecarloImpl()
    {
        // ビンゴボードを生成
        auto board(makeBoard());

        // 自作乱数クラスを初期化
        myrandom::MyRand mr(1, BOARDSIZE);

        // その行・列が既に埋まっているかどうかを格納する可変長配列
        // ROWCOLUMNSIZE個の要素をfalseで初期化
        std::vector<bool> rcfill(ROWCOLUMNSIZE, false);

        // 行・列が埋まるまでに要した回数と、その時点で埋まったマスを格納した
        // 可変長配列
        std::vector< mypair2 > fillnum;

        // ROWCOLUMNSIZE個の容量を確保
        fillnum.reserve(ROWCOLUMNSIZE);

        // その時点で埋まっているマスを計算するためのラムダ式
        auto const sum = [](const std::vector< mypair > & vec)
        {
            auto cnt = 0;
            for (auto & e : vec) {
                if (e.second) {
                    cnt++;
                }
            }

            return cnt;
        };

        // 無限ループ
        for (auto i = 1; true; i++) {
            // 乱数で得た数字で、かつまだ当たってないマスを検索
            auto itr = boost::find(board, std::make_pair(mr.myrand(), false));

            // そのようなマスがあった
            if (itr != board.end()) {
                // そのマスは当たったとし、フラグをtrueにする
                itr->second = true;
            }
            // そのようなマスがなかった
            else {
                //ループ続行
                continue;
            }

            // 各行・列が埋まったかどうかをチェック
            for (auto j = 0; j < 5; j++) {
                // 行をチェック
                if (board[5 * j].second &&
                    board[5 * j + 1].second &&
                    board[5 * j + 2].second &&
                    board[5 * j + 3].second &&
                    board[5 * j + 4].second &&
                    // その行は既に埋まっているかどうか
                    !rcfill[j]) {

                    // その行は埋まったとして、フラグをtrueにする
                    rcfill[j] = true;

                    // 要した試行回数と、その時点で埋まったマスの数を格納
                    fillnum.push_back(std::make_pair(i, sum(board)));
                }

                // 列をチェック
                if (board[j].second &&
                    board[j + 5].second &&
                    board[j + 10].second &&
                    board[j + 15].second &&
                    board[j + 20].second &&
                    // その列は既に埋まっているかどうか
                    !rcfill[j + 5]) {

                    // その列は埋まったとして、フラグをtrueにする
                    rcfill[j + 5] = true;

                    // 要した試行回数と、その時点で埋まったマスの数を格納
                    fillnum.push_back(std::make_pair(i, sum(board)));
                }
            }

            // 全ての行・列が埋まったかどうか
            if (fillnum.size() == ROWCOLUMNSIZE) {
                // 埋まったのでループ脱出
                break;
            }
        }

        // 要した試行関数の可変長配列を返す
        return fillnum;
    }

    tbb::concurrent_vector< std::vector<mypair2> > montecarloTBB()
    {
        // モンテカルロ・シミュレーションの結果を格納するための二次元可変長配列
        // 二つのスレッドが同時にアクセスする可能性があるためtbb::concurrent_vectorを使う
        tbb::concurrent_vector< std::vector<mypair2> > mcresult;

        // MCMAX個の容量を確保
        mcresult.reserve(MCMAX);

        // MCMAX回のループを並列化して実行
        tbb::parallel_for(
            0,
            MCMAX,
            1,
            [&mcresult](auto) { mcresult.push_back(montecarloImpl()); });

        // モンテカルロ・シミュレーションの結果を返す
        return mcresult;
    }
}
<commit_msg>細かい修正<commit_after>#include "../checkpoint/checkpoint.h"
#include "myrandom/myrand.h"
#include <algorithm>                            // for std::shuffle
#include <cstdint>                              // for std::int32_t
#include <iostream>                             // for std::cout
#include <random>                               // for std::mt19937
#include <utility>                              // for std::make_pair
#include <vector>                               // for std::vector
#include <boost/algorithm/cxx11/iota.hpp>       // for boost::algorithm::iota
#include <boost/format.hpp>                     // for boost::format
#include <boost/range/algorithm.hpp>            // for boost::find, boost::transform
#include <tbb/concurrent_vector.h>              // for tbb::concurrent_vector
#include <tbb/parallel_for.h>                   // for tbb::parallel_for

namespace {
    // ビンゴボードのマス数
    static auto constexpr BOARDSIZE = 25U;

    // モンテカルロシミュレーションの試行回数
    static auto constexpr MCMAX = 1000000;

    // 行・列の総数
    static auto constexpr ROWCOLUMNSIZE = 10U;

    //! A typedef.
    /*!
        そのマスに書かれてある番号と、そのマスが当たったかどうかを示すフラグ
        のstd::pair
    */
    using mypair = std::pair<std::int32_t, bool>;

    //! A typedef.
    /*!
        行・列が埋まるまでに要した回数と、その時点で埋まったマスのstd::pair
    */
    using mypair2 = std::pair<std::int32_t, std::int32_t>;

    //! A function.
    /*!
        ビンゴボードを生成する
        \return ビンゴボードが格納された可変長配列
    */
    std::vector<mypair> makeBoard();

    //! A function.
    /*!
        モンテカルロ・シミュレーションを行う
        \return モンテカルロ法の結果が格納された二次元可変長配列
    */
    std::vector< std::vector<mypair2> > montecarlo();

    //! A function.
    /*!
        モンテカルロ・シミュレーションの実装
        \return モンテカルロ法の結果が格納された可変長配列
    */
    std::vector<mypair2> montecarloImpl();

    //! A function.
    /*!
        モンテカルロ・シミュレーションをTBBで並列化して行う
        \return モンテカルロ法の結果が格納された可変長配列
    */
    tbb::concurrent_vector< std::vector<mypair2> > montecarloTBB();
}

int main()
{
    checkpoint::CheckPoint cp;

    cp.checkpoint("処理開始", __LINE__);

    // モンテカルロ・シミュレーションの結果を代入
    auto const mcresult(montecarlo());

    cp.checkpoint("並列化無効", __LINE__);

    // TBBで並列化したモンテカルロ・シミュレーションの結果を代入
    auto const mcresult2(montecarloTBB());

    cp.checkpoint("並列化有効", __LINE__);

    // モンテカルロ・シミュレーションの平均試行回数の結果を格納した可変長配列
    std::vector<double> trialavg(ROWCOLUMNSIZE);

    // モンテカルロ・シミュレーションのi回目の試行で、埋まっているマスの数を格納した可変長配列
    std::vector<double> fillavg(ROWCOLUMNSIZE);

    // 行・列の総数分繰り返す
    for (auto i = 0U; i < ROWCOLUMNSIZE; i++) {
        // 総和を0で初期化
        auto trialsum = 0;
        auto fillsum = 0;

        // 試行回数分繰り返す
        for (auto j = 0; j < MCMAX; j++) {
            // j回目の結果を加える
            trialsum += mcresult[j][i].first;
            fillsum += mcresult[j][i].second;
        }

        // 平均を算出してi行・列目のtrialavg、fillavgに代入
        trialavg[i] = static_cast<double>(trialsum) / static_cast<double>(MCMAX);
        fillavg[i] = static_cast<double>(fillsum) / static_cast<double>(MCMAX);
    }

    for (auto i = 0U; i < ROWCOLUMNSIZE; i++) {
        auto const efficiency = trialavg[i] / static_cast<double>(i + 1);
        std::cout
            << boost::format("%d個目に必要な平均試行回数：%.1f回, 効率 = %.1f（回/個）, ")
            % (i + 1) % trialavg[i] % efficiency
            << boost::format("埋まっているマスの平均個数：%.1f個\n")
            % fillavg[i];
    }

    cp.checkpoint_print();

    return 0;
}

namespace {
    std::vector<mypair> makeBoard()
    {
        // 仮のビンゴボードを生成
        std::vector<std::int32_t> boardtmp(BOARDSIZE);

        // 仮のビンゴボードに1～25の数字を代入
        boost::algorithm::iota(boardtmp, 1);

        // 仮のビンゴボードの数字をシャッフル
        std::shuffle(boardtmp.begin(), boardtmp.end(), std::mt19937());

        // ビンゴボードを生成
        std::vector<mypair> board(BOARDSIZE);

        // 仮のビンゴボードからビンゴボードを生成する
        boost::transform(
            boardtmp,
            board.begin(),
            [](auto n) { return std::make_pair(n, false); });

        // ビンゴボードを返す
        return board;
    }

    std::vector< std::vector<mypair2> > montecarlo()
    {
        // モンテカルロ・シミュレーションの結果を格納するための二次元可変長配列
        std::vector< std::vector<mypair2> > mcresult;

        // MCMAX個の容量を確保
        mcresult.reserve(MCMAX);

        // 試行回数分繰り返す
        for (auto i = 0; i < MCMAX; i++) {
            // モンテカルロ・シミュレーションの結果を代入
            mcresult.push_back(montecarloImpl());
        }

        // モンテカルロ・シミュレーションの結果を返す
        return mcresult;
    }

    std::vector<mypair2> montecarloImpl()
    {
        // ビンゴボードを生成
        auto board(makeBoard());

        // 自作乱数クラスを初期化
        myrandom::MyRand mr(1, BOARDSIZE);

        // その行・列が既に埋まっているかどうかを格納する可変長配列
        // ROWCOLUMNSIZE個の要素をfalseで初期化
        std::vector<bool> rcfill(ROWCOLUMNSIZE, false);

        // 行・列が埋まるまでに要した回数と、その時点で埋まったマスを格納した
        // 可変長配列
        std::vector< mypair2 > fillnum;

        // ROWCOLUMNSIZE個の容量を確保
        fillnum.reserve(ROWCOLUMNSIZE);

        // その時点で埋まっているマスを計算するためのラムダ式
        auto const sum = [](const std::vector< mypair > & vec)
        {
            auto cnt = 0;
            for (auto & e : vec) {
                if (e.second) {
                    cnt++;
                }
            }

            return cnt;
        };

        // 無限ループ
        for (auto i = 1; true; i++) {
            // 乱数で得た数字で、かつまだ当たってないマスを検索
            auto itr = boost::find(board, std::make_pair(mr.myrand(), false));

            // そのようなマスがあった
            if (itr != board.end()) {
                // そのマスは当たったとし、フラグをtrueにする
                itr->second = true;
            }
            // そのようなマスがなかった
            else {
                //ループ続行
                continue;
            }

            // 各行・列が埋まったかどうかをチェック
            for (auto j = 0; j < 5; j++) {
                // 行をチェック
                if (board[5 * j].second &&
                    board[5 * j + 1].second &&
                    board[5 * j + 2].second &&
                    board[5 * j + 3].second &&
                    board[5 * j + 4].second &&
                    // その行は既に埋まっているかどうか
                    !rcfill[j]) {

                    // その行は埋まったとして、フラグをtrueにする
                    rcfill[j] = true;

                    // 要した試行回数と、その時点で埋まったマスの数を格納
                    fillnum.push_back(std::make_pair(i, sum(board)));
                }

                // 列をチェック
                if (board[j].second &&
                    board[j + 5].second &&
                    board[j + 10].second &&
                    board[j + 15].second &&
                    board[j + 20].second &&
                    // その列は既に埋まっているかどうか
                    !rcfill[j + 5]) {

                    // その列は埋まったとして、フラグをtrueにする
                    rcfill[j + 5] = true;

                    // 要した試行回数と、その時点で埋まったマスの数を格納
                    fillnum.push_back(std::make_pair(i, sum(board)));
                }
            }

            // 全ての行・列が埋まったかどうか
            if (fillnum.size() == ROWCOLUMNSIZE) {
                // 埋まったのでループ脱出
                break;
            }
        }

        // 要した試行関数の可変長配列を返す
        return fillnum;
    }

    tbb::concurrent_vector< std::vector<mypair2> > montecarloTBB()
    {
        // モンテカルロ・シミュレーションの結果を格納するための二次元可変長配列
        // 二つのスレッドが同時にアクセスする可能性があるためtbb::concurrent_vectorを使う
        tbb::concurrent_vector< std::vector<mypair2> > mcresult;

        // MCMAX個の容量を確保
        mcresult.reserve(MCMAX);

        // MCMAX回のループを並列化して実行
        tbb::parallel_for(
            0,
            MCMAX,
            1,
            [&mcresult](auto) { mcresult.push_back(montecarloImpl()); });

        // モンテカルロ・シミュレーションの結果を返す
        return mcresult;
    }
}
<|endoftext|>


<commit_before>#include "qhexeditdata.h"

const qint64 QHexEditData::BUFFER_SIZE = 8192;

QHexEditData::QHexEditData(QIODevice *iodevice, QObject *parent): QObject(parent), _iodevice(iodevice), _length(iodevice->size()), _devicelength(iodevice->size()), _lastpos(-1), _lastaction(QHexEditData::None)
{
    qRegisterMetaType<QHexEditData::ActionType>("QHexEditData::ActionType");
    this->_modlist.append(new ModifiedItem(0, iodevice->size(), false));
}

QHexEditData::~QHexEditData()
{
    foreach(ModifiedItem* mi, this->_modlist)
        delete mi;

    this->_modlist.clear();

    if(this->_iodevice->isOpen())
        this->_iodevice->close();
}

QUndoStack *QHexEditData::undoStack()
{
    return &this->_undostack;
}

qint64 QHexEditData::length() const
{
    return this->_length;
}

bool QHexEditData::save()
{
    return this->saveTo(this->_iodevice);
}

bool QHexEditData::saveTo(QIODevice *iodevice)
{
    if(!iodevice->isOpen())
        iodevice->open(QIODevice::WriteOnly);

    if(!iodevice->isWritable())
        return false;

    qint64 outseekpos = 0;
    this->_iodevice->reset();

    for(int i = 0; i < this->_modlist.length(); i++)
    {
        ModifiedItem* mi = this->_modlist[i];
        iodevice->seek(outseekpos);

        if(mi->modified())
            iodevice->write(this->_modbuffer.mid(mi->pos(), mi->length()));
        else if(iodevice != this->_iodevice)
        {
            this->_iodevice->seek(mi->pos());
            QByteArray ba = this->_iodevice->read(mi->length());
            iodevice->write(ba);
        }

        outseekpos += mi->length();
    }

    return true;
}

QHexEditData *QHexEditData::fromDevice(QIODevice *iodevice)
{
    if(!iodevice->isOpen())
        iodevice->open(QFile::ReadWrite);

    return new QHexEditData(iodevice);
}

QHexEditData *QHexEditData::fromFile(QString filename)
{
    QFile* f = new QFile(filename);
    f->open(QFile::ReadWrite);

    return QHexEditData::fromDevice(f);
}

QHexEditData *QHexEditData::fromMemory(const QByteArray &ba)
{
    QBuffer* b = new QBuffer();
    b->setData(ba);
    b->open(QFile::ReadOnly);

    return QHexEditData::fromDevice(b);
}

QHexEditData::InsertCommand* QHexEditData::internalInsert(qint64 pos, const QByteArray &ba, QHexEditData::ActionType act)
{
    if(pos < 0 || pos > this->length() || !ba.length())
        return nullptr;

    int i;
    qint64 datapos;
    ModifiedItem* mi;

    if(!this->_modlist.isEmpty())
    {
        mi = this->modifiedItem(pos, &datapos, &i);

        if(!mi)
            return nullptr;
    }
    else
    {
        pos = 0;
        datapos = 0;
    }

    bool optimize = false;
    ModifyList oldml, newml;
    qint64 modoffset = pos - datapos;
    qint64 buffoffset = this->updateBuffer(ba);

    if(!modoffset)
    {
        optimize = (act == QHexEditData::Insert) && this->canOptimize(act, pos);
        newml.append(new ModifiedItem(buffoffset, ba.length()));
    }
    else
    {
        oldml.append(mi);
        newml.append(new ModifiedItem(mi->pos(), modoffset, mi->modified()));
        newml.append(new ModifiedItem(buffoffset, ba.length()));
        newml.append(new ModifiedItem(mi->pos() + modoffset, mi->length() - modoffset, mi->modified()));
    }

    this->_length += ba.length();
    emit dataChanged(pos, ba.length(), act);
    return new InsertCommand(i, pos, oldml, newml, this, optimize);
}

QHexEditData::RemoveCommand* QHexEditData::internalRemove(qint64 pos, qint64 len, QHexEditData::ActionType act)
{
    if(pos < 0 || !len || pos >= this->length() || pos > (this->length() - len))
        return nullptr;

    int i;
    qint64 datapos;
    ModifiedItem* mi = this->modifiedItem(pos, &datapos, &i);

    if(!mi)
        return nullptr;

    QList<ModifiedItem*> olditems, newitems;
    qint64 remoffset = pos - datapos, remlength = len;

    if(remoffset)
    {
        newitems.append(new ModifiedItem(mi->pos(), remoffset, mi->modified()));

        if((remoffset + remlength) < mi->length())
            newitems.append(new ModifiedItem(mi->pos() + remoffset + remlength, mi->length() - remoffset - remlength, mi->modified()));

        remlength -= qMin(remlength, mi->length() - remoffset);
        olditems.append(mi);
        i++;
    }

    while(remlength && (i < this->_modlist.length()))
    {
        mi = this->_modlist[i];

        if(remlength < mi->length())
            newitems.append(new ModifiedItem(mi->pos() + remlength, mi->length() - remlength, mi->modified()));

        remlength -= qMin(remlength, mi->length());
        olditems.append(mi);
        i++;
    }

    this->_length -= len;
    emit dataChanged(pos, len, act);
    return new RemoveCommand(i - olditems.length(), pos, olditems, newitems, this);
}

bool QHexEditData::canOptimize(QHexEditData::ActionType at, qint64 pos)
{
    return (this->_lastaction == at) && (this->_lastpos == pos);
}

void QHexEditData::recordAction(QHexEditData::ActionType at, qint64 pos)
{
    this->_lastpos = pos;
    this->_lastaction = at;
}

qint64 QHexEditData::updateBuffer(const QByteArray &ba)
{
    qint64 pos = this->_modbuffer.length();
    this->_modbuffer.append(ba);
    return pos;
}

QHexEditData::ModifiedItem* QHexEditData::modifiedItem(qint64 pos, qint64* datapos, int *index)
{
    int i = -1;
    qint64 currpos = 0;
    ModifiedItem* mi = nullptr;

    for(i = 0; i < this->_modlist.length(); i++)
    {
        mi = this->_modlist[i];

        if((pos >= currpos) && (pos < (currpos + mi->length())))
        {
            if(datapos)
                *datapos = currpos;

            if(index)
                *index = i;

            return mi;
        }

        currpos += mi->length();
    }

    if(mi && (pos == currpos)) /* Return Last Item for Append */
    {
        if(datapos)
            *datapos = currpos;

        if(index)
            *index = i;

        return mi;
    }

    return nullptr;
}
<commit_msg>QHexEditData: Check if selected file is Read-Only<commit_after>#include "qhexeditdata.h"

const qint64 QHexEditData::BUFFER_SIZE = 8192;

QHexEditData::QHexEditData(QIODevice *iodevice, QObject *parent): QObject(parent), _iodevice(iodevice), _length(iodevice->size()), _devicelength(iodevice->size()), _lastpos(-1), _lastaction(QHexEditData::None)
{
    qRegisterMetaType<QHexEditData::ActionType>("QHexEditData::ActionType");
    this->_modlist.append(new ModifiedItem(0, iodevice->size(), false));
}

QHexEditData::~QHexEditData()
{
    foreach(ModifiedItem* mi, this->_modlist)
        delete mi;

    this->_modlist.clear();

    if(this->_iodevice->isOpen())
        this->_iodevice->close();
}

QUndoStack *QHexEditData::undoStack()
{
    return &this->_undostack;
}

qint64 QHexEditData::length() const
{
    return this->_length;
}

bool QHexEditData::isReadOnly() const
{
    return !this->_iodevice->isWritable();
}

bool QHexEditData::save()
{
    return this->saveTo(this->_iodevice);
}

bool QHexEditData::saveTo(QIODevice *iodevice)
{
    if(!iodevice->isOpen())
        iodevice->open(QIODevice::WriteOnly);

    if(!iodevice->isWritable())
        return false;

    qint64 outseekpos = 0;
    this->_iodevice->reset();

    for(int i = 0; i < this->_modlist.length(); i++)
    {
        ModifiedItem* mi = this->_modlist[i];
        iodevice->seek(outseekpos);

        if(mi->modified())
            iodevice->write(this->_modbuffer.mid(mi->pos(), mi->length()));
        else if(iodevice != this->_iodevice)
        {
            this->_iodevice->seek(mi->pos());
            QByteArray ba = this->_iodevice->read(mi->length());
            iodevice->write(ba);
        }

        outseekpos += mi->length();
    }

    return true;
}

QHexEditData *QHexEditData::fromDevice(QIODevice *iodevice)
{
    if(!iodevice->isOpen())
        iodevice->open(QFile::ReadWrite);

    return new QHexEditData(iodevice);
}

QHexEditData *QHexEditData::fromFile(QString filename)
{
    QFileInfo fi(filename);
    QFile* f = new QFile(filename);

    if(fi.isWritable())
        f->open(QFile::ReadWrite);
    else
        f->open(QFile::ReadOnly);

    return QHexEditData::fromDevice(f);
}

QHexEditData *QHexEditData::fromMemory(const QByteArray &ba)
{
    QBuffer* b = new QBuffer();
    b->setData(ba);
    b->open(QFile::ReadOnly);

    return QHexEditData::fromDevice(b);
}

QHexEditData::InsertCommand* QHexEditData::internalInsert(qint64 pos, const QByteArray &ba, QHexEditData::ActionType act)
{
    if(pos < 0 || pos > this->length() || !ba.length())
        return nullptr;

    int i;
    qint64 datapos;
    ModifiedItem* mi;

    if(!this->_modlist.isEmpty())
    {
        mi = this->modifiedItem(pos, &datapos, &i);

        if(!mi)
            return nullptr;
    }
    else
    {
        pos = 0;
        datapos = 0;
    }

    bool optimize = false;
    ModifyList oldml, newml;
    qint64 modoffset = pos - datapos;
    qint64 buffoffset = this->updateBuffer(ba);

    if(!modoffset)
    {
        optimize = (act == QHexEditData::Insert) && this->canOptimize(act, pos);
        newml.append(new ModifiedItem(buffoffset, ba.length()));
    }
    else
    {
        oldml.append(mi);
        newml.append(new ModifiedItem(mi->pos(), modoffset, mi->modified()));
        newml.append(new ModifiedItem(buffoffset, ba.length()));
        newml.append(new ModifiedItem(mi->pos() + modoffset, mi->length() - modoffset, mi->modified()));
    }

    this->_length += ba.length();
    emit dataChanged(pos, ba.length(), act);
    return new InsertCommand(i, pos, oldml, newml, this, optimize);
}

QHexEditData::RemoveCommand* QHexEditData::internalRemove(qint64 pos, qint64 len, QHexEditData::ActionType act)
{
    if(pos < 0 || !len || pos >= this->length() || pos > (this->length() - len))
        return nullptr;

    int i;
    qint64 datapos;
    ModifiedItem* mi = this->modifiedItem(pos, &datapos, &i);

    if(!mi)
        return nullptr;

    QList<ModifiedItem*> olditems, newitems;
    qint64 remoffset = pos - datapos, remlength = len;

    if(remoffset)
    {
        newitems.append(new ModifiedItem(mi->pos(), remoffset, mi->modified()));

        if((remoffset + remlength) < mi->length())
            newitems.append(new ModifiedItem(mi->pos() + remoffset + remlength, mi->length() - remoffset - remlength, mi->modified()));

        remlength -= qMin(remlength, mi->length() - remoffset);
        olditems.append(mi);
        i++;
    }

    while(remlength && (i < this->_modlist.length()))
    {
        mi = this->_modlist[i];

        if(remlength < mi->length())
            newitems.append(new ModifiedItem(mi->pos() + remlength, mi->length() - remlength, mi->modified()));

        remlength -= qMin(remlength, mi->length());
        olditems.append(mi);
        i++;
    }

    this->_length -= len;
    emit dataChanged(pos, len, act);
    return new RemoveCommand(i - olditems.length(), pos, olditems, newitems, this);
}

bool QHexEditData::canOptimize(QHexEditData::ActionType at, qint64 pos)
{
    return (this->_lastaction == at) && (this->_lastpos == pos);
}

void QHexEditData::recordAction(QHexEditData::ActionType at, qint64 pos)
{
    this->_lastpos = pos;
    this->_lastaction = at;
}

qint64 QHexEditData::updateBuffer(const QByteArray &ba)
{
    qint64 pos = this->_modbuffer.length();
    this->_modbuffer.append(ba);
    return pos;
}

QHexEditData::ModifiedItem* QHexEditData::modifiedItem(qint64 pos, qint64* datapos, int *index)
{
    int i = -1;
    qint64 currpos = 0;
    ModifiedItem* mi = nullptr;

    for(i = 0; i < this->_modlist.length(); i++)
    {
        mi = this->_modlist[i];

        if((pos >= currpos) && (pos < (currpos + mi->length())))
        {
            if(datapos)
                *datapos = currpos;

            if(index)
                *index = i;

            return mi;
        }

        currpos += mi->length();
    }

    if(mi && (pos == currpos)) /* Return Last Item for Append */
    {
        if(datapos)
            *datapos = currpos;

        if(index)
            *index = i;

        return mi;
    }

    return nullptr;
}
<|endoftext|>


<commit_before>/*
 * cxx_app_startup_shutdown.c
 *
 *  Created on: 30 janv. 2013
 *      Author: fsulima
 */

#include "cxx_app_start.h"
#include "cxx_app_startup_termination.h"
#include "cxxapp.hpp"

int cxx_app_start(int argc, char **argv) {
	int ret;

	cxx_app_startup();
	ret = main(argc,argv);
	cxx_app_termination();

	return ret;
}
<commit_msg>c++: calling getopt_init on c++ app startup<commit_after>/*
 * cxx_app_startup_shutdown.c
 *
 *  Created on: 30 janv. 2013
 *      Author: fsulima
 */

#include "cxx_app_start.h"
#include "cxx_app_startup_termination.h"
#include "cxxapp.hpp"
#include <unistd.h>

int cxx_app_start(int argc, char **argv) {
	int ret;

	cxx_app_startup();
	getopt_init();
	ret = main(argc,argv);
	cxx_app_termination();

	return ret;
}
<|endoftext|>


<commit_before>/*
Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al.
All Rights Reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
  notice, this list of conditions and the following disclaimer.
* 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.
* Neither the name of Sony Pictures Imageworks 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.
*/

#include <cmath>

#include "oslops.h"
#include "oslexec_pvt.h"

#ifdef OSL_NAMESPACE
namespace OSL_NAMESPACE {
#endif

namespace OSL {
namespace pvt {

class AshikhminVelvetClosure : public BSDFClosure {
    Vec3 m_N;
    float m_sigma;
    float m_R0;
    float m_invsigma2;
public:
    CLOSURE_CTOR (AshikhminVelvetClosure) : BSDFClosure(side, Labels::DIFFUSE)
    {
        CLOSURE_FETCH_ARG (m_N, 1);
        CLOSURE_FETCH_ARG (m_sigma, 2);
        CLOSURE_FETCH_ARG (m_R0, 3);

        m_sigma = std::max(m_sigma, 0.01f);
        m_invsigma2 = 1 / (m_sigma * m_sigma);
    }

    void print_on (std::ostream &out) const
    {
        out << "ashikhmin_velvet (";
        out << "(" << m_N[0] << ", " << m_N[1] << ", " << m_N[2] << "), ";
        out << m_sigma << ", ";
        out << m_R0;
        out << ")";
    }

    Color3 eval_reflect (const Vec3 &omega_out, const Vec3 &omega_in, float normal_sign, float& pdf) const
    {
        float cosNO = normal_sign * m_N.dot(omega_out);
        float cosNI = normal_sign * m_N.dot(omega_in);
        if (cosNO > 0 && cosNI > 0) {
            Vec3 H = omega_in + omega_out;
            H.normalize();

            float cosNH = normal_sign * m_N.dot(H);
            float cosHO = fabsf(omega_out.dot(H));

            float cosNHdivHO = cosNH / cosHO;
            cosNHdivHO = std::max(cosNHdivHO, 0.00001f);

            float fac1 = 2 * fabsf(cosNHdivHO * cosNO);
            float fac2 = 2 * fabsf(cosNHdivHO * cosNI);

            float sinNH2 = 1 - cosNH * cosNH;
            float sinNH4 = sinNH2 * sinNH2;
            float cotangent2 =  (cosNH * cosNH) / sinNH2;

            float D = expf(-cotangent2 * m_invsigma2) * m_invsigma2 * float(M_1_PI) / sinNH4;
            float G = std::min(1.0f, std::min(fac1, fac2)); // TODO: derive G from D analytically
            // Schlick approximation of Fresnel reflectance
            float cosi2 = cosNO * cosNO;
            float cosi5 = cosi2 * cosi2 * cosNO;
            float F =  m_R0 + (1 - cosi5) * (1 - m_R0);

            float out = 0.25f * (D * G * F) / cosNO;

            pdf = 0.5f * (float) M_1_PI;
            return Color3 (out, out, out);
        }
        return Color3 (0, 0, 0);
    }

    Color3 eval_transmit (const Vec3 &omega_out, const Vec3 &omega_in, float normal_sign, float& pdf) const
    {
        return Color3 (0, 0, 0);
    }

    ustring sample (const Vec3 &Ng,
                 const Vec3 &omega_out, const Vec3 &domega_out_dx, const Vec3 &domega_out_dy,
                 float randu, float randv,
                 Vec3 &omega_in, Vec3 &domega_in_dx, Vec3 &domega_in_dy,
                 float &pdf, Color3 &eval) const
    {

        Vec3 Ngf, Nf;
        if (faceforward (omega_out, Ng, m_N, Ngf, Nf)) {
            // we are viewing the surface from above - send a ray out with uniform
            // distribution over the hemisphere
            sample_uniform_hemisphere (Nf, omega_out, randu, randv, omega_in, pdf);
            if (Ngf.dot(omega_in) > 0) {
                Vec3 H = omega_in + omega_out;
                H.normalize();

                float cosNI = Nf.dot(omega_in);
                float cosNO = Nf.dot(omega_out);
                float cosNH = Nf.dot(H);
                float cosHO = fabsf(omega_out.dot(H));

                float cosNHdivHO = cosNH / cosHO;
                cosNHdivHO = std::max(cosNHdivHO, 0.00001f);

                float fac1 = 2 * fabsf(cosNHdivHO * cosNO);
                float fac2 = 2 * fabsf(cosNHdivHO * cosNI);

                float sinNH2 = 1 - cosNH * cosNH;
                float sinNH4 = sinNH2 * sinNH2;
                float cotangent2 =  (cosNH * cosNH) / sinNH2;

                float D = expf(-cotangent2 * m_invsigma2) * m_invsigma2 * float(M_1_PI) / sinNH4;
                float G = std::min(1.0f, std::min(fac1, fac2)); // TODO: derive G from D analytically
                // Schlick approximation of Fresnel reflectance
                float cosi2 = cosNO * cosNO;
                float cosi5 = cosi2 * cosi2 * cosNO;
                float F =  m_R0 + (1 - cosi5) * (1 - m_R0);

                float power = 0.25f * (D * G * F) / cosNO;

                eval.setValue(power, power, power);

                // TODO: find a better approximation for the retroreflective bounce
                domega_in_dx = (2 * Nf.dot(domega_out_dx)) * Nf - domega_out_dx;
                domega_in_dy = (2 * Nf.dot(domega_out_dy)) * Nf - domega_out_dy;
                domega_in_dx *= 125;
                domega_in_dy *= 125;
            } else
                pdf = 0;
        }
        return Labels::REFLECT;
    }

};

DECLOP (OP_ashikhmin_velvet)
{
    closure_op_guts<AshikhminVelvetClosure, 4> (exec, nargs, args);
}

}; // namespace pvt
}; // namespace OSL
#ifdef OSL_NAMESPACE
}; // end namespace OSL_NAMESPACE
#endif
<commit_msg>updated to use Fresnel dielectric<commit_after>/*
Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al.
All Rights Reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
  notice, this list of conditions and the following disclaimer.
* 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.
* Neither the name of Sony Pictures Imageworks 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.
*/

#include <cmath>

#include "oslops.h"
#include "oslexec_pvt.h"

#ifdef OSL_NAMESPACE
namespace OSL_NAMESPACE {
#endif

namespace OSL {
namespace pvt {

class AshikhminVelvetClosure : public BSDFClosure {
    Vec3 m_N;
    float m_sigma;
    float m_eta;
    float m_invsigma2;
public:
    CLOSURE_CTOR (AshikhminVelvetClosure) : BSDFClosure(side, Labels::DIFFUSE)
    {
        CLOSURE_FETCH_ARG (m_N, 1);
        CLOSURE_FETCH_ARG (m_sigma, 2);
        CLOSURE_FETCH_ARG (m_eta, 3);

        m_sigma = std::max(m_sigma, 0.01f);
        m_invsigma2 = 1 / (m_sigma * m_sigma);
    }

    void print_on (std::ostream &out) const
    {
        out << "ashikhmin_velvet (";
        out << "(" << m_N[0] << ", " << m_N[1] << ", " << m_N[2] << "), ";
        out << m_sigma << ", ";
        out << m_eta;
        out << ")";
    }

    Color3 eval_reflect (const Vec3 &omega_out, const Vec3 &omega_in, float normal_sign, float& pdf) const
    {
        float cosNO = normal_sign * m_N.dot(omega_out);
        float cosNI = normal_sign * m_N.dot(omega_in);
        if (cosNO > 0 && cosNI > 0) {
            Vec3 H = omega_in + omega_out;
            H.normalize();

            float cosNH = normal_sign * m_N.dot(H);
            float cosHO = fabsf(omega_out.dot(H));

            float cosNHdivHO = cosNH / cosHO;
            cosNHdivHO = std::max(cosNHdivHO, 0.00001f);

            float fac1 = 2 * fabsf(cosNHdivHO * cosNO);
            float fac2 = 2 * fabsf(cosNHdivHO * cosNI);

            float sinNH2 = 1 - cosNH * cosNH;
            float sinNH4 = sinNH2 * sinNH2;
            float cotangent2 =  (cosNH * cosNH) / sinNH2;

            float D = expf(-cotangent2 * m_invsigma2) * m_invsigma2 * float(M_1_PI) / sinNH4;
            float G = std::min(1.0f, std::min(fac1, fac2)); // TODO: derive G from D analytically
            float F = fresnel_dielectric(cosNO, m_eta);

            float out = 0.25f * (D * G * F) / cosNO;

            pdf = 0.5f * (float) M_1_PI;
            return Color3 (out, out, out);
        }
        return Color3 (0, 0, 0);
    }

    Color3 eval_transmit (const Vec3 &omega_out, const Vec3 &omega_in, float normal_sign, float& pdf) const
    {
        return Color3 (0, 0, 0);
    }

    ustring sample (const Vec3 &Ng,
                 const Vec3 &omega_out, const Vec3 &domega_out_dx, const Vec3 &domega_out_dy,
                 float randu, float randv,
                 Vec3 &omega_in, Vec3 &domega_in_dx, Vec3 &domega_in_dy,
                 float &pdf, Color3 &eval) const
    {

        Vec3 Ngf, Nf;
        if (faceforward (omega_out, Ng, m_N, Ngf, Nf)) {
            // we are viewing the surface from above - send a ray out with uniform
            // distribution over the hemisphere
            sample_uniform_hemisphere (Nf, omega_out, randu, randv, omega_in, pdf);
            if (Ngf.dot(omega_in) > 0) {
                Vec3 H = omega_in + omega_out;
                H.normalize();

                float cosNI = Nf.dot(omega_in);
                float cosNO = Nf.dot(omega_out);
                float cosNH = Nf.dot(H);
                float cosHO = fabsf(omega_out.dot(H));

                float cosNHdivHO = cosNH / cosHO;
                cosNHdivHO = std::max(cosNHdivHO, 0.00001f);

                float fac1 = 2 * fabsf(cosNHdivHO * cosNO);
                float fac2 = 2 * fabsf(cosNHdivHO * cosNI);

                float sinNH2 = 1 - cosNH * cosNH;
                float sinNH4 = sinNH2 * sinNH2;
                float cotangent2 =  (cosNH * cosNH) / sinNH2;

                float D = expf(-cotangent2 * m_invsigma2) * m_invsigma2 * float(M_1_PI) / sinNH4;
                float G = std::min(1.0f, std::min(fac1, fac2)); // TODO: derive G from D analytically
                float F = fresnel_dielectric(cosNO, m_eta);

                float power = 0.25f * (D * G * F) / cosNO;

                eval.setValue(power, power, power);

                // TODO: find a better approximation for the retroreflective bounce
                domega_in_dx = (2 * Nf.dot(domega_out_dx)) * Nf - domega_out_dx;
                domega_in_dy = (2 * Nf.dot(domega_out_dy)) * Nf - domega_out_dy;
                domega_in_dx *= 125;
                domega_in_dy *= 125;
            } else
                pdf = 0;
        }
        return Labels::REFLECT;
    }

};

DECLOP (OP_ashikhmin_velvet)
{
    closure_op_guts<AshikhminVelvetClosure, 4> (exec, nargs, args);
}

}; // namespace pvt
}; // namespace OSL
#ifdef OSL_NAMESPACE
}; // end namespace OSL_NAMESPACE
#endif
<|endoftext|>


<commit_before>// Copyright (c) 2008 Roberto Raggi <roberto.raggi@gmail.com>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

#include "Literals.h"
#include "NameVisitor.h"
#include <cstring>
#include <algorithm>
#include <iostream>

using namespace CPlusPlus;

////////////////////////////////////////////////////////////////////////////////
Literal::Literal(const char *chars, unsigned size)
    : _next(0), _index(0)
{
    _chars = new char[size + 1];

    std::strncpy(_chars, chars, size);
    _chars[size] = '\0';
    _size = size;

    _hashCode = hashCode(_chars, _size);
}

Literal::~Literal()
{ delete[] _chars; }

bool Literal::equalTo(const Literal *other) const
{
    if (! other)
        return false;
    else if (this == other)
        return true;
    else if (hashCode() != other->hashCode())
        return false;
    else if (size() != other->size())
        return false;
    return ! std::strcmp(chars(), other->chars());
}

Literal::iterator Literal::begin() const
{ return _chars; }

Literal::iterator Literal::end() const
{ return _chars + _size; }

const char *Literal::chars() const
{ return _chars; }

char Literal::at(unsigned index) const
{ return _chars[index]; }

unsigned Literal::size() const
{ return _size; }

unsigned Literal::hashCode() const
{ return _hashCode; }

unsigned Literal::hashCode(const char *chars, unsigned size)
{
    unsigned h = 0;
    for (unsigned i = 0; i < size; ++i)
        h = (h >> 5) - h + chars[i];
    return h;
}

////////////////////////////////////////////////////////////////////////////////
StringLiteral::StringLiteral(const char *chars, unsigned size)
    : Literal(chars, size)
{ }

StringLiteral::~StringLiteral()
{ }

////////////////////////////////////////////////////////////////////////////////
enum {
    NumericLiteralIsInt,
    NumericLiteralIsFloat,
    NumericLiteralIsDouble,
    NumericLiteralIsLongDouble,
    NumericLiteralIsLong,
    NumericLiteralIsLongLong
};

NumericLiteral::NumericLiteral(const char *chars, unsigned size)
    : Literal(chars, size), _flags(0)
{
    f._type = NumericLiteralIsInt;

    if (size > 1 && chars[0] == '0' && (chars[1] == 'x' || chars[1] == 'X')) {
        f._isHex = true;
    } else {
        const char *begin = chars;
        const char *end = begin + size;

        bool done = false;
        const char *it = end - 1;

        for (; it != begin - 1 && ! done; --it) {
            switch (*it) {
            case 'l': case 'L': // long suffix
            case 'u': case 'U': // unsigned suffix
            case 'f': case 'F': // floating suffix
                break;

            default:
                done = true;
                break;
            } // switch
        }

        for (const char *dot = it; it != begin - 1; --it) {
            if (*dot == '.')
                f._type = NumericLiteralIsDouble;
        }

        for (++it; it != end; ++it) {
            if (*it == 'l' || *it == 'L') {
                if (f._type == NumericLiteralIsDouble) {
                    f._type = NumericLiteralIsLongDouble;
                } else if (it + 1 != end && (it[1] == 'l' || it[1] == 'L')) {
                    ++it;
                    f._type = NumericLiteralIsLongLong;
                } else {
                    f._type = NumericLiteralIsLong;
                }
            } else if (*it == 'f' || *it == 'F') {
                f._type = NumericLiteralIsFloat;
            } else if (*it == 'u' || *it == 'U') {
                f._isUnsigned = true;
            }
        }
    }
}

NumericLiteral::~NumericLiteral()
{ }

bool NumericLiteral::isHex() const
{ return f._isHex; }

bool NumericLiteral::isUnsigned() const
{ return f._isUnsigned; }

bool NumericLiteral::isInt() const
{ return f._type == NumericLiteralIsInt; }

bool NumericLiteral::isFloat() const
{ return f._type == NumericLiteralIsFloat; }

bool NumericLiteral::isDouble() const
{ return f._type == NumericLiteralIsDouble; }

bool NumericLiteral::isLongDouble() const
{ return f._type == NumericLiteralIsLongDouble; }

bool NumericLiteral::isLong() const
{ return f._type == NumericLiteralIsLong; }

bool NumericLiteral::isLongLong() const
{ return f._type == NumericLiteralIsLongLong; }

////////////////////////////////////////////////////////////////////////////////
Identifier::Identifier(const char *chars, unsigned size)
    : Literal(chars, size)
{ }

Identifier::~Identifier()
{ }

void Identifier::accept0(NameVisitor *visitor) const
{ visitor->visit(this); }

bool Identifier::isEqualTo(const Name *other) const
{
    if (this == other)
        return true;

    else if (other) {
        if (const Identifier *nameId = other->asNameId()) {
            return equalTo(nameId);
        }
    }
    return false;
}
<commit_msg>C++: Improve Literal::hashCode.<commit_after>// Copyright (c) 2008 Roberto Raggi <roberto.raggi@gmail.com>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

#include "Literals.h"
#include "NameVisitor.h"
#include <cstring>
#include <algorithm>
#include <iostream>

using namespace CPlusPlus;

////////////////////////////////////////////////////////////////////////////////
Literal::Literal(const char *chars, unsigned size)
    : _next(0), _index(0)
{
    _chars = new char[size + 1];

    std::strncpy(_chars, chars, size);
    _chars[size] = '\0';
    _size = size;

    _hashCode = hashCode(_chars, _size);
}

Literal::~Literal()
{ delete[] _chars; }

bool Literal::equalTo(const Literal *other) const
{
    if (! other)
        return false;
    else if (this == other)
        return true;
    else if (hashCode() != other->hashCode())
        return false;
    else if (size() != other->size())
        return false;
    return ! std::strcmp(chars(), other->chars());
}

Literal::iterator Literal::begin() const
{ return _chars; }

Literal::iterator Literal::end() const
{ return _chars + _size; }

const char *Literal::chars() const
{ return _chars; }

char Literal::at(unsigned index) const
{ return _chars[index]; }

unsigned Literal::size() const
{ return _size; }

unsigned Literal::hashCode() const
{ return _hashCode; }

unsigned Literal::hashCode(const char *chars, unsigned size)
{
    /* Hash taken from QtCore's qHash for strings, which in turn has the note:

    These functions are based on Peter J. Weinberger's hash function
    (from the Dragon Book). The constant 24 in the original function
    was replaced with 23 to produce fewer collisions on input such as
    "a", "aa", "aaa", "aaaa", ...
    */

    uint h = 0;

    while (size--) {
        h = (h << 4) + *chars++;
        h ^= (h & 0xf0000000) >> 23;
        h &= 0x0fffffff;
    }
    return h;
}

////////////////////////////////////////////////////////////////////////////////
StringLiteral::StringLiteral(const char *chars, unsigned size)
    : Literal(chars, size)
{ }

StringLiteral::~StringLiteral()
{ }

////////////////////////////////////////////////////////////////////////////////
enum {
    NumericLiteralIsInt,
    NumericLiteralIsFloat,
    NumericLiteralIsDouble,
    NumericLiteralIsLongDouble,
    NumericLiteralIsLong,
    NumericLiteralIsLongLong
};

NumericLiteral::NumericLiteral(const char *chars, unsigned size)
    : Literal(chars, size), _flags(0)
{
    f._type = NumericLiteralIsInt;

    if (size > 1 && chars[0] == '0' && (chars[1] == 'x' || chars[1] == 'X')) {
        f._isHex = true;
    } else {
        const char *begin = chars;
        const char *end = begin + size;

        bool done = false;
        const char *it = end - 1;

        for (; it != begin - 1 && ! done; --it) {
            switch (*it) {
            case 'l': case 'L': // long suffix
            case 'u': case 'U': // unsigned suffix
            case 'f': case 'F': // floating suffix
                break;

            default:
                done = true;
                break;
            } // switch
        }

        for (const char *dot = it; it != begin - 1; --it) {
            if (*dot == '.')
                f._type = NumericLiteralIsDouble;
        }

        for (++it; it != end; ++it) {
            if (*it == 'l' || *it == 'L') {
                if (f._type == NumericLiteralIsDouble) {
                    f._type = NumericLiteralIsLongDouble;
                } else if (it + 1 != end && (it[1] == 'l' || it[1] == 'L')) {
                    ++it;
                    f._type = NumericLiteralIsLongLong;
                } else {
                    f._type = NumericLiteralIsLong;
                }
            } else if (*it == 'f' || *it == 'F') {
                f._type = NumericLiteralIsFloat;
            } else if (*it == 'u' || *it == 'U') {
                f._isUnsigned = true;
            }
        }
    }
}

NumericLiteral::~NumericLiteral()
{ }

bool NumericLiteral::isHex() const
{ return f._isHex; }

bool NumericLiteral::isUnsigned() const
{ return f._isUnsigned; }

bool NumericLiteral::isInt() const
{ return f._type == NumericLiteralIsInt; }

bool NumericLiteral::isFloat() const
{ return f._type == NumericLiteralIsFloat; }

bool NumericLiteral::isDouble() const
{ return f._type == NumericLiteralIsDouble; }

bool NumericLiteral::isLongDouble() const
{ return f._type == NumericLiteralIsLongDouble; }

bool NumericLiteral::isLong() const
{ return f._type == NumericLiteralIsLong; }

bool NumericLiteral::isLongLong() const
{ return f._type == NumericLiteralIsLongLong; }

////////////////////////////////////////////////////////////////////////////////
Identifier::Identifier(const char *chars, unsigned size)
    : Literal(chars, size)
{ }

Identifier::~Identifier()
{ }

void Identifier::accept0(NameVisitor *visitor) const
{ visitor->visit(this); }

bool Identifier::isEqualTo(const Name *other) const
{
    if (this == other)
        return true;

    else if (other) {
        if (const Identifier *nameId = other->asNameId()) {
            return equalTo(nameId);
        }
    }
    return false;
}
<|endoftext|>


<commit_before>#include "parser.h"

std::vector<std::string> keywords = {"norrk\x94ping","norrkoping",
	"spongebob","britney","spears", "paris", "hilton"};
std::string errorUrl1 ="";
std::map<std::string,std::string> parseHttp(std::string s){
  std::map<std::string, std::string> m;

  std::istringstream resp(s);
  std::string header;
  std::string::size_type index;
  bool firstLine = true;
  while (std::getline(resp, header) && header != "\r") {
  	if(firstLine){
  		m.insert(std::make_pair("URL",header.substr(4,header.length())));
  		firstLine = false;
  		//std::cerr << m.find("URL")->second << std::endl;
      continue;
  	}
    index = header.find(':', 0);
    if(index != std::string::npos) {
      m.insert(std::make_pair(
        boost::algorithm::trim_copy(header.substr(0, index)),
        boost::algorithm::trim_copy(header.substr(index + 1))
      ));
    }
  }
  return m;
}

std::string censor(std::string content, std::map<std::string, std::string> m){
	std::string url = m.find("URL")->second;
	for(size_t i =0; i<=keywords.size();i++){
		std::transform(url.begin(), url.end(), url.begin(), ::tolower);
		std::size_t found = url.find(keywords.at(i));
  		if (found!=std::string::npos){
  			return errorUrl1;
  		}
	}
	return "";
}
<commit_msg>iterator instead of for<commit_after>#include "parser.h"

std::list<std::string> keywords = {"norrk\x94ping","norrkoping",
	"spongebob","britney","spears", "paris", "hilton"};
std::string errorUrl1 ="";
std::map<std::string,std::string> parseHttp(std::string s){
  std::map<std::string, std::string> m;

  std::istringstream resp(s);
  std::string header;
  std::string::size_type index;
  bool firstLine = true;
  while (std::getline(resp, header) && header != "\r") {
  	if(firstLine){
  		m.insert(std::make_pair("URL",header.substr(4,header.length())));
  		firstLine = false;
  		//std::cerr << m.find("URL")->second << std::endl;
      continue;
  	}
    index = header.find(':', 0);
    if(index != std::string::npos) {
      m.insert(std::make_pair(
        boost::algorithm::trim_copy(header.substr(0, index)),
        boost::algorithm::trim_copy(header.substr(index + 1))
      ));
    }
  }
  return m;
}

std::string censor(std::string content, std::map<std::string, std::string> m){
	std::string url = m.find("URL")->second;
	std::transform(url.begin(), url.end(), url.begin(), ::tolower);
	for (std::list<std::string>::iterator it=keywords.begin(); it != keywords.end(); ++it){
		std::size_t found = url.find(*it);
  		if (found!=std::string::npos){
  			return errorUrl1;
  		}
	}
	return "";
}
<|endoftext|>


<commit_before>#include <boost/thread.hpp>
#include <string>
#include <vector>

#include "caffe/data_layers.hpp"
#include "caffe/net.hpp"
#include "caffe/util/io.hpp"

namespace caffe {

template <typename Dtype>
BaseDataLayer<Dtype>::BaseDataLayer(const LayerParameter& param)
    : Layer<Dtype>(param),
      transform_param_(param.transform_param()) {
}

template <typename Dtype>
void BaseDataLayer<Dtype>::LayerSetUp(const vector<Blob<Dtype>*>& bottom,
      const vector<Blob<Dtype>*>& top) {
  if (top.size() == 1) {
    output_labels_ = false;
  } else {
    output_labels_ = true;
  }
  data_transformer_.reset(
      new DataTransformer<Dtype>(transform_param_, this->phase_));
  data_transformer_->InitRand();
  // The subclasses should setup the size of bottom and top
  DataLayerSetUp(bottom, top);
}

template <typename Dtype>
BasePrefetchingDataLayer<Dtype>::BasePrefetchingDataLayer(
    const LayerParameter& param)
    : BaseDataLayer<Dtype>(param),
      prefetch_free_(), prefetch_full_() {
  for (int i = 0; i < PREFETCH_COUNT; ++i) {
    prefetch_free_.push(&prefetch_[i]);
  }
}

template <typename Dtype>
void BasePrefetchingDataLayer<Dtype>::LayerSetUp(
    const vector<Blob<Dtype>*>& bottom, const vector<Blob<Dtype>*>& top) {
  BaseDataLayer<Dtype>::LayerSetUp(bottom, top);
  // Before starting the prefetch thread, we make cpu_data and gpu_data
  // calls so that the prefetch thread does not accidentally make simultaneous
  // cudaMalloc calls when the main thread is running. In some GPUs this
  // seems to cause failures if we do not so.
  for (int i = 0; i < PREFETCH_COUNT; ++i) {
    prefetch_[i].data_.mutable_cpu_data();
    if (this->output_labels_) {
      prefetch_[i].label_.mutable_cpu_data();
    }
  }
#ifndef CPU_ONLY
  if (Caffe::mode() == Caffe::GPU) {
    for (int i = 0; i < PREFETCH_COUNT; ++i) {
      prefetch_[i].data_.mutable_gpu_data();
      if (this->output_labels_) {
        prefetch_[i].label_.mutable_gpu_data();
      }
    }
  }
#endif
  DLOG(INFO) << "Initializing prefetch";
  this->data_transformer_->InitRand();
  StartInternalThread();
  DLOG(INFO) << "Prefetch initialized.";
}

template <typename Dtype>
void BasePrefetchingDataLayer<Dtype>::InternalThreadEntry() {
#ifndef CPU_ONLY
  cudaStream_t stream;
  if (Caffe::mode() == Caffe::GPU) {
    cudaStreamCreateWithFlags(&stream, cudaStreamNonBlocking);
  }
#endif

  try {
    while (!must_stop()) {
      Batch<Dtype>* batch = prefetch_free_.pop();
      load_batch(batch);
#ifndef CPU_ONLY
      if (Caffe::mode() == Caffe::GPU) {
        batch->data_.data().get()->async_gpu_push(stream);
        cudaStreamSynchronize(stream);
      }
#endif
      prefetch_full_.push(batch);
    }
  } catch (boost::thread_interrupted&) {
    // Interrupted exception is expected on shutdown
  }
}

template <typename Dtype>
void BasePrefetchingDataLayer<Dtype>::Forward_cpu(
    const vector<Blob<Dtype>*>& bottom, const vector<Blob<Dtype>*>& top) {
  Batch<Dtype>* batch = prefetch_full_.pop("Data layer prefetch queue empty");
  // Reshape to loaded data.
  top[0]->Reshape(batch->data_.num(), batch->data_.channels(),
      batch->data_.height(), batch->data_.width());
  // Copy the data
  caffe_copy(batch->data_.count(), batch->data_.cpu_data(),
             top[0]->mutable_cpu_data());
  DLOG(INFO) << "Prefetch copied";
  if (this->output_labels_) {
    // Reshape to loaded labels.
    top[1]->ReshapeLike(batch->label_);
    // Copy the labels.
    caffe_copy(batch->label_.count(), batch->label_.cpu_data(),
        top[1]->mutable_cpu_data());
  }

  prefetch_free_.push(batch);
}

#ifdef CPU_ONLY
STUB_GPU_FORWARD(BasePrefetchingDataLayer, Forward);
#endif

INSTANTIATE_CLASS(BaseDataLayer);
INSTANTIATE_CLASS(BasePrefetchingDataLayer);

}  // namespace caffe
<commit_msg>Destroy CUDA stream when finished<commit_after>#include <boost/thread.hpp>
#include <string>
#include <vector>

#include "caffe/data_layers.hpp"
#include "caffe/net.hpp"
#include "caffe/util/io.hpp"

namespace caffe {

template <typename Dtype>
BaseDataLayer<Dtype>::BaseDataLayer(const LayerParameter& param)
    : Layer<Dtype>(param),
      transform_param_(param.transform_param()) {
}

template <typename Dtype>
void BaseDataLayer<Dtype>::LayerSetUp(const vector<Blob<Dtype>*>& bottom,
      const vector<Blob<Dtype>*>& top) {
  if (top.size() == 1) {
    output_labels_ = false;
  } else {
    output_labels_ = true;
  }
  data_transformer_.reset(
      new DataTransformer<Dtype>(transform_param_, this->phase_));
  data_transformer_->InitRand();
  // The subclasses should setup the size of bottom and top
  DataLayerSetUp(bottom, top);
}

template <typename Dtype>
BasePrefetchingDataLayer<Dtype>::BasePrefetchingDataLayer(
    const LayerParameter& param)
    : BaseDataLayer<Dtype>(param),
      prefetch_free_(), prefetch_full_() {
  for (int i = 0; i < PREFETCH_COUNT; ++i) {
    prefetch_free_.push(&prefetch_[i]);
  }
}

template <typename Dtype>
void BasePrefetchingDataLayer<Dtype>::LayerSetUp(
    const vector<Blob<Dtype>*>& bottom, const vector<Blob<Dtype>*>& top) {
  BaseDataLayer<Dtype>::LayerSetUp(bottom, top);
  // Before starting the prefetch thread, we make cpu_data and gpu_data
  // calls so that the prefetch thread does not accidentally make simultaneous
  // cudaMalloc calls when the main thread is running. In some GPUs this
  // seems to cause failures if we do not so.
  for (int i = 0; i < PREFETCH_COUNT; ++i) {
    prefetch_[i].data_.mutable_cpu_data();
    if (this->output_labels_) {
      prefetch_[i].label_.mutable_cpu_data();
    }
  }
#ifndef CPU_ONLY
  if (Caffe::mode() == Caffe::GPU) {
    for (int i = 0; i < PREFETCH_COUNT; ++i) {
      prefetch_[i].data_.mutable_gpu_data();
      if (this->output_labels_) {
        prefetch_[i].label_.mutable_gpu_data();
      }
    }
  }
#endif
  DLOG(INFO) << "Initializing prefetch";
  this->data_transformer_->InitRand();
  StartInternalThread();
  DLOG(INFO) << "Prefetch initialized.";
}

template <typename Dtype>
void BasePrefetchingDataLayer<Dtype>::InternalThreadEntry() {
#ifndef CPU_ONLY
  cudaStream_t stream;
  if (Caffe::mode() == Caffe::GPU) {
    CUDA_CHECK(cudaStreamCreateWithFlags(&stream, cudaStreamNonBlocking));
  }
#endif

  try {
    while (!must_stop()) {
      Batch<Dtype>* batch = prefetch_free_.pop();
      load_batch(batch);
#ifndef CPU_ONLY
      if (Caffe::mode() == Caffe::GPU) {
        batch->data_.data().get()->async_gpu_push(stream);
        CUDA_CHECK(cudaStreamSynchronize(stream));
      }
#endif
      prefetch_full_.push(batch);
    }
  } catch (boost::thread_interrupted&) {
    // Interrupted exception is expected on shutdown
  }
#ifndef CPU_ONLY
  if (Caffe::mode() == Caffe::GPU) {
    CUDA_CHECK(cudaStreamDestroy(stream));
  }
#endif
}

template <typename Dtype>
void BasePrefetchingDataLayer<Dtype>::Forward_cpu(
    const vector<Blob<Dtype>*>& bottom, const vector<Blob<Dtype>*>& top) {
  Batch<Dtype>* batch = prefetch_full_.pop("Data layer prefetch queue empty");
  // Reshape to loaded data.
  top[0]->Reshape(batch->data_.num(), batch->data_.channels(),
      batch->data_.height(), batch->data_.width());
  // Copy the data
  caffe_copy(batch->data_.count(), batch->data_.cpu_data(),
             top[0]->mutable_cpu_data());
  DLOG(INFO) << "Prefetch copied";
  if (this->output_labels_) {
    // Reshape to loaded labels.
    top[1]->ReshapeLike(batch->label_);
    // Copy the labels.
    caffe_copy(batch->label_.count(), batch->label_.cpu_data(),
        top[1]->mutable_cpu_data());
  }

  prefetch_free_.push(batch);
}

#ifdef CPU_ONLY
STUB_GPU_FORWARD(BasePrefetchingDataLayer, Forward);
#endif

INSTANTIATE_CLASS(BaseDataLayer);
INSTANTIATE_CLASS(BasePrefetchingDataLayer);

}  // namespace caffe
<|endoftext|>