text:
//------------------------------------------------------------------------------
// Copyright (c) 2018 Hsienchi Kuo (Allen Institute, Hanchuan Peng's team)
// All rights reserved.
//------------------------------------------------------------------------------

/*******************************************************************************
*
*  This library provides functionalities for neuron struct operations, such as crop, register, sample, data extraction, etc.
*  NeuronStructUtil class is desinged to take NeuronTree struct as the input and as well output NeuronTree struct for most of the methods.
*  This class intends to operate on the whole neuron struct level, as 'utility' it is called.
*
*  Many NeuronStructUtil class methods are implemented as static functions. The input NeuronTree is always set to be const so that it will not be modified.
*  A typical function call would need at least three input arguments:
*
*		NeuronStructUtil::func(const NeuronTree& inputTree, NeuronTree& outputTree, other input arguments);
*
********************************************************************************/

#include <iostream>
#include <string>
#include <iterator>
#include <set>
#include <cmath>

#include <boost/filesystem.hpp>

#include "basic_4dimage.h"
#include "NeuronStructUtilities.h"
#include "ImgProcessor.h"

using namespace boost;

NeuronTree NeuronStructUtil::swcRegister(NeuronTree& inputTree, const NeuronTree& refTree)
{
	double xShift, yShift, zShift;
	double xScale, yScale, zScale;

	double xmin = 10000, ymin = 10000, zmin = 10000;
	double xmax = 0, ymax = 0, zmax = 0;
	for (QList<NeuronSWC>::iterator it = inputTree.listNeuron.begin(); it != inputTree.listNeuron.end(); ++it)
	{
		if (it->x < xmin) xmin = it->x;
		if (it->x > xmax) xmax = it->x;
		if (it->y < ymin) ymin = it->y;
		if (it->y > ymax) ymax = it->y;
		if (it->z < zmin) zmin = it->z;
		if (it->z > zmax) zmax = it->z;
	}
	double refXmin = 10000, refYmin = 10000, refZmin = 10000;
	double refXmax = 0, refYmax = 0, refZmax = 0;
	for (QList<NeuronSWC>::const_iterator refIt = refTree.listNeuron.begin(); refIt != refTree.listNeuron.end(); ++refIt)
	{
		if (refIt->x < refXmin) refXmin = refIt->x;
		if (refIt->x > refXmax) refXmax = refIt->x;
		if (refIt->y < refYmin) refYmin = refIt->y;
		if (refIt->y > refYmax) refYmax = refIt->y;
		if (refIt->z < refZmin) refZmin = refIt->z;
		if (refIt->z > refZmax) refZmax = refIt->z;
	}

	xScale = (refXmax - refXmin) / (xmax - xmin);
	yScale = (refYmax - refYmin) / (ymax - ymin);
	zScale = (refZmax - refZmin) / (zmax - zmin);
	xShift = refXmin - xmin * xScale;
	yShift = refYmin - ymin * yScale;
	zShift = refZmin - zmin * zScale;

	NeuronTree outputTree;
	for (int i = 0; i < inputTree.listNeuron.size(); ++i)
	{
		NeuronSWC newNode = inputTree.listNeuron.at(i);
		newNode.x = newNode.x * xScale + xShift;
		newNode.y = newNode.y * yScale + yShift;
		newNode.z = newNode.z * zScale + zShift;
		outputTree.listNeuron.push_back(newNode);
	}

	return outputTree;
}

void NeuronStructUtil::swcSlicer(const NeuronTree& inputTree, vector<NeuronTree>& outputTrees, int thickness)
{
	// -- Dissemble SWC files into "slices." Each outputSWC file represents only 1 z slice.
	// thickness * 2 + 1 = the number of consecutive z slices for one SWC node to appear. This is for the purpose producing continous masks.

	QList<NeuronSWC> inputList = inputTree.listNeuron;
	int zMax = 0;
	ptrdiff_t thicknessPtrDiff = ptrdiff_t(thickness); // Determining how many z sections to be included in 1 single slice.
	for (QList<NeuronSWC>::iterator it = inputList.begin(); it != inputList.end(); ++it)
	{
		it->z = round(it->z);
		if (it->z >= zMax) zMax = it->z;
	}

	QList<NeuronTree> slicedTrees; // Determining number of sliced trees in the list.
	for (int i = 0; i < zMax; ++i)
	{
		NeuronTree nt;
		slicedTrees.push_back(nt);
	}

	for (QList<NeuronSWC>::iterator it = inputList.begin(); it != inputList.end(); ++it)
	{
		NeuronSWC currNode = *it;
		ptrdiff_t sliceNo = ptrdiff_t(it->z);
		(slicedTrees.begin() + sliceNo - 1)->listNeuron.push_back(currNode); // SWC starts with 1.
		float currZ = currNode.z;

		// -- Project +/- thickness slices onto the same plane, making sure the tube can be connected accross planes. -- //
		vector<ptrdiff_t> sectionNums;
		for (ptrdiff_t ptri = 1; ptri <= thicknessPtrDiff; ++ptri)
		{
			ptrdiff_t minusDiff = sliceNo - ptri;
			ptrdiff_t plusDiff = sliceNo + ptri;

			if (minusDiff < 0) continue;
			else sectionNums.push_back(minusDiff);

			if (plusDiff > ptrdiff_t(zMax)) continue;
			else sectionNums.push_back(plusDiff);
		}
		for (vector<ptrdiff_t>::iterator ptrIt = sectionNums.begin(); ptrIt != sectionNums.end(); ++ptrIt)
		{
			//cout << "current node z:" << currNode.z << " " << *ptrIt << "| ";
			NeuronSWC newNode = currNode;
			newNode.z = float(*ptrIt);
			(slicedTrees.begin() + *ptrIt - 1)->listNeuron.push_back(newNode);
		}
		//cout << endl;

		sectionNums.clear();
		// ------------------------------------------------------------------------------------------------------------- //
	}

	for (QList<NeuronTree>::iterator it = slicedTrees.begin(); it != slicedTrees.end(); ++it)
		outputTrees.push_back(*it);
}

map<int, QList<NeuronSWC>> NeuronStructUtil::swcSplitByType(const NeuronTree& inputTree)
{
	map<int, QList<NeuronSWC>> outputNodeTypeMap;
	map<int, boost::container::flat_set<int>> nodeIDsetMap;
	for (QList<NeuronSWC>::const_iterator it = inputTree.listNeuron.begin(); it != inputTree.listNeuron.end(); ++it)
	{
		outputNodeTypeMap[it->type].append(*it);
		nodeIDsetMap[it->type].insert(it->n);
	}
	for (map<int, QList<NeuronSWC>>::iterator mapIt = outputNodeTypeMap.begin(); mapIt != outputNodeTypeMap.end(); ++mapIt)
	{
		for (QList<NeuronSWC>::iterator nodeIt = mapIt->second.begin(); nodeIt != mapIt->second.end(); ++nodeIt)
		{
			if (nodeIt->parent == -1) continue;
			else if (nodeIDsetMap.at(nodeIt->type).find(nodeIt->parent) == nodeIDsetMap.at(nodeIt->type).end()) nodeIt->parent = -1;
		}
	}

	return outputNodeTypeMap;
}

NeuronTree NeuronStructUtil::swcSubtraction(const NeuronTree& targetTree, const NeuronTree& refTree, int type)
{
	boost::container::flat_map<string, QList<NeuronSWC>> targetNodeTileMap;
	boost::container::flat_map<string, QList<NeuronSWC>> refNodeTileMap;
	NeuronStructUtil::nodeTileMapGen(targetTree, targetNodeTileMap);
	NeuronStructUtil::nodeTileMapGen(refTree, refNodeTileMap);

	if (type == 0)
	{
		vector<ptrdiff_t> delLocs;
		for (boost::container::flat_map<string, QList<NeuronSWC>>::iterator targetTileIt = targetNodeTileMap.begin(); targetTileIt != targetNodeTileMap.end(); ++targetTileIt)
		{
			if (refNodeTileMap.find(targetTileIt->first) != refNodeTileMap.end())
			{
				for (QList<NeuronSWC>::iterator checkIt1 = targetTileIt->second.begin(); checkIt1 != targetTileIt->second.end(); ++checkIt1)
				{
					for (QList<NeuronSWC>::iterator checkIt2 = refNodeTileMap.at(targetTileIt->first).begin(); checkIt2 != refNodeTileMap.at(targetTileIt->first).end(); ++checkIt2)
					{
						if (checkIt1->x == checkIt2->x && checkIt1->y == checkIt2->y && checkIt1->z == checkIt2->z)
							delLocs.push_back(ptrdiff_t(checkIt1 - targetTileIt->second.begin()));
					}
				}
			}
			else continue;

			sort(delLocs.rbegin(), delLocs.rend());
			for (vector<ptrdiff_t>::iterator delIt = delLocs.begin(); delIt != delLocs.end(); ++delIt) targetTileIt->second.erase(targetTileIt->second.begin() + *delIt);
			delLocs.clear();
		}
	}
	else
	{
		vector<ptrdiff_t> delLocs;
		for (boost::container::flat_map<string, QList<NeuronSWC>>::iterator targetTileIt = targetNodeTileMap.begin(); targetTileIt != targetNodeTileMap.end(); ++targetTileIt)
		{
			if (refNodeTileMap.find(targetTileIt->first) != refNodeTileMap.end())
			{
				for (QList<NeuronSWC>::iterator checkIt1 = targetTileIt->second.begin(); checkIt1 != targetTileIt->second.end(); ++checkIt1)
				{
					for (QList<NeuronSWC>::iterator checkIt2 = refNodeTileMap.at(targetTileIt->first).begin(); checkIt2 != refNodeTileMap.at(targetTileIt->first).end(); ++checkIt2)
					{
						if (checkIt1->x == checkIt2->x && checkIt1->y == checkIt2->y && checkIt1->z == checkIt2->z && checkIt2->type == type)
							delLocs.push_back(ptrdiff_t(checkIt1 - targetTileIt->second.begin()));
					}
				}
			}
			else continue;

			sort(delLocs.rbegin(), delLocs.rend());
			for (vector<ptrdiff_t>::iterator delIt = delLocs.begin(); delIt != delLocs.end(); ++delIt) targetTileIt->second.erase(targetTileIt->second.begin() + *delIt);
			delLocs.clear();
		}
	}

	NeuronTree outputTree;
	for (boost::container::flat_map<string, QList<NeuronSWC>>::iterator mapIt = targetNodeTileMap.begin(); mapIt != targetNodeTileMap.end(); ++mapIt)
		outputTree.listNeuron.append(mapIt->second);

	return outputTree;
}

// ========================================== SWC Profiling Methods =========================================
QList<NeuronSWC> NeuronStructUtil::removeRednNode(const NeuronTree& inputTree)
{
	// -- This method removes dupliated nodes.

	boost::container::flat_map<string, QList<NeuronSWC>> nodeTileMap;
	NeuronStructUtil::nodeTileMapGen(inputTree, nodeTileMap);
	cout << "SWC tile number: " << nodeTileMap.size() << endl;

	QList<NeuronSWC> outputNodeList;
	cout << "processing tile: ";
	int tileCount = 0;
	for (boost::container::flat_map<string, QList<NeuronSWC>>::iterator tileIt = nodeTileMap.begin(); tileIt != nodeTileMap.end(); ++tileIt)
	{
		++tileCount;
		cout << tileCount << " ";
		bool redun = true;
		while (redun)
		{
			for (QList<NeuronSWC>::iterator it1 = tileIt->second.begin(); it1 != tileIt->second.end(); ++it1)
			{
				for (QList<NeuronSWC>::iterator it2 = tileIt->second.begin(); it2 != tileIt->second.end(); ++it2)
				{
					if (it2 == it1) continue;

					if (it2->x == it1->x && it2->y == it1->y && it2->z == it1->z)
					{
						if (it2->parent == -1)
						{
							tileIt->second.erase(it2);
							goto NODE_DELETED;
						}
					}
				}
			}
			redun = false;

		NODE_DELETED:
			continue;
		}

		outputNodeList.append(tileIt->second);
	}
	cout << endl;

	return outputNodeList;
}

NeuronTree NeuronStructUtil::swcZclenUP(const NeuronTree& inputTree, float zThre)
{
	// -- This method removes signal nodes from different depths that share the same x-y coordinates due to 2D connected component procedure for 3D structure.
	//      zThre: depth window allowance.
	//      Nodes that share the same x-y coordinates but belong to different zThre groups will still be considered different nodes.

	map<string, vector<NeuronSWC>> xyLabeledNodeMap;
	for (QList<NeuronSWC>::const_iterator it = inputTree.listNeuron.begin(); it != inputTree.listNeuron.end(); ++it)
	{
		string xLabel = to_string(int(it->x / 2));
		string yLabel = to_string(int(it->y / 2));
		string labelKey = xLabel + "_" + yLabel;
		if (xyLabeledNodeMap.find(labelKey) != xyLabeledNodeMap.end()) xyLabeledNodeMap[labelKey].push_back(*it);
		else
		{
			vector<NeuronSWC> newSet;
			newSet.push_back(*it);
			xyLabeledNodeMap.insert(pair<string, vector<NeuronSWC>>(labelKey, newSet));
		}
	}

	NeuronTree outputTree;
	for (map<string, vector<NeuronSWC>>::iterator it = xyLabeledNodeMap.begin(); it != xyLabeledNodeMap.end(); ++it)
	{
		boost::container::flat_map<float, NeuronSWC> zSortedNodes; // boost::container::flat_map is vector based, so it can do pointer arithmetic.
		if (it->second.size() == 1)
		{
			outputTree.listNeuron.push_back(*(it->second.begin()));
			continue;
		}
		else
		{
			for (vector<NeuronSWC>::iterator nodeIt = it->second.begin(); nodeIt != it->second.end(); ++nodeIt)
				zSortedNodes.insert(pair<float, NeuronSWC>(nodeIt->z, *nodeIt));

			boost::container::flat_map<float, NeuronSWC>::iterator startIt = zSortedNodes.begin();
			for (boost::container::flat_map<float, NeuronSWC>::iterator zIt = zSortedNodes.begin() + 1; zIt != zSortedNodes.end(); ++zIt)
			{
				if (zIt->second.z - (zIt - 1)->second.z > zThre)
				{
					ptrdiff_t steps = zIt - startIt;
					ptrdiff_t selectedLoc = ptrdiff_t(int(steps) / 2);
					outputTree.listNeuron.push_back((startIt + selectedLoc)->second);
					startIt = zIt;
				}
			}
			if (startIt == zSortedNodes.begin())
			{
				ptrdiff_t selectedLoc = ptrdiff_t(int((zSortedNodes.end() - zSortedNodes.begin()) / 2));
				outputTree.listNeuron.push_back((startIt + selectedLoc)->second);
			}
		}
	}

	return outputTree;
}

map<string, float> NeuronStructUtil::selfNodeDist(const QList<NeuronSWC>& inputNodeList)
{
	// -- This method computes the distance of every node to its nearest node in the given swc.
	// -- The output is a map that contains 4 measures: mean, std, var, median.

	boost::container::flat_map<string, vector<NeuronSWC>> labeledNodeMap;
	NeuronStructUtil::nodeTileMapGen(inputNodeList, labeledNodeMap, 30);

	float distSum = 0;
	vector<float> distVec;
	for (boost::container::flat_map<string, vector<NeuronSWC>>::iterator it = labeledNodeMap.begin(); it != labeledNodeMap.end(); ++it)
	{
		if (it->second.size() == 1)
		{
			float dist = 10000;
			for (QList<NeuronSWC>::const_iterator nodeIt = inputNodeList.begin(); nodeIt != inputNodeList.end(); ++nodeIt)
			{
				if (it->second.begin()->x == nodeIt->x && it->second.begin()->y == nodeIt->y && it->second.begin()->z == nodeIt->z)
					continue;

				float tempDist = sqrtf((it->second.begin()->x - nodeIt->x) * (it->second.begin()->x - nodeIt->x) +
					(it->second.begin()->y - nodeIt->y) * (it->second.begin()->y - nodeIt->y) +
					(it->second.begin()->z - nodeIt->z) * (it->second.begin()->z - nodeIt->z) * zRATIO * zRATIO);
				if (tempDist < dist) dist = tempDist;
			}
			distVec.push_back(dist);
			distSum = distSum + dist;
			continue;
		}

		for (vector<NeuronSWC>::iterator nodeIt1 = it->second.begin(); nodeIt1 != it->second.end(); ++nodeIt1)
		{
			float dist = 10000;
			for (vector<NeuronSWC>::iterator nodeIt2 = it->second.begin(); nodeIt2 != it->second.end(); ++nodeIt2)
			{
				if (nodeIt1 == nodeIt2) continue;

				float tempDist = sqrtf((nodeIt1->x - nodeIt2->x) * (nodeIt1->x - nodeIt2->x) +
					(nodeIt1->y - nodeIt2->y) * (nodeIt1->y - nodeIt2->y) +
					(nodeIt1->z - nodeIt2->z) * (nodeIt1->z - nodeIt2->z) * zRATIO * zRATIO);
				if (tempDist < dist) dist = tempDist;
			}
			distVec.push_back(dist);
			distSum = distSum + dist;
		}
	}

	float distMean = distSum / float(distVec.size());
	float distVarSum = 0;
	for (vector<float>::iterator it = distVec.begin(); it != distVec.end(); ++it) distVarSum = distVarSum + (*it - distMean) * (*it - distMean);
	float distVar = distVarSum / float(distVec.size());
	float distStd = sqrtf(distVar);
	sort(distVec.begin(), distVec.end());
	float distMedian = float(distVec.at(floor(distVec.size() / 2)));

	map<string, float> outputMap;
	outputMap.insert(pair<string, float>("mean", distMean));
	outputMap.insert(pair<string, float>("std", distStd));
	outputMap.insert(pair<string, float>("var", distVar));
	outputMap.insert(pair<string, float>("median", distMedian));

	return outputMap;
}

NeuronTree NeuronStructUtil::swcIdentityCompare(const NeuronTree& subjectTree, const NeuronTree& refTree, float distThre, float nodeTileLength)
{
	// -- This method identifies positive signal nodes from noise with given reference NeuronTree.
	// -- radius: tile length
	// -- distThre: distance threshold for nearest node pair

	map<string, vector<NeuronSWC>> gridSWCmap; // Better use vector instead of set here, as set by default sorts the elements.
	// This can cause complication if the element is a data struct.

	NeuronStructUtil::nodeTileMapGen(refTree, gridSWCmap, nodeTileLength);

	NeuronTree outputTree;
	NeuronTree refConfinedFilteredTree;
	for (QList<NeuronSWC>::const_iterator suIt = subjectTree.listNeuron.begin(); suIt != subjectTree.listNeuron.end(); ++suIt)
	{
		string xLabel = to_string(int((suIt->x) / (nodeTileLength)));
		string yLabel = to_string(int((suIt->y) / (nodeTileLength)));
		string zLabel = to_string(int((suIt->z) / (nodeTileLength / zRATIO)));
		string keyLabel = xLabel + "_" + yLabel + "_" + zLabel;

		if (gridSWCmap.find(keyLabel) != gridSWCmap.end())
		{
			bool identified = false;
			for (vector<NeuronSWC>::iterator nodeIt = gridSWCmap[keyLabel].begin(); nodeIt != gridSWCmap[keyLabel].end(); ++nodeIt)
			{
				float dist = sqrt((nodeIt->x - suIt->x) * (nodeIt->x - suIt->x) + (nodeIt->y - suIt->y) * (nodeIt->y - suIt->y) +
					zRATIO * zRATIO * (nodeIt->z - suIt->z) * (nodeIt->z - suIt->z));

				if (dist <= distThre)
				{
					outputTree.listNeuron.push_back(*suIt);
					(outputTree.listNeuron.end() - 1)->type = 2;
					identified = true;
					break;
				}
			}

			if (!identified)
			{
				outputTree.listNeuron.push_back(*suIt);
				(outputTree.listNeuron.end() - 1)->type = 3;
			}
		}
		else refConfinedFilteredTree.listNeuron.push_back(*suIt);
	}

	return outputTree;
}
// ===================================== END of [SWC Profiling Methods] =====================================

// =================================== SWC <-> Connected Components ====================================
vector<connectedComponent> NeuronStructUtil::swc2signal2DBlobs(const NeuronTree& inputTree)
{
	// -- Finds signal blobs "slice by slice" from input NeuronTree. Each slice is independent to one another.
	// -- Therefore, the same real blobs in 3D are consists of certain amount of 2D "blob slices" produced by this method.
	// -- Each 2D blob slice accounts for 1 ImgAnalyzer::connectedComponent.

	vector<NeuronSWC> allNodes;
	for (QList<NeuronSWC>::const_iterator it = inputTree.listNeuron.begin(); it != inputTree.listNeuron.end(); ++it) allNodes.push_back(*it);

	vector<connectedComponent> connComps2D;
	int islandCount = 0;
	cout << "number of SWC nodes processed: ";
	for (vector<NeuronSWC>::iterator nodeIt = allNodes.begin(); nodeIt != allNodes.end(); ++nodeIt)
	{
		if (int(nodeIt - allNodes.begin()) % 10000 == 0) cout << int(nodeIt - allNodes.begin()) << " ";
		for (vector<connectedComponent>::iterator connIt = connComps2D.begin(); connIt != connComps2D.end(); ++connIt)
		{
			if (connIt->coordSets.empty()) continue;
			else if (int(nodeIt->z) == connIt->coordSets.begin()->first)
			{
				for (set<vector<int>>::iterator dotIt = connIt->coordSets[int(nodeIt->z)].begin(); dotIt != connIt->coordSets[int(nodeIt->z)].end(); ++dotIt)
				{
					if (int(nodeIt->x) <= dotIt->at(0) + 1 && int(nodeIt->x) >= dotIt->at(0) - 1 &&
						int(nodeIt->y) <= dotIt->at(1) + 1 && int(nodeIt->y) >= dotIt->at(1) - 1)
					{
						vector<int> newCoord(3);
						newCoord[0] = int(nodeIt->x);
						newCoord[1] = int(nodeIt->y);
						newCoord[2] = int(nodeIt->z);
						connIt->coordSets[newCoord[2]].insert(newCoord);
						connIt->size = connIt->size + 1;

						if (newCoord[0] < connIt->xMin) connIt->xMin = newCoord[0];
						else if (newCoord[0] > connIt->xMax) connIt->xMax = newCoord[0];

						if (newCoord[1] < connIt->yMin) connIt->yMin = newCoord[1];
						else if (newCoord[1] > connIt->yMax) connIt->yMax = newCoord[1];

						goto NODE_INSERTED;
					}
				}
			}
		}

		{
			++islandCount;
			connectedComponent newIsland;
			newIsland.islandNum = islandCount;
			vector<int> newCoord(3);
			newCoord[0] = int(nodeIt->x);
			newCoord[1] = int(nodeIt->y);
			newCoord[2] = int(nodeIt->z);
			set<vector<int>> coordSet;
			coordSet.insert(newCoord);
			newIsland.coordSets.insert(pair<int, set<vector<int>>>(newCoord[2], coordSet));
			newIsland.xMax = newCoord[0];
			newIsland.xMin = newCoord[0];
			newIsland.yMax = newCoord[1];
			newIsland.yMin = newCoord[1];
			newIsland.zMin = newCoord[2];
			newIsland.zMax = newCoord[2];
			newIsland.size = 1;
			connComps2D.push_back(newIsland);
		}

	NODE_INSERTED:
		continue;
	}
	cout << endl << endl;

	vector<float> center(3);
	for (vector<connectedComponent>::iterator it = connComps2D.begin(); it != connComps2D.end(); ++it)
		ImgAnalyzer::ChebyshevCenter_connComp(*it);

	return connComps2D;
}

vector<connectedComponent> NeuronStructUtil::swc2signal3DBlobs(const NeuronTree& inputTree)
{
	// -- This method is a wrapper of NeuronStructUtil::swc2signal2DBlobs and NeuronStructUtil::merge2DConnComponent.
	// -- It produces 3D signal blobs by calling the two swc2signal2DBlobs and merge2DConnComponent sequentially.

	vector<connectedComponent> inputConnCompList = this->swc2signal2DBlobs(inputTree);
	vector<connectedComponent> outputConnCompList = this->merge2DConnComponent(inputConnCompList);

	return outputConnCompList;
}

vector<connectedComponent> NeuronStructUtil::merge2DConnComponent(const vector<connectedComponent>& inputConnCompList)
{
	// -- This method finds 3D signal blobs by grouping 2D signal blobs together, which are produced by NeuronStructUtil::swc2signal2DBlobs.
	// -- The approach is consists of 2 stages:
	//		1. Identifying the same 3D blobs slice by slice.
	//		2. Merging 3D blobs that contain the same 2D blobs.

	cout << "Merging 2D signal blobs.." << endl;
	cout << "-- processing slice ";

	vector<connectedComponent> outputConnCompList;

	int zMax = 0;

	// -- I notice that boost's container templates are able to lift up the performace by ~30%.
	boost::container::flat_map<int, boost::container::flat_set<int>> b2Dtob3Dmap;
	b2Dtob3Dmap.clear();
	boost::container::flat_map<int, boost::container::flat_set<int>> b3Dcomps;
	b3Dcomps.clear();
	// ---------------------------------------------------------------------------------------

	// --------- First slice, container initiation --------------
	int sliceBlobCount = 0;
	for (vector<connectedComponent>::const_iterator it = inputConnCompList.begin(); it != inputConnCompList.end(); ++it)
	{
		if (it->coordSets.begin()->first > zMax) zMax = it->coordSets.begin()->first;

		if (it->coordSets.begin()->first == 0)
		{
			++sliceBlobCount;
			boost::container::flat_set<int> blob3D;
			blob3D.insert(sliceBlobCount);
			b2Dtob3Dmap.insert(pair<int, boost::container::flat_set<int>>(it->islandNum, blob3D));
			boost::container::flat_set<int> comps;
			comps.insert(it->islandNum);
			b3Dcomps[sliceBlobCount] = comps;
		}
	}
	// -----------------------------------------------------------

	// ------------------------------------------- Merge 2D blobs from 2 adjacent slices -------------------------------------------
	vector<connectedComponent> currSliceConnComps;
	vector<connectedComponent> preSliceConnComps;
	size_t increasedSize;
	for (int i = 1; i <= zMax; ++i)
	{
		currSliceConnComps.clear();
		preSliceConnComps.clear();

		increasedSize = 0;
		for (vector<connectedComponent>::const_iterator it = inputConnCompList.begin(); it != inputConnCompList.end(); ++it)
			if (it->coordSets.begin()->first == i) currSliceConnComps.push_back(*it);
		if (currSliceConnComps.empty())
		{
			cout << i << "->0 ";
			continue;
		}

		cout << i << "->";
		for (vector<connectedComponent>::const_iterator it = inputConnCompList.begin(); it != inputConnCompList.end(); ++it)
			if (it->coordSets.begin()->first == i - 1) preSliceConnComps.push_back(*it);
		if (preSliceConnComps.empty())
		{
			for (vector<connectedComponent>::iterator newCompsIt = currSliceConnComps.begin(); newCompsIt != currSliceConnComps.end(); ++newCompsIt)
			{
				++sliceBlobCount;
				boost::container::flat_set<int> blob3D;
				blob3D.insert(sliceBlobCount);
				b2Dtob3Dmap.insert(pair<int, boost::container::flat_set<int>>(newCompsIt->islandNum, blob3D));
				boost::container::flat_set<int> comps;
				comps.insert(newCompsIt->islandNum);
				b3Dcomps[sliceBlobCount] = comps;
				increasedSize = increasedSize + comps.size();
			}
			continue;
		}

		for (vector<connectedComponent>::iterator currIt = currSliceConnComps.begin(); currIt != currSliceConnComps.end(); ++currIt)
		{
			bool merged = false;
			for (vector<connectedComponent>::iterator preIt = preSliceConnComps.begin(); preIt != preSliceConnComps.end(); ++preIt)
			{
				if (currIt->xMin > preIt->xMax + 2 || currIt->xMax < preIt->xMin - 2 ||
					currIt->yMin > preIt->yMax + 2 || currIt->yMax < preIt->yMin - 2) continue;

				for (set<vector<int>>::iterator currDotIt = currIt->coordSets.begin()->second.begin(); currDotIt != currIt->coordSets.begin()->second.end(); ++currDotIt)
				{
					for (set<vector<int>>::iterator preDotIt = preIt->coordSets.begin()->second.begin(); preDotIt != preIt->coordSets.begin()->second.end(); ++preDotIt)
					{
						if (currDotIt->at(0) >= preDotIt->at(0) - 1 && currDotIt->at(0) <= preDotIt->at(0) + 1 &&
							currDotIt->at(1) >= preDotIt->at(1) - 1 && currDotIt->at(1) <= preDotIt->at(1) + 1)
						{
							merged = true;
							boost::container::flat_set<int> asso3Dblob = b2Dtob3Dmap[preIt->islandNum];
							b2Dtob3Dmap.insert(pair<int, boost::container::flat_set<int>>(currIt->islandNum, asso3Dblob));
							for (boost::container::flat_set<int>::iterator blob3DIt = asso3Dblob.begin(); blob3DIt != asso3Dblob.end(); ++blob3DIt)
								b3Dcomps[*blob3DIt].insert(currIt->islandNum);

							goto BLOB_MERGED;
						}
					}
				}

				if (!merged) continue;

			BLOB_MERGED:
				merged = true;
			}

			if (!merged)
			{
				++sliceBlobCount;
				boost::container::flat_set<int> newBlob3D;
				newBlob3D.insert(sliceBlobCount);
				b2Dtob3Dmap.insert(pair<int, boost::container::flat_set<int>>(currIt->islandNum, newBlob3D));
				boost::container::flat_set<int> comps;
				comps.insert(currIt->islandNum);
				b3Dcomps[sliceBlobCount] = comps;
				increasedSize = increasedSize + comps.size();
			}
		}
		cout << increasedSize << ", ";
	}
	cout << endl << endl;
	cout << "Done merging 2D blobs from every 2 slices." << endl << endl;
	// ---------------------------------------- END of [Merge 2D blobs from 2 adjacent slices] -------------------------------------------

	// ------------------------------------------ Merge 3D blobs --------------------------------------------
	cout << "Now merging 3D blobs.." << endl;
	cout << "-- oroginal 3D blobs number: " << b3Dcomps.size() << endl;
	bool mergeFinish = false;
	int currBaseBlob = 1;
	while (!mergeFinish)
	{
		for (boost::container::flat_map<int, boost::container::flat_set<int>>::iterator checkIt1 = b3Dcomps.begin(); checkIt1 != b3Dcomps.end(); ++checkIt1)
		{
			if (checkIt1->first < currBaseBlob) continue;
			for (boost::container::flat_map<int, boost::container::flat_set<int>>::iterator checkIt2 = checkIt1; checkIt2 != b3Dcomps.end(); ++checkIt2)
			{
				if (checkIt2 == checkIt1) continue;
				for (boost::container::flat_set<int>::iterator member1 = checkIt1->second.begin(); member1 != checkIt1->second.end(); ++member1)
				{
					for (boost::container::flat_set<int>::iterator member2 = checkIt2->second.begin(); member2 != checkIt2->second.end(); ++member2)
					{
						if (*member2 == *member1)
						{
							checkIt1->second.insert(checkIt2->second.begin(), checkIt2->second.end());
							b3Dcomps.erase(checkIt2);
							currBaseBlob = checkIt1->first;
							cout << "  merging blob " << checkIt1->first << " and blob " << checkIt2->first << endl;
							goto MERGED;
						}
					}
				}
			}
		}
		mergeFinish = true;

	MERGED:
		continue;
	}
	cout << "-- new 3D blobs number: " << b3Dcomps.size() << endl;
	// --------------------------------------- END of [Merge 3D blobs] --------------------------------------

	map<int, connectedComponent> compsMap;
	for (vector<connectedComponent>::const_iterator inputIt = inputConnCompList.begin(); inputIt != inputConnCompList.end(); ++inputIt)
		compsMap.insert(pair<int, connectedComponent>(inputIt->islandNum, *inputIt));
	int newLabel = 0;
	for (boost::container::flat_map<int, boost::container::flat_set<int>>::iterator it = b3Dcomps.begin(); it != b3Dcomps.end(); ++it)
	{
		++newLabel;
		connectedComponent newComp;
		newComp.islandNum = newLabel;
		newComp.size = 0;
		newComp.xMax = 0; newComp.xMin = 0;
		newComp.yMax = 0; newComp.yMin = 0;
		newComp.zMax = 0; newComp.zMin = 0;
		for (boost::container::flat_set<int>::iterator it2 = it->second.begin(); it2 != it->second.end(); ++it2)
		{
			newComp.coordSets.insert(pair<int, set<vector<int>>>(compsMap[*it2].coordSets.begin()->first, compsMap[*it2].coordSets.begin()->second));
			newComp.xMax = getMax(newComp.xMax, compsMap[*it2].xMax);
			newComp.xMin = getMin(newComp.xMin, compsMap[*it2].xMin);
			newComp.yMax = getMax(newComp.yMax, compsMap[*it2].yMax);
			newComp.yMin = getMin(newComp.yMin, compsMap[*it2].yMin);
			newComp.zMax = getMax(newComp.zMax, compsMap[*it2].zMax);
			newComp.zMin = getMin(newComp.zMin, compsMap[*it2].zMin);
			newComp.size = newComp.size + compsMap[*it2].size;
		}

		outputConnCompList.push_back(newComp);
	}

	return outputConnCompList;
}
// =============================== END of [SWC <-> Connected Components] ===============================

// ==================================== Neuron Struct Clustering Methods ========================================
vector<connectedComponent> NeuronStructUtil::swc2clusters_distance(const NeuronTree& inputTree, float dist)
{
	QList<NeuronSWC> inputList = inputTree.listNeuron;
	vector<connectedComponent> outputConnCompList;
	outputConnCompList.clear();
	connectedComponent connComp1;
	vector<int> node1Coord(3);
	node1Coord.at(0) = int(inputList.begin()->x);
	node1Coord.at(1) = int(inputList.begin()->y);
	node1Coord.at(2) = int(inputList.begin()->z);
	set<vector<int>> connComp1Set;
	connComp1Set.insert(node1Coord);
	connComp1.coordSets.insert(pair<int, set<vector<int>>>(node1Coord.at(2), connComp1Set));
	connComp1.size = 1;
	outputConnCompList.push_back(connComp1);
	inputList.erase(inputList.begin());

	while (inputList.size() > 0)
	{
		for (QList<NeuronSWC>::iterator nodeIt = inputList.begin(); nodeIt != inputList.end(); ++nodeIt)
		{
			for (vector<connectedComponent>::iterator cluIt = outputConnCompList.begin(); cluIt != outputConnCompList.end(); ++cluIt)
			{
				for (map<int, set<vector<int>>>::iterator zIt = cluIt->coordSets.begin(); zIt != cluIt->coordSets.end(); ++zIt)
				{
					for (set<vector<int>>::iterator cluNodeIt = zIt->second.begin(); cluNodeIt != zIt->second.end(); ++cluNodeIt)
					{
						if (sqrt((nodeIt->x - float(cluNodeIt->at(0))) * (nodeIt->x - float(cluNodeIt->at(0))) +
							     (nodeIt->y - float(cluNodeIt->at(1))) * (nodeIt->y - float(cluNodeIt->at(1))) +
							     (nodeIt->z - float(cluNodeIt->at(2))) * (nodeIt->z - float(cluNodeIt->at(2))) * zRATIO * zRATIO) <= dist)
						{
							if (cluIt->coordSets.find(nodeIt->z) != cluIt->coordSets.end())
							{
								vector<int> newPoint(3);
								newPoint.at(0) = int(nodeIt->x);
								newPoint.at(1) = int(nodeIt->y);
								newPoint.at(2) = int(nodeIt->z);
								cluIt->coordSets[newPoint.at(2)].insert(newPoint);
								++cluIt->size;
							}
							else
							{
								vector<int> newPoint(3);
								newPoint.at(0) = int(nodeIt->x);
								newPoint.at(1) = int(nodeIt->y);
								newPoint.at(2) = int(nodeIt->z);
								set<vector<int>> newSet;
								newSet.insert(newPoint);
								cluIt->coordSets.insert(pair<int, set<vector<int>>>(newPoint.at(2), newSet));
								++cluIt->size;
							}

							inputList.erase(nodeIt);
							goto NODE_PROCESSED;
						}
					}
				}
			}

			connectedComponent newComp;
			vector<int> newCompPoint(3);
			newCompPoint.at(0) = int(nodeIt->x);
			newCompPoint.at(1) = int(nodeIt->y);
			newCompPoint.at(2) = int(nodeIt->z);
			set<vector<int>> newCompSet;
			newCompSet.insert(newCompPoint);
			newComp.coordSets.insert(pair<int, set<vector<int>>>(newCompPoint.at(2), newCompSet));
			newComp.size = 1;
			outputConnCompList.push_back(newComp);
			inputList.erase(nodeIt);
			break;
		}

	NODE_PROCESSED:
		continue;
	}

	vector<connectedComponent>::iterator mergeIt;
	vector<connectedComponent>::iterator currCompIt;
	while (1)
	{
		for (vector<connectedComponent>::iterator compBaseIt = outputConnCompList.begin(); compBaseIt != outputConnCompList.end(); ++compBaseIt)
		{
			for (vector<connectedComponent>::iterator checkCompIt = compBaseIt + 1; checkCompIt != outputConnCompList.end(); ++checkCompIt)
			{
				for (map<int, set<vector<int>>>::iterator checkIt = checkCompIt->coordSets.begin(); checkIt != checkCompIt->coordSets.end(); ++checkIt)
				{
					for (set<vector<int>>::iterator checkNodeIt = checkIt->second.begin(); checkNodeIt != checkIt->second.end(); ++checkNodeIt)
					{
						for (map<int, set<vector<int>>>::iterator currIt = compBaseIt->coordSets.begin(); currIt != compBaseIt->coordSets.end(); ++currIt)
						{
							for (set<vector<int>>::iterator currNodeIt = currIt->second.begin(); currNodeIt != currIt->second.end(); ++currNodeIt)
							{
								if (sqrt((float(currNodeIt->at(0)) - float(checkNodeIt->at(0))) * (float(currNodeIt->at(0)) - float(checkNodeIt->at(0))) +
										 (float(currNodeIt->at(1)) - float(checkNodeIt->at(1))) * (float(currNodeIt->at(1)) - float(checkNodeIt->at(1))) +
										 (float(currNodeIt->at(2)) - float(checkNodeIt->at(2))) * (float(currNodeIt->at(2)) - float(checkNodeIt->at(2))) * zRATIO * zRATIO) <= dist)
								{
									mergeIt = checkCompIt;
									currCompIt = compBaseIt;
									goto CLUSTER_MERGE;
								}
							}
						}
					}
				}
			}
		}
		break;

	CLUSTER_MERGE:
		{
			for (map<int, set<vector<int>>>::iterator zIt = mergeIt->coordSets.begin(); zIt != mergeIt->coordSets.end(); ++zIt)
			{
				for (set<vector<int>>::iterator nodeIt = zIt->second.begin(); nodeIt != zIt->second.end(); ++nodeIt)
				{
					if (currCompIt->coordSets.find(nodeIt->at(0)) != currCompIt->coordSets.end())
					{
						vector<int> newPoint(3);
						newPoint.at(0) = nodeIt->at(0);
						newPoint.at(1) = nodeIt->at(1);
						newPoint.at(2) = nodeIt->at(2);
						currCompIt->coordSets[newPoint.at(2)].insert(newPoint);
					}
					else
					{
						vector<int> newPoint(3);
						newPoint.at(0) = nodeIt->at(0);
						newPoint.at(1) = nodeIt->at(1);
						newPoint.at(2) = nodeIt->at(2);
						set<vector<int>> newSet;
						newSet.insert(newPoint);
						currCompIt->coordSets.insert(pair<int, set<vector<int>>>(newPoint.at(2), newSet));
					}
				}
			}

			outputConnCompList.erase(mergeIt);
			continue;
		}
	}

	return outputConnCompList;
}
// ================================ END of [Neuron Struct Clustering Methods] ===================================

/* =================================== Volumetric SWC sampling methods =================================== */
void NeuronStructUtil::sigNode_Gen(const NeuronTree& inputTree, NeuronTree& outputTree, float ratio, float distance)
{
	// -- Randomly generate signal patches within given distance range
	//      ratio:    the ratio of targeted number of upsampling nodes to the number of maunal nodes in the inputTree
	//      distance: the radius allowed with SWC node centered

	cout << "target signal patch number: " << int(inputTree.listNeuron.size() * ratio) << endl;
	int nodeCount = 0;
	for (QList<NeuronSWC>::const_iterator it = inputTree.listNeuron.begin(); it != inputTree.listNeuron.end(); ++it)
	{
		outputTree.listNeuron.push_back(*it);
		(outputTree.listNeuron.end() - 1)->parent = -1;
		(outputTree.listNeuron.end() - 1)->type = 2;
		int foldCount = 2;
		while (foldCount <= ratio)
		{
			int randNumX = rand() % int(distance * 2) + int(it->x - distance);
			int randNumY = rand() % int(distance * 2) + int(it->y - distance);
			int randNumZ = rand() % int(distance * 2) + int(it->z - distance);

			++nodeCount;
			if (nodeCount % 10000 == 0) cout << nodeCount << " signal nodes generated." << endl;

			NeuronSWC newNode;
			newNode.x = randNumX;
			newNode.y = randNumY;
			newNode.z = randNumZ;
			newNode.type = 2;
			newNode.radius = 1;
			newNode.parent = -1;
			outputTree.listNeuron.push_back(newNode);

			++foldCount;
		}
	}
}

void NeuronStructUtil::bkgNode_Gen(const NeuronTree& inputTree, NeuronTree& outputTree, int dims[], float ratio, float distance)
{
	// -- Randomly generate background patches away from the forbidden distance
	//      dims:     image stack dimension
	//      ratio:    the ratio of targeted number of background nodes to the number of manual nodes in the inputTree
	//      distance: the forbidden distance from each SWC node

	QList<NeuronSWC> neuronList = inputTree.listNeuron;
	int targetBkgNodeNum = int(neuronList.size() * ratio);
	cout << targetBkgNodeNum << " targeted bkg nodes to ge generated." << endl;
	int bkgNodeCount = 0;
	while (bkgNodeCount <= targetBkgNodeNum)
	{
		int randNumX = rand() % (dims[0] - 20) + 10;
		int randNumY = rand() % (dims[1] - 20) + 10;
		int randNumZ = rand() % dims[2];

		bool flag = false;
		for (QList<NeuronSWC>::iterator it = neuronList.begin(); it != neuronList.end(); ++it)
		{
			float distSqr;
			float diffx = float(randNumX) - it->x;
			float diffy = float(randNumY) - it->y;
			float diffz = float(randNumZ) - it->z;
			distSqr = diffx * diffx + diffy * diffy + diffz * diffz;

			if (distSqr <= distance * distance)
			{
				flag = true;
				break;
			}
		}

		if (flag == false)
		{
			++bkgNodeCount;
			if (bkgNodeCount % 10000 == 0) cout << bkgNodeCount << " bkg nodes generated." << endl;

			NeuronSWC newBkgNode;
			newBkgNode.x = randNumX;
			newBkgNode.y = randNumY;
			newBkgNode.z = randNumZ;
			newBkgNode.type = 3;
			newBkgNode.radius = 1;
			newBkgNode.parent = -1;
			outputTree.listNeuron.push_back(newBkgNode);
		}
	}
}

void NeuronStructUtil::bkgNode_Gen_somaArea(const NeuronTree& intputTree, NeuronTree& outputTree, int xLength, int yLength, int zLength, float ratio, float distance)
{
	// -- Randomly generate background patches away from the forbidden distance. This method aims to reinforce the background recognition near soma area.
	//      xLength, yLength, zLength: decide the range to apply with soma centered
	//      ratio:    the ratio of targeted number of soma background nodes to the number of manual nodes in the inputTree
	//      distance: the forbidden distance from each SWC node

	NeuronSWC somaNode;
	for (QList<NeuronSWC>::const_iterator it = intputTree.listNeuron.begin(); it != intputTree.listNeuron.end(); ++it)
	{
		if (it->parent == -1)
		{
			somaNode = *it;
			break;
		}
	}
	float xlb = somaNode.x - float(xLength);
	float xhb = somaNode.x + float(xLength);
	float ylb = somaNode.y - float(yLength);
	float yhb = somaNode.y + float(yLength);
	float zlb = somaNode.z - float(zLength);
	float zhb = somaNode.z + float(zLength);

	list<NeuronSWC> confinedNodes;
	for (QList<NeuronSWC>::const_iterator it = intputTree.listNeuron.begin(); it != intputTree.listNeuron.end(); ++it)
		if (xlb <= it->x && xhb >= it->x && ylb <= it->y && yhb >= it->y && zlb <= it->z && zhb >= it->z) confinedNodes.push_back(*it);

	int targetBkgNodeNum = int(float(xLength) * float(yLength) * float(zLength) * ratio);
	cout << targetBkgNodeNum << " targeted bkg nodes to ge generated." << endl;
	int bkgNodeCount = 0;
	while (bkgNodeCount <= targetBkgNodeNum)
	{
		int randNumX = rand() % int(xhb - xlb + 1) + int(xlb);
		int randNumY = rand() % int(yhb - ylb + 1) + int(ylb);
		int randNumZ = rand() % int(zhb - zlb + 1) + int(zlb);

		bool flag = false;
		for (list<NeuronSWC>::iterator it = confinedNodes.begin(); it != confinedNodes.end(); ++it)
		{
			float distSqr;
			float diffx = float(randNumX) - it->x;
			float diffy = float(randNumY) - it->y;
			float diffz = float(randNumZ) - it->z;
			distSqr = diffx * diffx + diffy * diffy + diffz * diffz;

			if (distSqr <= distance * distance)
			{
				flag = true;
				break;
			}
		}

		if (flag == false)
		{
			++bkgNodeCount;
			if (bkgNodeCount % 10000 == 0) cout << bkgNodeCount << " bkg nodes generated within the soma area." << endl;

			NeuronSWC newBkgNode;
			newBkgNode.x = randNumX;
			newBkgNode.y = randNumY;
			newBkgNode.z = randNumZ;
			newBkgNode.type = 3;
			newBkgNode.radius = 1;
			newBkgNode.parent = -1;
			outputTree.listNeuron.push_back(newBkgNode);
		}
	}
}
/* =================================== Volumetric SWC sampling methods =================================== */


text:
#include <mapnik/version.hpp>

#include <mapnik/map.hpp>
#include <mapnik/datasource_cache.hpp>
#include <mapnik/font_engine_freetype.hpp>
#include <mapnik/agg_renderer.hpp>
#include <mapnik/expression.hpp>
#include <mapnik/color_factory.hpp>
#if MAPNIK_MAJOR_VERSION >= 3
 #include <mapnik/image.hpp>
 #include <mapnik/image_view_any.hpp>
 #define image_32 image_rgba8
#else
 #include <mapnik/image_data.hpp>
 #include <mapnik/graphics.hpp>
#endif
#include <mapnik/image_util.hpp>
#include <mapnik/image_view.hpp>
#include <mapnik/config_error.hpp>
#include <mapnik/load_map.hpp>
#include <mapnik/box2d.hpp>

#include <boost/filesystem.hpp>
#include <boost/format.hpp>

#include <fstream>
#include <cstdint>
#include <cstring>
#include <cstdio>

#include <dirent.h>
#include <sys/stat.h>
#include <sys/types.h>

#include "h2o.h"

#include "proj.hpp"
#include "path-mapper.h"
#include "tile/mapnik-bridge.h"
#include "tile/mkdir-p.h"

extern "C" {

void save_tile(h2o_req_t* req, const char* tile_path, const char* data, size_t len, const char* mime_type, size_t mime_type_len, int flags, tile_rendered_callback callback) {
    /* write to the filesystem */
    /*
    As the rendered image was already h2o_send_inline'ed in the callback,
    any errors in saving it to a file will be just error-logged:
    response to the client is NOT affected: no such thing as "500 Internal Server Error."
    */
    callback(req, data, len, tile_path, mime_type, mime_type_len, flags);

    size_t tmp_path_len = strlen(tile_path)+18;
    char *tmp_tile_path = static_cast<char*>(alloca(tmp_path_len));
    snprintf(tmp_tile_path, tmp_path_len, "%s.%x", tile_path, pthread_self());
    mkdir_p_parent(tmp_tile_path);
    int fd = open(tmp_tile_path, O_WRONLY | O_TRUNC | O_CREAT, 0666);
    if (fd < 0) {
        h2o_req_log_error(req, "lib/handler/mapnik-bridge.cpp", "Could not open file %s: %s\n", tmp_tile_path, strerror(errno));
    }
    int v = write(fd, data, len);
    if (v != len) {
        h2o_req_log_error(req, "lib/handler/mapnik-bridge.cpp", "Failed to write to file %s: %s\n", tmp_tile_path, strerror(errno));
        close(fd);
        unlink(tmp_tile_path);
    }
    close(fd);
    rename(tmp_tile_path, tile_path);
}

void render_tile(h2o_req_t* req, void* map_ptr, const char* tile_path, uint32_t zoom, uint32_t x, uint32_t y, const char* mime_type, size_t mime_type_len, int flags, tile_rendered_callback callback) {

    try {
        using namespace mapnik;
//        boost::filesystem::path path(tile_path);

        const Map _map = *(Map*)map_ptr;
        Map m(_map);    // clone

        /* (left, top)-(right, bottom) in Mercator projection. */
        double l, t, r, b;
        image_32 image(m.width(),m.height());
#if MAPNIK_MAJOR_VERSION >= 3
        image_view_rgba8 vw(TILE_SIZE/2, TILE_SIZE/2, TILE_SIZE, TILE_SIZE, image);
#else
        image_view<mapnik::image_data_32> vw(TILE_SIZE/2, TILE_SIZE/2, TILE_SIZE, TILE_SIZE, image.data());
#endif
        tile_to_merc_box(zoom, x, y, l, t, r, b);
        box2d<double> bbox(l, t, r, b);
        /* Double the bbox */
        bbox.width(bbox.width() * 2);
        bbox.height(bbox.height() * 2);
        /* Render */
        m.zoom_to_box(bbox);
        agg_renderer<image_32> ren(m,image);
        ren.apply();
        /* Clip the center 256x256 into vw */
#if MAPNIK_MAJOR_VERSION >= 3
        std::string buf = save_to_string(image_view_any(vw), "png256:e=miniz");
#else
        std::string buf = save_to_string(vw, "png256");
#endif
        save_tile(req, tile_path, buf.c_str(), buf.length(), H2O_STRLIT("image/png"), 0, callback);
    } catch (std::exception& e) {
        h2o_req_log_error(req, "lib/handler/mapnik-bridge.cpp", "%s", e.what());
        req->res.status = 500;
        req->res.reason = "internal server error";
        h2o_send_inline(req, NULL, 0);
    }

}

void* alloc_mapnik(const char* style_path) {
    // To avoid label scattering, we render a 2x2 larger area and then clip the center.
    mapnik::Map* m = new mapnik::Map(TILE_SIZE*2, TILE_SIZE*2);
    // Any failure in parsing the style file will immediately cause abortion by an unhandled exception, this is intended.
    mapnik::load_map(*m, style_path);
    return m;
}

void dispose_mapnik(void* m) {
    mapnik::Map* map = (mapnik::Map*)m;
    delete map;
}

void init_mapnik_datasource(const char* datasource) {
    if (datasource == NULL) {
        datasource = "/usr/local/lib/mapnik/input";
    }

    // Absence of datasource dir will immediately cause abortion by an unhandled exception, this is intended.
    boost::filesystem::path bpath(datasource);
    if (unlikely(!boost::filesystem::exists(bpath))) {
        std::string message = str(boost::format("Error: Mapnik datasource %1% does not exist, check the \"mapnik-datasource\" configuration in your .conf.") % bpath);
        throw std::runtime_error( message );
    }
    boost::filesystem::path canonical = boost::filesystem::canonical(bpath);
    if (unlikely(!boost::filesystem::is_directory(canonical))) {
        std::string message = str(boost::format("Error: Mapnik datasource %1% is not a directory, check the \"mapnik-datasource\" configuration in your .conf.") % bpath);
        throw std::runtime_error( message );
    }

    mapnik::datasource_cache::instance().register_datasources(datasource);
}

void load_fonts(const char *font_dir) {
    DIR *fonts = opendir(font_dir);
    struct dirent *entry;
    char path[PATH_MAX]; // FIXME: Eats lots of stack space when recursive

    if (!fonts) {
        fprintf(stderr, "Unable to open font directory: %s\n", font_dir);
        return;
    }

    while ((entry = readdir(fonts))) {
        struct stat b;
        char *p;

        if (!strcmp(entry->d_name, ".") || !strcmp(entry->d_name, ".."))
            continue;
        snprintf(path, sizeof(path), "%s/%s", font_dir, entry->d_name);
        if (stat(path, &b))
            continue;
        if (S_ISDIR(b.st_mode)) {
            load_fonts(path);
            continue;
        }
        p = strrchr(path, '.');
        if (p && !strcmp(p, ".ttf")) {
#if DEBUG
            fprintf(stderr, "DEBUG: Loading font: %s\n", path);
#endif
            mapnik::freetype_engine::register_font(path);
        }
    }
    closedir(fonts);
}

}

ext: cpp


text:
#include <iostream>
#include <boost/numeric/mtl/mtl.hpp>

int main(int, char**)
{
    using namespace mtl;

    const unsigned n= 10;
    dense2D<float, mat::parameters<col_major> > B(n, n);

    mat::hessian_setup(B, 1.0);

    std::cout << "one_norm(B) is " << one_norm(B)<< "\n";
    std::cout << "infinity_norm(B) is " << infinity_norm(B)<< "\n";
    std::cout << "frobenius_norm(B) is " << frobenius_norm(B)<< "\n";

    return 0;
}


text:
/*
 *
 * Copyright (c) 2004
 * John Maddock
 *
 * Use, modification and distribution are subject to the
 * Boost Software License, Version 1.0. (See accompanying file
 * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
 *
 */

 /*
  *   LOCATION:    see http://www.boost.org for most recent version.
  *   FILE         w32_regex_traits.hpp
  *   VERSION      see <boost/version.hpp>
  *   DESCRIPTION: Declares regular expression traits class w32_regex_traits.
  */

#ifndef BOOST_W32_REGEX_TRAITS_HPP_INCLUDED
#define BOOST_W32_REGEX_TRAITS_HPP_INCLUDED

#ifndef BOOST_RE_PAT_EXCEPT_HPP
#include <boost/regex/pattern_except.hpp>
#endif
#ifndef BOOST_REGEX_TRAITS_DEFAULTS_HPP_INCLUDED
#include <boost/regex/v4/regex_traits_defaults.hpp>
#endif
#ifdef BOOST_HAS_THREADS
#include <boost/regex/pending/static_mutex.hpp>
#endif
#ifndef BOOST_REGEX_PRIMARY_TRANSFORM
#include <boost/regex/v4/primary_transform.hpp>
#endif
#ifndef BOOST_REGEX_OBJECT_CACHE_HPP
#include <boost/regex/pending/object_cache.hpp>
#endif

#ifdef BOOST_MSVC
#pragma warning(push)
#pragma warning(disable: 4103)
#endif
#ifdef BOOST_HAS_ABI_HEADERS
#  include BOOST_ABI_PREFIX
#endif
#ifdef BOOST_MSVC
#pragma warning(pop)
#endif

#ifdef BOOST_MSVC
#pragma warning(push)
#pragma warning(disable:4786)
#pragma warning(disable:4800)
#endif

namespace boost{

//
// forward declaration is needed by some compilers:
//
template <class charT>
class w32_regex_traits;

namespace re_detail{

//
// start by typedeffing the types we'll need:
//
typedef ::boost::uint32_t lcid_type;   // placeholder for LCID.
typedef ::boost::shared_ptr<void> cat_type; // placeholder for dll HANDLE.

//
// then add wrappers around the actual Win32 API's (ie implementation hiding):
//
BOOST_REGEX_DECL lcid_type BOOST_REGEX_CALL w32_get_default_locale();
BOOST_REGEX_DECL bool BOOST_REGEX_CALL w32_is_lower(char, lcid_type);
#ifndef BOOST_NO_WREGEX
BOOST_REGEX_DECL bool BOOST_REGEX_CALL w32_is_lower(wchar_t, lcid_type);
#ifdef BOOST_REGEX_HAS_OTHER_WCHAR_T
BOOST_REGEX_DECL bool BOOST_REGEX_CALL w32_is_lower(unsigned short ca, lcid_type state_id);
#endif
#endif
BOOST_REGEX_DECL bool BOOST_REGEX_CALL w32_is_upper(char, lcid_type);
#ifndef BOOST_NO_WREGEX
BOOST_REGEX_DECL bool BOOST_REGEX_CALL w32_is_upper(wchar_t, lcid_type);
#ifdef BOOST_REGEX_HAS_OTHER_WCHAR_T
BOOST_REGEX_DECL bool BOOST_REGEX_CALL w32_is_upper(unsigned short ca, lcid_type state_id);
#endif
#endif
BOOST_REGEX_DECL cat_type BOOST_REGEX_CALL w32_cat_open(const std::string& name);
BOOST_REGEX_DECL std::string BOOST_REGEX_CALL w32_cat_get(const cat_type& cat, lcid_type state_id, int i, const std::string& def);
#ifndef BOOST_NO_WREGEX
BOOST_REGEX_DECL std::wstring BOOST_REGEX_CALL w32_cat_get(const cat_type& cat, lcid_type state_id, int i, const std::wstring& def);
#ifdef BOOST_REGEX_HAS_OTHER_WCHAR_T
BOOST_REGEX_DECL std::basic_string<unsigned short> BOOST_REGEX_CALL w32_cat_get(const cat_type& cat, lcid_type, int i, const std::basic_string<unsigned short>& def);
#endif
#endif
BOOST_REGEX_DECL std::string BOOST_REGEX_CALL w32_transform(lcid_type state_id, const char* p1, const char* p2);
#ifndef BOOST_NO_WREGEX
BOOST_REGEX_DECL std::wstring BOOST_REGEX_CALL w32_transform(lcid_type state_id, const wchar_t* p1, const wchar_t* p2);
#ifdef BOOST_REGEX_HAS_OTHER_WCHAR_T
BOOST_REGEX_DECL std::basic_string<unsigned short> BOOST_REGEX_CALL w32_transform(lcid_type state_id, const unsigned short* p1, const unsigned short* p2);
#endif
#endif
BOOST_REGEX_DECL char BOOST_REGEX_CALL w32_tolower(char c, lcid_type);
#ifndef BOOST_NO_WREGEX
BOOST_REGEX_DECL wchar_t BOOST_REGEX_CALL w32_tolower(wchar_t c, lcid_type);
#ifdef BOOST_REGEX_HAS_OTHER_WCHAR_T
BOOST_REGEX_DECL unsigned short BOOST_REGEX_CALL w32_tolower(unsigned short c, lcid_type state_id);
#endif
#endif
BOOST_REGEX_DECL char BOOST_REGEX_CALL w32_toupper(char c, lcid_type);
#ifndef BOOST_NO_WREGEX
BOOST_REGEX_DECL wchar_t BOOST_REGEX_CALL w32_toupper(wchar_t c, lcid_type);
#endif
BOOST_REGEX_DECL bool BOOST_REGEX_CALL w32_is(lcid_type, boost::uint32_t mask, char c);
#ifndef BOOST_NO_WREGEX
BOOST_REGEX_DECL bool BOOST_REGEX_CALL w32_is(lcid_type, boost::uint32_t mask, wchar_t c);
#ifdef BOOST_REGEX_HAS_OTHER_WCHAR_T
BOOST_REGEX_DECL bool BOOST_REGEX_CALL w32_is(lcid_type state_id, boost::uint32_t m, unsigned short c);
#endif
#endif
//
// class w32_regex_traits_base:
// acts as a container for locale and the facets we are using.
//
template <class charT>
struct w32_regex_traits_base
{
   w32_regex_traits_base(lcid_type l)
   { imbue(l); }
   lcid_type imbue(lcid_type l);

   lcid_type m_locale;
};

template <class charT>
inline lcid_type w32_regex_traits_base<charT>::imbue(lcid_type l)
{
   lcid_type result(m_locale);
   m_locale = l;
   return result;
}

//
// class w32_regex_traits_char_layer:
// implements methods that require specialisation for narrow characters:
//
template <class charT>
class w32_regex_traits_char_layer : public w32_regex_traits_base<charT>
{
   typedef std::basic_string<charT> string_type;
   typedef std::map<charT, regex_constants::syntax_type> map_type;
   typedef typename map_type::const_iterator map_iterator_type;
public:
   w32_regex_traits_char_layer(const lcid_type l);

   regex_constants::syntax_type syntax_type(charT c)const
   {
      map_iterator_type i = m_char_map.find(c);
      return ((i == m_char_map.end()) ? 0 : i->second);
   }
   regex_constants::escape_syntax_type escape_syntax_type(charT c) const
   {
      map_iterator_type i = m_char_map.find(c);
      if(i == m_char_map.end())
      {
         if(::boost::re_detail::w32_is_lower(c, this->m_locale)) return regex_constants::escape_type_class;
         if(::boost::re_detail::w32_is_upper(c, this->m_locale)) return regex_constants::escape_type_not_class;
         return 0;
      }
      return i->second;
   }
   charT tolower(charT c)const
   {
      return ::boost::re_detail::w32_tolower(c, this->m_locale);
   }
   bool isctype(boost::uint32_t mask, charT c)const
   {
      return ::boost::re_detail::w32_is(this->m_locale, mask, c);
   }

private:
   string_type get_default_message(regex_constants::syntax_type);
   // TODO: use a hash table when available!
   map_type m_char_map;
};

template <class charT>
w32_regex_traits_char_layer<charT>::w32_regex_traits_char_layer(::boost::re_detail::lcid_type l)
   : w32_regex_traits_base<charT>(l)
{
   // we need to start by initialising our syntax map so we know which
   // character is used for which purpose:
   cat_type cat;
   std::string cat_name(w32_regex_traits<charT>::get_catalog_name());
   if(cat_name.size())
   {
      cat = ::boost::re_detail::w32_cat_open(cat_name);
      if(!cat)
      {
         std::string m("Unable to open message catalog: ");
         std::runtime_error err(m + cat_name);
         boost::re_detail::raise_runtime_error(err);
      }
   }
   //
   // if we have a valid catalog then load our messages:
   //
   if(cat)
   {
      for(regex_constants::syntax_type i = 1; i < regex_constants::syntax_max; ++i)
      {
         string_type mss = ::boost::re_detail::w32_cat_get(cat, this->m_locale, i, get_default_message(i));
         for(typename string_type::size_type j = 0; j < mss.size(); ++j)
         {
            this->m_char_map[mss[j]] = i;
         }
      }
   }
   else
   {
      for(regex_constants::syntax_type i = 1; i < regex_constants::syntax_max; ++i)
      {
         const char* ptr = get_default_syntax(i);
         while(ptr && *ptr)
         {
            this->m_char_map[static_cast<charT>(*ptr)] = i;
            ++ptr;
         }
      }
   }
}

template <class charT>
typename w32_regex_traits_char_layer<charT>::string_type
   w32_regex_traits_char_layer<charT>::get_default_message(regex_constants::syntax_type i)
{
   const char* ptr = get_default_syntax(i);
   string_type result;
   while(ptr && *ptr)
   {
      result.append(1, static_cast<charT>(*ptr));
      ++ptr;
   }
   return result;
}

//
// specialised version for narrow characters:
//
template <>
class BOOST_REGEX_DECL w32_regex_traits_char_layer<char> : public w32_regex_traits_base<char>
{
   typedef std::string string_type;
public:
   w32_regex_traits_char_layer(::boost::re_detail::lcid_type l)
   : w32_regex_traits_base<char>(l)
   {
      init();
   }

   regex_constants::syntax_type syntax_type(char c)const
   {
      return m_char_map[static_cast<unsigned char>(c)];
   }
   regex_constants::escape_syntax_type escape_syntax_type(char c) const
   {
      return m_char_map[static_cast<unsigned char>(c)];
   }
   char tolower(char c)const
   {
      return m_lower_map[static_cast<unsigned char>(c)];
   }
   bool isctype(boost::uint32_t mask, char c)const
   {
      return m_type_map[static_cast<unsigned char>(c)] & mask;
   }

private:
   regex_constants::syntax_type m_char_map[1u << CHAR_BIT];
   char m_lower_map[1u << CHAR_BIT];
   boost::uint16_t m_type_map[1u << CHAR_BIT];
   void init();
};

//
// class w32_regex_traits_implementation:
// provides pimpl implementation for w32_regex_traits.
//
template <class charT>
class w32_regex_traits_implementation : public w32_regex_traits_char_layer<charT>
{
public:
   typedef typename w32_regex_traits<charT>::char_class_type char_class_type;
   BOOST_STATIC_CONSTANT(char_class_type, mask_word = 0x0400); // must be C1_DEFINED << 1
   BOOST_STATIC_CONSTANT(char_class_type, mask_unicode = 0x0800); // must be C1_DEFINED << 2
   BOOST_STATIC_CONSTANT(char_class_type, mask_horizontal = 0x1000); // must be C1_DEFINED << 3
   BOOST_STATIC_CONSTANT(char_class_type, mask_vertical = 0x2000); // must be C1_DEFINED << 4
   BOOST_STATIC_CONSTANT(char_class_type, mask_base = 0x3ff);  // all the masks used by the CT_CTYPE1 group

   typedef std::basic_string<charT> string_type;
   typedef charT char_type;
   w32_regex_traits_implementation(::boost::re_detail::lcid_type l);
   std::string error_string(regex_constants::error_type n) const
   {
      if(!m_error_strings.empty())
      {
         std::map<int, std::string>::const_iterator p = m_error_strings.find(n);
         return (p == m_error_strings.end()) ? std::string(get_default_error_string(n)) : p->second;
      }
      return get_default_error_string(n);
   }
   char_class_type lookup_classname(const charT* p1, const charT* p2) const
   {
      char_class_type result = lookup_classname_imp(p1, p2);
      if(result == 0)
      {
         typedef typename string_type::size_type size_type;
         string_type temp(p1, p2);
         for(size_type i = 0; i < temp.size(); ++i)
            temp[i] = this->tolower(temp[i]);
         result = lookup_classname_imp(&*temp.begin(), &*temp.begin() + temp.size());
      }
      return result;
   }
   string_type lookup_collatename(const charT* p1, const charT* p2) const;
   string_type transform_primary(const charT* p1, const charT* p2) const;
   string_type transform(const charT* p1, const charT* p2) const
   {
      return ::boost::re_detail::w32_transform(this->m_locale, p1, p2);
   }
private:
   std::map<int, std::string>     m_error_strings;   // error messages indexed by numberic ID
   std::map<string_type, char_class_type>  m_custom_class_names; // character class names
   std::map<string_type, string_type>      m_custom_collate_names; // collating element names
   unsigned                       m_collate_type;    // the form of the collation string
   charT                          m_collate_delim;   // the collation group delimiter
   //
   // helpers:
   //
   char_class_type lookup_classname_imp(const charT* p1, const charT* p2) const;
};

template <class charT>
typename w32_regex_traits_implementation<charT>::string_type
   w32_regex_traits_implementation<charT>::transform_primary(const charT* p1, const charT* p2) const
{
   string_type result;
   //
   // What we do here depends upon the format of the sort key returned by
   // sort key returned by this->transform:
   //
   switch(m_collate_type)
   {
   case sort_C:
   case sort_unknown:
      // the best we can do is translate to lower case, then get a regular sort key:
      {
         result.assign(p1, p2);
         typedef typename string_type::size_type size_type;
         for(size_type i = 0; i < result.size(); ++i)
            result[i] = this->tolower(result[i]);
         result = this->transform(&*result.begin(), &*result.begin() + result.size());
         break;
      }
   case sort_fixed:
      {
         // get a regular sort key, and then truncate it:
         result.assign(this->transform(p1, p2));
         result.erase(this->m_collate_delim);
         break;
      }
   case sort_delim:
         // get a regular sort key, and then truncate everything after the delim:
         result.assign(this->transform(p1, p2));
         std::size_t i;
         for(i = 0; i < result.size(); ++i)
         {
            if(result[i] == m_collate_delim)
               break;
         }
         result.erase(i);
         break;
   }
   if(result.empty())
      result = string_type(1, charT(0));
   return result;
}

template <class charT>
typename w32_regex_traits_implementation<charT>::string_type
   w32_regex_traits_implementation<charT>::lookup_collatename(const charT* p1, const charT* p2) const
{
   typedef typename std::map<string_type, string_type>::const_iterator iter_type;
   if(m_custom_collate_names.size())
   {
      iter_type pos = m_custom_collate_names.find(string_type(p1, p2));
      if(pos != m_custom_collate_names.end())
         return pos->second;
   }
#if !defined(BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS)\
               && !BOOST_WORKAROUND(BOOST_MSVC, < 1300)\
               && !BOOST_WORKAROUND(__BORLANDC__, <= 0x0551)
   std::string name(p1, p2);
#else
   std::string name;
   const charT* p0 = p1;
   while(p0 != p2)
      name.append(1, char(*p0++));
#endif
   name = lookup_default_collate_name(name);
#if !defined(BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS)\
               && !BOOST_WORKAROUND(BOOST_MSVC, < 1300)\
               && !BOOST_WORKAROUND(__BORLANDC__, <= 0x0551)
   if(name.size())
      return string_type(name.begin(), name.end());
#else
   if(name.size())
   {
      string_type result;
      typedef std::string::const_iterator iter;
      iter b = name.begin();
      iter e = name.end();
      while(b != e)
         result.append(1, charT(*b++));
      return result;
   }
#endif
   if(p2 - p1 == 1)
      return string_type(1, *p1);
   return string_type();
}

template <class charT>
w32_regex_traits_implementation<charT>::w32_regex_traits_implementation(::boost::re_detail::lcid_type l)
: w32_regex_traits_char_layer<charT>(l)
{
   cat_type cat;
   std::string cat_name(w32_regex_traits<charT>::get_catalog_name());
   if(cat_name.size())
   {
      cat = ::boost::re_detail::w32_cat_open(cat_name);
      if(!cat)
      {
         std::string m("Unable to open message catalog: ");
         std::runtime_error err(m + cat_name);
         boost::re_detail::raise_runtime_error(err);
      }
   }
   //
   // if we have a valid catalog then load our messages:
   //
   if(cat)
   {
      //
      // Error messages:
      //
      for(boost::regex_constants::error_type i = static_cast<boost::regex_constants::error_type>(0);
         i <= boost::regex_constants::error_unknown;
         i = static_cast<boost::regex_constants::error_type>(i + 1))
      {
         const char* p = get_default_error_string(i);
         string_type default_message;
         while(*p)
         {
            default_message.append(1, static_cast<charT>(*p));
            ++p;
         }
         string_type s = ::boost::re_detail::w32_cat_get(cat, this->m_locale, i+200, default_message);
         std::string result;
         for(std::string::size_type j = 0; j < s.size(); ++j)
         {
            result.append(1, static_cast<char>(s[j]));
         }
         m_error_strings[i] = result;
      }
      //
      // Custom class names:
      //
      static const char_class_type masks[14] =
      {
         0x0104u, // C1_ALPHA | C1_DIGIT
         0x0100u, // C1_ALPHA
         0x0020u, // C1_CNTRL
         0x0004u, // C1_DIGIT
         (~(0x0020u|0x0008u) & 0x01ffu) | 0x0400u, // not C1_CNTRL or C1_SPACE
         0x0002u, // C1_LOWER
         (~0x0020u & 0x01ffu) | 0x0400, // not C1_CNTRL
         0x0010u, // C1_PUNCT
         0x0008u, // C1_SPACE
         0x0001u, // C1_UPPER
         0x0080u, // C1_XDIGIT
         0x0040u, // C1_BLANK
         w32_regex_traits_implementation<charT>::mask_word,
         w32_regex_traits_implementation<charT>::mask_unicode,
      };
      static const string_type null_string;
      for(unsigned int j = 0; j <= 13; ++j)
      {
         string_type s(::boost::re_detail::w32_cat_get(cat, this->m_locale, j+300, null_string));
         if(s.size())
            this->m_custom_class_names[s] = masks[j];
      }
   }
   //
   // get the collation format used by m_pcollate:
   //
   m_collate_type = re_detail::find_sort_syntax(this, &m_collate_delim);
}

template <class charT>
typename w32_regex_traits_implementation<charT>::char_class_type
   w32_regex_traits_implementation<charT>::lookup_classname_imp(const charT* p1, const charT* p2) const
{
   static const char_class_type masks[22] =
   {
      0,
      0x0104u, // C1_ALPHA | C1_DIGIT
      0x0100u, // C1_ALPHA
      0x0040u, // C1_BLANK
      0x0020u, // C1_CNTRL
      0x0004u, // C1_DIGIT
      0x0004u, // C1_DIGIT
      (~(0x0020u|0x0008u|0x0040) & 0x01ffu) | 0x0400u, // not C1_CNTRL or C1_SPACE or C1_BLANK
      w32_regex_traits_implementation<charT>::mask_horizontal,
      0x0002u, // C1_LOWER
      0x0002u, // C1_LOWER
      (~0x0020u & 0x01ffu) | 0x0400, // not C1_CNTRL
      0x0010u, // C1_PUNCT
      0x0008u, // C1_SPACE
      0x0008u, // C1_SPACE
      0x0001u, // C1_UPPER
      w32_regex_traits_implementation<charT>::mask_unicode,
      0x0001u, // C1_UPPER
      w32_regex_traits_implementation<charT>::mask_vertical,
      0x0104u | w32_regex_traits_implementation<charT>::mask_word,
      0x0104u | w32_regex_traits_implementation<charT>::mask_word,
      0x0080u, // C1_XDIGIT
   };
   if(m_custom_class_names.size())
   {
      typedef typename std::map<std::basic_string<charT>, char_class_type>::const_iterator map_iter;
      map_iter pos = m_custom_class_names.find(string_type(p1, p2));
      if(pos != m_custom_class_names.end())
         return pos->second;
   }
   std::size_t state_id = 1 + re_detail::get_default_class_id(p1, p2);
   if(state_id < sizeof(masks) / sizeof(masks[0]))
      return masks[state_id];
   return masks[0];
}

template <class charT>
boost::shared_ptr<const w32_regex_traits_implementation<charT> > create_w32_regex_traits(::boost::re_detail::lcid_type l BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(charT))
{
   // TODO: create a cache for previously constructed objects.
   return boost::object_cache< ::boost::re_detail::lcid_type, w32_regex_traits_implementation<charT> >::get(l, 5);
}

} // re_detail

template <class charT>
class w32_regex_traits
{
public:
   typedef charT                         char_type;
   typedef std::size_t                   size_type;
   typedef std::basic_string<char_type>  string_type;
   typedef ::boost::re_detail::lcid_type locale_type;
   typedef boost::uint_least32_t         char_class_type;

   struct boost_extensions_tag{};

   w32_regex_traits()
      : m_pimpl(re_detail::create_w32_regex_traits<charT>(::boost::re_detail::w32_get_default_locale()))
   { }
   static size_type length(const char_type* p)
   {
      return std::char_traits<charT>::length(p);
   }
   regex_constants::syntax_type syntax_type(charT c)const
   {
      return m_pimpl->syntax_type(c);
   }
   regex_constants::escape_syntax_type escape_syntax_type(charT c) const
   {
      return m_pimpl->escape_syntax_type(c);
   }
   charT translate(charT c) const
   {
      return c;
   }
   charT translate_nocase(charT c) const
   {
      return this->m_pimpl->tolower(c);
   }
   charT translate(charT c, bool icase) const
   {
      return icase ? this->m_pimpl->tolower(c) : c;
   }
   charT tolower(charT c) const
   {
      return this->m_pimpl->tolower(c);
   }
   charT toupper(charT c) const
   {
      return ::boost::re_detail::w32_toupper(c, this->m_pimpl->m_locale);
   }
   string_type transform(const charT* p1, const charT* p2) const
   {
      return ::boost::re_detail::w32_transform(this->m_pimpl->m_locale, p1, p2);
   }
   string_type transform_primary(const charT* p1, const charT* p2) const
   {
      return m_pimpl->transform_primary(p1, p2);
   }
   char_class_type lookup_classname(const charT* p1, const charT* p2) const
   {
      return m_pimpl->lookup_classname(p1, p2);
   }
   string_type lookup_collatename(const charT* p1, const charT* p2) const
   {
      return m_pimpl->lookup_collatename(p1, p2);
   }
   bool isctype(charT c, char_class_type f) const
   {
      if((f & re_detail::w32_regex_traits_implementation<charT>::mask_base)
         && (this->m_pimpl->isctype(f & re_detail::w32_regex_traits_implementation<charT>::mask_base, c)))
         return true;
      else if((f & re_detail::w32_regex_traits_implementation<charT>::mask_unicode) && re_detail::is_extended(c))
         return true;
      else if((f & re_detail::w32_regex_traits_implementation<charT>::mask_word) && (c == '_'))
         return true;
      else if((f & re_detail::w32_regex_traits_implementation<charT>::mask_vertical)
         && (::boost::re_detail::is_separator(c) || (c == '\v')))
         return true;
      else if((f & re_detail::w32_regex_traits_implementation<charT>::mask_horizontal)
         && this->isctype(c, 0x0008u) && !this->isctype(c, re_detail::w32_regex_traits_implementation<charT>::mask_vertical))
         return true;
      return false;
   }
   int toi(const charT*& p1, const charT* p2, int radix)const
   {
      return ::boost::re_detail::global_toi(p1, p2, radix, *this);
   }
   int value(charT c, int radix)const
   {
      int result = ::boost::re_detail::global_value(c);
      return result < radix ? result : -1;
   }
   locale_type imbue(locale_type l)
   {
      ::boost::re_detail::lcid_type result(getloc());
      m_pimpl = re_detail::create_w32_regex_traits<charT>(l);
      return result;
   }
   locale_type getloc()const
   {
      return m_pimpl->m_locale;
   }
   std::string error_string(regex_constants::error_type n) const
   {
      return m_pimpl->error_string(n);
   }

   //
   // extension:
   // set the name of the message catalog in use (defaults to "boost_regex").
   //
   static std::string catalog_name(const std::string& name);
   static std::string get_catalog_name();

private:
   boost::shared_ptr<const re_detail::w32_regex_traits_implementation<charT> > m_pimpl;
   //
   // catalog name handler:
   //
   static std::string& get_catalog_name_inst();

#ifdef BOOST_HAS_THREADS
   static static_mutex& get_mutex_inst();
#endif
};

template <class charT>
std::string w32_regex_traits<charT>::catalog_name(const std::string& name)
{
#ifdef BOOST_HAS_THREADS
   static_mutex::scoped_lock lk(get_mutex_inst());
#endif
   std::string result(get_catalog_name_inst());
   get_catalog_name_inst() = name;
   return result;
}

template <class charT>
std::string& w32_regex_traits<charT>::get_catalog_name_inst()
{
   static std::string s_name;
   return s_name;
}

template <class charT>
std::string w32_regex_traits<charT>::get_catalog_name()
{
#ifdef BOOST_HAS_THREADS
   static_mutex::scoped_lock lk(get_mutex_inst());
#endif
   std::string result(get_catalog_name_inst());
   return result;
}

#ifdef BOOST_HAS_THREADS
template <class charT>
static_mutex& w32_regex_traits<charT>::get_mutex_inst()
{
   static static_mutex s_mutex = BOOST_STATIC_MUTEX_INIT;
   return s_mutex;
}
#endif

} // boost

#ifdef BOOST_MSVC
#pragma warning(pop)
#endif

#ifdef BOOST_MSVC
#pragma warning(push)
#pragma warning(disable: 4103)
#endif
#ifdef BOOST_HAS_ABI_HEADERS
#  include BOOST_ABI_SUFFIX
#endif
#ifdef BOOST_MSVC
#pragma warning(pop)
#endif

#endif

ext: hpp

max_stars_repo_name: randolphwong/mcsema

max_issues_repo_name: randolphwong/mcsema

max_forks_repo_name: randolphwong/mcsema


text:
/**************************************************************************\
|
|    Copyright (C) 2009 Marc Stevens
|
|    This program is free software: you can redistribute it and/or modify
|    it under the terms of the GNU General Public License as published by
|    the Free Software Foundation, either version 3 of the License, or
|    (at your option) any later version.
|
|    This program is distributed in the hope that it will be useful,
|    but WITHOUT ANY WARRANTY; without even the implied warranty of
|    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
|    GNU General Public License for more details.
|
|    You should have received a copy of the GNU General Public License
|    along with this program.  If not, see <http://www.gnu.org/licenses/>.
|
\**************************************************************************/

#include <vector>
#include <string>
#include <map>

#include <boost/lexical_cast.hpp>

#include <hashclash/saveload_bz2.hpp>
#include <hashclash/sha1detail.hpp>
#include <hashclash/sha1differentialpath.hpp>
#include <hashclash/booleanfunction.hpp>

#include "main.hpp"

using namespace hashclash;
using namespace std;

void sha1_backward_differential_step(const sha1differentialpath& path, path_container_autobalance& outpaths)
{
	const int t = int(outpaths.t);
	const unsigned& maxcond = outpaths.maxcond;
	const unsigned& maxsdrs = outpaths.maxsdrs;
	const unsigned& maxweight = outpaths.maxweight;
	const unsigned& minweight = outpaths.minweight;

	booleanfunction* F = 0;
	if (t < 20) F = &SHA1_F1_data; // this implementation only works properly for sha1_f1
	else if (t < 40) F = &SHA1_F2_data;
	else if (t < 60) F = &SHA1_F3_data;
	else if (t < 80) F = &SHA1_F4_data;

	static sha1differentialpath newpath;
	static vector<sdr> sdrs;
	static bitcondition Qtm1b[32], Qtm2b[32], Qtm3b[32];
	static vector<unsigned> bval;
	static uint32 fdiv[32];
	static bf_outcome foutcomes[32];
//	static std::vector<std::pair<uint32,double> > rotateddiff;
	static vector<sdr> deltam;
	static vector<unsigned> Qtm1prev, Qtm1prevn;

	newpath = path;
	newpath[t-4].clear();

	unsigned totprecond = 0;
	unsigned totcond = 0;
	for (int k = t; k <= outpaths.tend && k <= 80; ++k)
		if (k < newpath.tend())
			totprecond += newpath[k].hw();
	totcond = totprecond + newpath[t-1].hw() + newpath[t-2].hw();

	unsigned minextracond = 0;
	Qtm1prev.clear();
	Qtm1prevn.clear();
	bf_outcome outconstant, outplus, outminus;
	for (unsigned b = 0; b < 32; ++b)
	{
		Qtm1b[b] = newpath(t-1,b);
		if (Qtm1b[b] == bc_prev) {
			Qtm1prev.push_back(b);
			Qtm1b[b] = bc_constant;
			newpath[t-1].set(b, bc_constant);
		} else if (Qtm1b[b] == bc_prevn) {
			Qtm1prevn.push_back(b);
			Qtm1b[b] = bc_constant;
			newpath.setbitcondition(t-1,b, bc_constant);
		}
		Qtm2b[b] = newpath(t-2,(b+2)&31);
		if (b < 31) {
			outconstant = F->outcome( Qtm1b[b], Qtm2b[b], bc_constant );
			outplus = F->outcome( Qtm1b[b], Qtm2b[b], bc_plus );
			outminus = F->outcome( Qtm1b[b], Qtm2b[b], bc_minus );
		} else {
			outconstant = msb_bf_outcome(*F, Qtm1b[b], Qtm2b[b], bc_constant );
			outplus = msb_bf_outcome(*F, Qtm1b[b], Qtm2b[b], bc_plus );
			outminus = msb_bf_outcome(*F, Qtm1b[b], Qtm2b[b], bc_minus );
		}
		if (outconstant.size() > 1 && outplus.size() > 1 && outminus.size() > 1)
			++minextracond;
	}
	sdr sdrQtm3 = newpath[t-3].getsdr();
	uint32 Qtm3_hwnaf = hwnaf(sdrQtm3.adddiff());
	if (totcond + Qtm3_hwnaf + minextracond > maxcond) return;

	/* table deltam */
	sdr mmask = outpaths.m_mask[t];
	deltam.clear();
	deltam.reserve(1<<mmask.hw());
	uint32 addmask = (~mmask.mask)+1;
	uint32 andmask = mmask.mask & 0x7FFFFFFF;
	mmask.sign = 0;
	do {
		mmask.sign += addmask; mmask.sign &= andmask;
		deltam.push_back(mmask);
	} while (mmask.sign != 0 && !outpaths.onemessagediff);
#if 1
        unsigned minhw = 32;
        for (unsigned i = 0; i < deltam.size(); ++i)
                if (hwnaf(deltam[i].adddiff()) < minhw)
                        minhw = hwnaf(deltam[i].adddiff());
        unsigned ii = 0;
        while (ii < deltam.size()) {
                if (hwnaf(deltam[ii].adddiff()) > minhw) {
                        swap(deltam[ii], deltam.back());
                        deltam.pop_back();
                } else
                        ++ii;
        }
#endif

	/* table sdrs for delta Qtm1 */
	unsigned w = Qtm3_hwnaf+1;
	if (w < minweight) w = minweight;
        unsigned mincount = 0;
        if (minweight > 0)
                mincount = count_sdrs(sdrQtm3,minweight-1,30);
	while (
			(w < 32)
			&& (w+1 <= maxweight)
			&& (totcond + w + 1 + minextracond <= maxcond)
			&& (count_sdrs(sdrQtm3, w+1,30)-mincount <= maxsdrs)
		)
		++w;
	table_sdrs(sdrs, sdrQtm3, w, 30);

	wordconditions pathQtm1 = newpath[t-1];
	wordconditions& newpathQtm1 = newpath[t-1];
	wordconditions& newpathQtm2 = newpath[t-2];
	wordconditions& newpathQtm3 = newpath[t-3];
	wordconditions& newpathQtm4 = newpath[t-4];

	uint32 dQtm4pc = newpath[t+1].diff() - newpath[t].getsdr().rotate_left(5).adddiff();

	vector<sdr>::const_iterator cit = sdrs.begin(), citend = sdrs.end();
	for (; cit != citend; ++cit)
	{
		sdrQtm3 = *cit;
		unsigned hwQtm3 = sdrQtm3.hw();
		if (hwQtm3 < minweight) continue;
		if (totcond + hwQtm3 + minextracond > maxcond)
			continue;
		newpathQtm3 = sdrQtm3;

		uint32 cnt = 1;
		uint32 dF_fixed = 0;
		unsigned maxextracond = 0;
		bval.clear();
		for (unsigned b = 0; b < 32; ++b)
		{
			Qtm3b[b] = newpathQtm3.get((b+2)&31);
			if (b < 31)
				foutcomes[b] = F->outcome( Qtm1b[b], Qtm2b[b], Qtm3b[b] );
			else
				foutcomes[b] = msb_bf_outcome(*F, Qtm1b[b], Qtm2b[b], Qtm3b[b] );
			unsigned fsize = foutcomes[b].size();
			if (fsize > 1)
			{
				fdiv[b] = cnt;
				if (fsize == 2) cnt <<= 1;
				else if (fsize == 3) { cnt += cnt<<1; ++ maxextracond; }
				bval.push_back(b);
			} else
				dF_fixed += foutcomes[b](0,b);
		}
		if (totcond + hwQtm3 + bval.size() > maxcond)
			continue;
		if (outpaths.estimatefactor != 0)
		{
			outpaths.estimate(totcond + hwQtm3 + bval.size() + ((maxextracond+1)>>1), cnt*deltam.size());
			continue;
		}

		newpathQtm2 = path[t-2];

		std::reverse(bval.begin(), bval.end());
		bf_conditions newconditions;
		for (uint32 k = 0; k < cnt; ++k)
		{
			uint32 m = k;
			uint32 dF = dF_fixed;
			newpathQtm1 = pathQtm1;
			for (unsigned j = 0; j < bval.size(); ++j)
			{
				const unsigned b = bval[j];
				unsigned i = 0;
				while (m >= fdiv[b])
				{
					m -= fdiv[b];
					++i;
				}
				if (b < 31)
					newconditions = F->backwardconditions( Qtm1b[b], Qtm2b[b], Qtm3b[b], foutcomes[b][i] );
				else {
					newconditions = msb_bf_backwardconditions(*F, Qtm1b[b], Qtm2b[b], Qtm3b[b], foutcomes[b][i] );
					if (msb_bf_outcome(*F, newconditions).size() > 1 || msb_bf_outcome(*F, newconditions)[0] != foutcomes[b][i]) {
						cout << endl << "[" << Qtm1b[b] << Qtm2b[b] << Qtm3b[b] <<"](" << foutcomes[b][i] <<")=>[" << newconditions.first << newconditions.second << newconditions.third << "]" << endl;
						bf_outcome tmp = msb_bf_outcome(*F, Qtm1b[b], Qtm2b[b], Qtm3b[b]);
						for (unsigned i = 0; i < tmp.size(); ++i)
							cout << tmp[i] << flush;
						cout << endl;
						tmp = F->outcome(Qtm1b[b], Qtm2b[b], Qtm3b[b]);
						for (unsigned i = 0; i < tmp.size(); ++i)
							cout << tmp[i] << flush;
						cout << endl;
						newconditions = F->backwardconditions( Qtm1b[b], Qtm2b[b], Qtm3b[b], bc_constant );
						cout << "(.)=>[" << newconditions.first << newconditions.second << newconditions.third << "]" << endl;
						throw;
					}
				}
				newpathQtm1.set(b, newconditions.first);
				newpathQtm2.set((b+2)&31, newconditions.second);
				newpathQtm3.set((b+2)&31, newconditions.third);

				dF += foutcomes[b](i,b);
			}

			bool contradiction = false;
			for (unsigned i = 0; i < Qtm1prev.size(); ++i) {
				const unsigned b = Qtm1prev[i];
				const bitcondition bcQtm1b = newpathQtm1[b];
				switch (bcQtm1b) {
				case bc_constant:
					newpathQtm1.set(b, bc_prev);
					break;
				case bc_one:
				case bc_zero:
					if (newpathQtm2[b] == bc_prev) {
						newpathQtm3.set(b, bcQtm1b);
					} else if (newpathQtm2[b] == bc_prevn) {
						if (bcQtm1b == bc_one)
							newpathQtm3.set(b, bc_zero);
						else
							newpathQtm3.set(b, bc_one);
					} else if (newpathQtm2[b] != bc_constant && newpathQtm2[b] != bcQtm1b) {
						//cerr << "[^" << newpathQtm1[b] << newpathQtm2[b] << newpathQtm3[b] << "]" << flush;
						contradiction = true;
					}
					newpathQtm2.set(b, bcQtm1b);
					break;
				default:
					cerr << "[^" << newpathQtm1[b] << newpathQtm2[b] << newpathQtm3[b] << "]" << flush;
					contradiction = true;
				}
			}
			for (unsigned i = 0; i < Qtm1prevn.size(); ++i) {
				const unsigned b = Qtm1prevn[i];
				const bitcondition bcQtm1b = newpathQtm1[b];
				switch (bcQtm1b) {
				case bc_constant:
					newpathQtm1.set(b, bc_prevn);
					break;
				case bc_one:
				case bc_zero:
					if (newpathQtm2[b] == bc_prev) {
						if (bcQtm1b == bc_one)
							newpathQtm3.set(b, bc_zero);
						else
							newpathQtm3.set(b, bc_one);
					} else if (newpathQtm2[b] == bc_prevn) {
						newpathQtm3.set(b, bcQtm1b);
					} else if (newpathQtm2[b] != bc_constant && newpathQtm2[b] == bcQtm1b) {
						//cerr << "[^" << newpathQtm1[b] << newpathQtm2[b] << newpathQtm3[b] << "]" << flush;
						contradiction = true;
					}
					if (bcQtm1b == bc_one)
						newpathQtm2.set(b, bc_zero);
					else
						newpathQtm2.set(b, bc_one);
					break;
				default:
					cerr << "[^" << newpathQtm1[b] << newpathQtm2[b] << newpathQtm3[b] << "]" << flush;
					contradiction = true;
				}
			}
			if (contradiction)
				continue;

			unsigned ncond = totprecond + newpathQtm1.hw() + newpathQtm2.hw() + newpathQtm3.hw();
			if (ncond > maxcond) return;
			for (unsigned i = 0; i < deltam.size(); ++i)
			{
				newpath.getme(t) = deltam[i];
				uint32 dQtm4 = dQtm4pc - dF - deltam[i].adddiff();
				newpathQtm4 = naf(dQtm4).rotate_right(30);
				unsigned ncond2 = ncond;
				if (outpaths.includenaf) {
					if (outpaths.halfnafweight)
						ncond2 += (newpathQtm4.hw()>>1);
					else
						ncond2 += newpathQtm4.hw();
				}
				if (ncond2 <= maxcond)
					outpaths.push_back(newpath, ncond2);
			}
		} // for cnt
	} // for sdrs
}


text:
//  Copyright (c) 2007-2014 Hartmut Kaiser
//
//  Distributed under the Boost Software License, Version 1.0. (See accompanying
//  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

#if !defined(HPX_RUNTIME_COMPONENTS_SERVER_MIGRATE_COMPONENT_JAN_30_2014_0737AM)
#define HPX_RUNTIME_COMPONENTS_SERVER_MIGRATE_COMPONENT_JAN_30_2014_0737AM

#include <hpx/hpx_fwd.hpp>
#include <hpx/runtime/actions/plain_action.hpp>
#include <hpx/runtime/naming/name.hpp>
#include <hpx/runtime/get_ptr.hpp>
#include <hpx/runtime/components/stubs/runtime_support.hpp>

#include <boost/serialization/shared_ptr.hpp>

namespace hpx { namespace components { namespace server
{
    ///////////////////////////////////////////////////////////////////////////
    /// \brief Migrate given component to the specified target locality
    namespace detail
    {
        // clean up (source) memory of migrated object
        template <typename Component>
        naming::id_type migrate_component_cleanup(
            future<naming::id_type> f,
            boost::shared_ptr<Component> ptr,
            naming::id_type const& to_migrate)
        {
            ptr->mark_as_migrated();
            return to_migrate;
        }

        // trigger the actual migration
        template <typename Component>
        future<naming::id_type> migrate_component_postproc(
            future<boost::shared_ptr<Component> > f,
            naming::id_type const& to_migrate,
            naming::id_type const& target_locality)
        {
            using components::stubs::runtime_support;

            boost::shared_ptr<Component> ptr = f.get();
            boost::uint32_t pin_count = ptr->pin_count();

            if (pin_count == ~0x0u)
            {
                HPX_THROW_EXCEPTION(invalid_status,
                    "hpx::components::server::migrate_component",
                    "attempting to migrate an instance of a component which was "
                    "already migrated");
                return make_ready_future(naming::invalid_id);
            }
            if (pin_count > 1)
            {
                HPX_THROW_EXCEPTION(invalid_status,
                    "hpx::components::server::migrate_component",
                    "attempting to migrate an instance of a component which is "
                    "currently pinned");
                return make_ready_future(naming::invalid_id);
            }

            return runtime_support::migrate_component_async<Component>(
                        target_locality, ptr, to_migrate)
                .then(util::bind(
                    &detail::migrate_component_cleanup<Component>,
                    util::placeholders::_1, ptr, to_migrate));
        }
    }

    ///////////////////////////////////////////////////////////////////////////
    template <typename Component>
    future<naming::id_type> migrate_component(
        naming::id_type const& to_migrate,
        naming::id_type const& target_locality)
    {
        // 'migration' to same locality as before is a no-op
        if (target_locality == hpx::find_here())
        {
            return make_ready_future(to_migrate);
        }
        if (!Component::supports_migration())
        {
            HPX_THROW_EXCEPTION(invalid_status,
                "hpx::components::server::migrate_component",
                "attempting to migrate an instance of a component which is "
                "does not support migration");
            return make_ready_future(naming::invalid_id);
        }

        return hpx::detail::get_ptr_for_migration<Component>(to_migrate)
            .then(util::bind(&detail::migrate_component_postproc<Component>,
                util::placeholders::_1, to_migrate, target_locality));
    }

    template <typename Component>
    struct migrate_component_action
      : ::hpx::actions::action<
            future<naming::id_type> (*)(naming::id_type const&, naming::id_type const&)
          , &migrate_component<Component>
          , migrate_component_action<Component> >
    {};
}}}

HPX_REGISTER_PLAIN_ACTION_TEMPLATE(
    (template <typename Component>),
    (hpx::components::server::migrate_component_action<Component>)
)

#endif


text:
//  boost/chrono/stopwatches/reporters/process_default_formatter.hpp
//  Copyright 2011 Vicente J. Botet Escriba
//  Copyright (c) Microsoft Corporation 2014
//  Distributed under the Boost Software License, Version 1.0.
//  (See accompanying file LICENSE_1_0.txt or
//   copy at http://www.boost.org/LICENSE_1_0.txt)
//  See http://www.boost.org/libs/chrono/stopwatches for documentation.

#ifndef BOOST_CHRONO_STOPWATCHES_REPORTERS_PROCESS_DEFAULT_FORMATTER_HPP
#define BOOST_CHRONO_STOPWATCHES_REPORTERS_PROCESS_DEFAULT_FORMATTER_HPP

#include <boost/chrono/config.hpp>

#include <boost/chrono/stopwatches/reporters/stopwatch_reporter_default_formatter.hpp>
#include <boost/chrono/stopwatches/reporters/clock_default_formatter.hpp>
#include <boost/chrono/stopwatches/formatters/elapsed_formatter.hpp>
#include <boost/chrono/stopwatches/formatters/times_formatter.hpp>
#include <boost/chrono/process_cpu_clocks.hpp>

#if defined(BOOST_CHRONO_HAS_PROCESS_CLOCKS)

namespace boost
{
  namespace chrono
  {
#if ! BOOST_OS_WINDOWS || BOOST_PLAT_WINDOWS_DESKTOP

    template <typename CharT>
    struct basic_clock_default_formatter<CharT, process_cpu_clock>
    {
      typedef basic_times_formatter<milli, CharT> type;
    };

#endif
  } // namespace chrono
} // namespace boost

#endif

#endif

max_issues_repo_name: wujf/mongo

max_forks_repo_name: wujf/mongo


text:
/*
	This file is part of cpp-ethereum.

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

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

	You should have received a copy of the GNU General Public License
	along with cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.
*/
/** @file EthashCPUMiner.cpp
 * @author Gav Wood <i@gavwood.com>
 * @date 2014
 *
 * Determines the PoW algorithm.
 */

#include "EthashCPUMiner.h"
#include <thread>
#include <chrono>
#include <boost/algorithm/string.hpp>
#include <random>

#if ETH_CPUID
#define HAVE_STDINT_H
#include <libcpuid/libcpuid.h>
#endif // ETH_CPUID
using namespace std;
using namespace dev;
using namespace eth;

unsigned EthashCPUMiner::s_numInstances = 0;

#if ETH_CPUID
static string jsonEncode(map<string, string> const& _m)
{
    string ret = "{";

    for (auto const& i: _m)
    {
        string k = boost::replace_all_copy(boost::replace_all_copy(i.first, "\\", "\\\\"), "'", "\\'");
        string v = boost::replace_all_copy(boost::replace_all_copy(i.second, "\\", "\\\\"), "'", "\\'");
        if (ret.size() > 1)
            ret += ", ";
        ret += "\"" + k + "\":\"" + v + "\"";
    }

    return ret + "}";
}
#endif // ETH_CPUID

EthashCPUMiner::EthashCPUMiner(GenericMiner<EthashProofOfWork>::ConstructionInfo const &_ci) :
        GenericMiner<EthashProofOfWork>(_ci), Worker("miner" + toString(index()))
{
}

EthashCPUMiner::~EthashCPUMiner()
{
}

void EthashCPUMiner::kickOff()
{
    stopWorking();
    startWorking();
}

void EthashCPUMiner::pause()
{
    stopWorking();
}

void EthashCPUMiner::workLoop()
{
    auto tid = std::this_thread::get_id();
    static std::mt19937_64 s_eng((utcTime() + std::hash<decltype(tid)>()(tid)));

    uint64_t tryNonce = s_eng();
    ethash_return_value ethashReturn;

    WorkPackage w = work();

    EthashAux::FullType dag;
    while (!shouldStop() && !dag)
    {
        while (!shouldStop() && EthashAux::computeFull(w.seedHash, true) != 100)
            this_thread::sleep_for(chrono::milliseconds(500));
        dag = EthashAux::full(w.seedHash, false);
    }

    h256 boundary = w.boundary;
    unsigned hashCount = 1;
    for (; !shouldStop(); tryNonce++, hashCount++)
    {
        ethashReturn = ethash_full_compute(dag->full, *(ethash_h256_t *)w.headerHash.data(), tryNonce);
        h256 value = h256((uint8_t *)&ethashReturn.result, h256::ConstructFromPointer);
        if (value <= boundary && submitProof(EthashProofOfWork::Solution{(h64)(u64)tryNonce,
                                                                         h256((uint8_t *)&ethashReturn.mix_hash,
                                                                              h256::ConstructFromPointer)}))
            break;
        if (!(hashCount % 100))
            accumulateHashes(100);
    }
}

std::string EthashCPUMiner::platformInfo()
{
    string baseline = toString(std::thread::hardware_concurrency()) + "-thread CPU";

#if ETH_CPUID
    if (!cpuid_present())
        return baseline;
    struct cpu_raw_data_t raw;
    struct cpu_id_t data;
    if (cpuid_get_raw_data(&raw) < 0)
        return baseline;
    if (cpu_identify(&raw, &data) < 0)
        return baseline;
    map<string, string> m;
    m["vendor"] = data.vendor_str;
    m["codename"] = data.cpu_codename;
    m["brand"] = data.brand_str;
    m["L1 cache"] = toString(data.l1_data_cache);
    m["L2 cache"] = toString(data.l2_cache);
    m["L3 cache"] = toString(data.l3_cache);
    m["cores"] = toString(data.num_cores);
    m["threads"] = toString(data.num_logical_cpus);
    m["clocknominal"] = toString(cpu_clock_by_os());
    m["clocktested"] = toString(cpu_clock_measure(200, 0));
    /*
    printf("  MMX         : %s\n", data.flags[CPU_FEATURE_MMX] ? "present" : "absent");
    printf("  MMX-extended: %s\n", data.flags[CPU_FEATURE_MMXEXT] ? "present" : "absent");
    printf("  SSE         : %s\n", data.flags[CPU_FEATURE_SSE] ? "present" : "absent");
    printf("  SSE2        : %s\n", data.flags[CPU_FEATURE_SSE2] ? "present" : "absent");
    printf("  3DNow!      : %s\n", data.flags[CPU_FEATURE_3DNOW] ? "present" : "absent");
    */
    return jsonEncode(m);
#else
    return baseline;
#endif // ETH_CPUID
}


text:
/*
* Copyright (c) 2018, YOYOW Foundation PTE. LTD. and contributors.
*/
#pragma once
#include <graphene/chain/protocol/asset.hpp>
#include <graphene/db/object.hpp>
#include <graphene/db/generic_index.hpp>
#include <boost/multi_index/composite_key.hpp>
#include <graphene/chain/account_object.hpp>

namespace graphene { namespace chain {

   /**
   * @brief This class represents a account pledge asset to witness on the object graph
   * @ingroup object
   * @ingroup protocol
   */
   class pledge_mining_object : public graphene::db::abstract_object<pledge_mining_object>
   {
      public:
         static const uint8_t space_id = implementation_ids;
         static const uint8_t type_id = impl_pledge_mining_object_type;

         account_uid_type     pledge_account;
         account_uid_type     witness;
         uint32_t             last_bonus_block_num = 0;
         pledge_balance_id_type pledge_id;

   };

   struct by_pledge_witness;
   struct by_pledge_account;

   /**
   * @ingroup object_index
   */
   typedef multi_index_container<
      pledge_mining_object,
      indexed_by<
         ordered_unique< tag<by_id>, member< object, object_id_type, &object::id > >,
         ordered_unique< tag<by_pledge_witness>,
            composite_key<
            pledge_mining_object,
            member<pledge_mining_object, account_uid_type, &pledge_mining_object::witness>,
            member<pledge_mining_object, account_uid_type, &pledge_mining_object::pledge_account>
            >
         >,
         ordered_unique< tag<by_pledge_account>,
            composite_key<
            pledge_mining_object,
            member<pledge_mining_object, account_uid_type, &pledge_mining_object::pledge_account>,
            member<pledge_mining_object, account_uid_type, &pledge_mining_object::witness>
            >
         >
      >
   > pledge_mining_multi_index_type;

   /**
   * @ingroup object_index
   */
   typedef generic_index<pledge_mining_object, pledge_mining_multi_index_type> pledge_mining_index;

} } // graphene::chain

FC_REFLECT_DERIVED( graphene::chain::pledge_mining_object, (graphene::db::object),
                    (pledge_account)
                    (witness)
                    (last_bonus_block_num)
                    (pledge_id)
                  )

max_stars_repo_name: abitmore/yoyow-core

max_issues_repo_name: yoyow-org/bitshares-core

max_forks_repo_name: yoyow-org/bitshares-core