<commit_before>//--------------------------------------------------------------------------------------------------
// Implementation of the papers "Exact Acceleration of Linear Object Detectors", 12th European
// Conference on Computer Vision, 2012 and "Deformable Part Models with Individual Part Scaling",
// 24th British Machine Vision Conference, 2013.
//
// Copyright (c) 2013 Idiap Research Institute, <http://www.idiap.ch/>
// Written by Charles Dubout <charles.dubout@idiap.ch>
//
// This file is part of FFLDv2 (the Fast Fourier Linear Detector version 2)
//
// FFLDv2 is free software: you can redistribute it and/or modify it under the terms of the GNU
// Affero General Public License version 3 as published by the Free Software Foundation.
//
// FFLDv2 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 Affero
// General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License along with FFLDv2. If
// not, see <http://www.gnu.org/licenses/>.
//--------------------------------------------------------------------------------------------------

#include "Scene.h"

#include <algorithm>
#include <iostream>
#include <sstream>

#include <libxml/parser.h>

using namespace FFLD;
using namespace std;

Scene::Scene() : width_(0), height_(0), depth_(0)
{
}

Scene::Scene(int width, int height, int depth, const string & filename,
			 const vector<Object> & objects) : width_(width), height_(height), depth_(depth),
filename_(filename), objects_(objects)
{
}

bool Scene::empty() const
{
	return ((width() <= 0) || (height() <= 0) || (depth() <= 0) || filename().empty()) &&
		   objects().empty();
}

template <typename Result>
static inline Result content(const xmlNodePtr cur)
{
	if ((cur == NULL) || (cur->xmlChildrenNode == NULL))
		return Result();

	istringstream iss(reinterpret_cast<const char *>(cur->xmlChildrenNode->content));
	Result result;
	// iss >> result;
	result = iss.str()
	return result;
}

Scene::Scene(const string & filename)
{
	// const string Names[20] =
	// {
	// 	"aeroplane", "bicycle", "bird", "boat", "bottle", "bus", "car", "cat", "chair", "cow",
	// 	"diningtable", "dog", "horse", "motorbike", "person", "pottedplant", "sheep", "sofa",
	// 	"train", "tvmonitor"
	// };

        const string Names[80] =
        {
            "airplane", "apple", "backpack", "banana", "baseball bat",
            "baseball glove", "bear", "bed", "bench", "bicycle", "bird",
            "boat", "book", "bottle", "bowl", "broccoli", "bus", "cake",
            "car", "carrot", "cat", "cell phone", "chair", "clock", "couch",
            "cow", "cup", "dining table", "dog", "donut", "elephant",
            "fire hydrant", "fork", "frisbee", "giraffe", "hair drier",
            "handbag", "horse", "hot dog", "keyboard", "kite", "knife",
            "laptop", "microwave", "motorcycle", "mouse", "orange",
            "oven", "parking meter", "person", "pizza", "potted plant",
            "refrigerator", "remote", "sandwich", "scissors", "sheep",
            "sink", "skateboard", "skis", "snowboard", "spoon", "sports ball",
            "stop sign", "suitcase", "surfboard", "teddy bear", "tennis racket",
            "tie", "toaster", "toilet", "toothbrush", "traffic light", "train",
            "truck", "tv", "umbrella", "vase", "wine", "zebra"
        };

	const string Poses[4] =
	{
		"Frontal", "Left", "Rear", "Right"
	};

	xmlDoc * doc = xmlParseFile(filename.c_str());

	if (doc == NULL) {
		cerr << "Could not open " << filename << endl;
		return;
	}

	xmlNodePtr cur = xmlDocGetRootElement(doc);

	if (cur == NULL) {
		xmlFreeDoc(doc);
		cerr << "Could not open " << filename << endl;
		return;
	}

	if (xmlStrcmp(cur->name, reinterpret_cast<const xmlChar *>("annotation"))) {
		xmlFreeDoc(doc);
		cerr << "Could not open " << filename << endl;
		return;
	}

	cur = cur->xmlChildrenNode;

	while (cur != NULL) {
		if (!xmlStrcmp(cur->name, reinterpret_cast<const xmlChar *>("filename"))) {
			// Full path
			size_t last = filename.rfind('/');

			if (last != string::npos) {
				last = filename.rfind('/', last - 1);

				if (last != string::npos)
					filename_ = filename.substr(0, last) + "/JPEGImages/" +
								content<string>(cur);
			}
		}
		else if (!xmlStrcmp(cur->name, reinterpret_cast<const xmlChar *>("size"))) {
			xmlNodePtr cur2 = cur->xmlChildrenNode;

			while (cur2 != NULL) {
				if (!xmlStrcmp(cur2->name, reinterpret_cast<const xmlChar *>("width")))
					width_ = content<int>(cur2);
				else if (!xmlStrcmp(cur2->name, reinterpret_cast<const xmlChar *>("height")))
					height_ = content<int>(cur2);
				else if (!xmlStrcmp(cur2->name, reinterpret_cast<const xmlChar *>("depth")))
					depth_ = content<int>(cur2);

				cur2 = cur2->next;
			}
		}
		else if (!xmlStrcmp(cur->name, reinterpret_cast<const xmlChar *>("object"))) {
			objects_.push_back(Object());

			xmlNodePtr cur2 = cur->xmlChildrenNode;

			while (cur2 != NULL) {
				if (!xmlStrcmp(cur2->name, reinterpret_cast<const xmlChar *>("name"))) {
					const string * iter =
						find(Names, Names + 80, content<string>(cur2));
					std::cout << "XML NAME: " << content<string>(cur2) << std::endl;

					if (iter != Names + 80)
						objects_.back().setName(static_cast<Object::Name>(iter - Names));
				}
				else if (!xmlStrcmp(cur2->name, reinterpret_cast<const xmlChar *>("pose"))) {
					const string * iter =
						find(Poses, Poses + 4, content<string>(cur2));

					if (iter != Poses + 4)
						objects_.back().setPose(static_cast<Object::Pose>(iter - Poses));
				}
				else if (!xmlStrcmp(cur2->name, reinterpret_cast<const xmlChar *>("truncated"))) {
					objects_.back().setTruncated(content<bool>(cur2));
				}
				else if (!xmlStrcmp(cur2->name, reinterpret_cast<const xmlChar *>("difficult"))) {
					objects_.back().setDifficult(content<bool>(cur2));
				}
				else if (!xmlStrcmp(cur2->name, reinterpret_cast<const xmlChar *>("bndbox"))) {
					Rectangle bndbox;

					xmlNodePtr cur3 = cur2->xmlChildrenNode;

					while (cur3 != NULL) {
						if (!xmlStrcmp(cur3->name, reinterpret_cast<const xmlChar *>("xmin")))
							bndbox.setX(content<int>(cur3));
						else if (!xmlStrcmp(cur3->name, reinterpret_cast<const xmlChar *>("ymin")))
							bndbox.setY(content<int>(cur3));
						else if (!xmlStrcmp(cur3->name, reinterpret_cast<const xmlChar *>("xmax")))
							bndbox.setWidth(content<int>(cur3));
						else if (!xmlStrcmp(cur3->name, reinterpret_cast<const xmlChar *>("ymax")))
							bndbox.setHeight(content<int>(cur3));

						cur3 = cur3->next;
					}

					// Only set the bounding box if all values have been assigned
					if (bndbox.x() && bndbox.y() && bndbox.width() && bndbox.height()) {
						bndbox.setX(bndbox.x() - 1);
						bndbox.setY(bndbox.y() - 1);
						bndbox.setWidth(bndbox.width() - bndbox.x());
						bndbox.setHeight(bndbox.height() - bndbox.y());
						objects_.back().setBndbox(bndbox);
					}
				}

				cur2 = cur2->next;
			}
		}

		cur = cur->next;
	}

	xmlFreeDoc(doc);
}

int Scene::width() const
{
	return width_;
}

void Scene::setWidth(int width)
{
	width_ = width;
}

int Scene::height() const
{
	return height_;
}

void Scene::setHeight(int height)
{
	height_ = height;
}

int Scene::depth() const
{
	return depth_;
}

void Scene::setDepth(int depth)
{
	depth_ = depth;
}

const string & Scene::filename() const
{
	return filename_;
}

void Scene::setFilename(const string &filename)
{
	filename_ = filename;
}

const vector<Object> & Scene::objects() const
{
	return objects_;
}

void Scene::setObjects(const vector<Object> &objects)
{
	objects_ = objects;
}

ostream & FFLD::operator<<(ostream & os, const Scene & scene)
{
	os << scene.width() << ' ' << scene.height() << ' ' << scene.depth() << ' '
	   << scene.objects().size() << ' ' << scene.filename() << endl;

	for (int i = 0; i < scene.objects().size(); ++i)
		os << scene.objects()[i] << endl;

	return os;
}

istream & FFLD::operator>>(istream & is, Scene & scene)
{
	int width, height, depth, nbObjects;

    is >> width >> height >> depth >> nbObjects;
	is.get(); // Remove the space

	string filename;
	getline(is, filename);

	vector<Object> objects(nbObjects);

	for (int i = 0; i < nbObjects; ++i)
		is >> objects[i];

	if (!is) {
		scene = Scene();
		return is;
	}

	scene = Scene(width, height, depth, filename, objects);

	return is;
}
<commit_msg>use noskiws for Scene.ccp:content<commit_after>//--------------------------------------------------------------------------------------------------
// Implementation of the papers "Exact Acceleration of Linear Object Detectors", 12th European
// Conference on Computer Vision, 2012 and "Deformable Part Models with Individual Part Scaling",
// 24th British Machine Vision Conference, 2013.
//
// Copyright (c) 2013 Idiap Research Institute, <http://www.idiap.ch/>
// Written by Charles Dubout <charles.dubout@idiap.ch>
//
// This file is part of FFLDv2 (the Fast Fourier Linear Detector version 2)
//
// FFLDv2 is free software: you can redistribute it and/or modify it under the terms of the GNU
// Affero General Public License version 3 as published by the Free Software Foundation.
//
// FFLDv2 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 Affero
// General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License along with FFLDv2. If
// not, see <http://www.gnu.org/licenses/>.
//--------------------------------------------------------------------------------------------------

#include "Scene.h"

#include <algorithm>
#include <iostream>
#include <sstream>

#include <libxml/parser.h>

using namespace FFLD;
using namespace std;

Scene::Scene() : width_(0), height_(0), depth_(0)
{
}

Scene::Scene(int width, int height, int depth, const string & filename,
			 const vector<Object> & objects) : width_(width), height_(height), depth_(depth),
filename_(filename), objects_(objects)
{
}

bool Scene::empty() const
{
	return ((width() <= 0) || (height() <= 0) || (depth() <= 0) || filename().empty()) &&
		   objects().empty();
}

template <typename Result>
static inline Result content(const xmlNodePtr cur)
{
	if ((cur == NULL) || (cur->xmlChildrenNode == NULL))
		return Result();

	istringstream iss(reinterpret_cast<const char *>(cur->xmlChildrenNode->content));
	Result result;
	iss >> noskipws >> result;
	return result;
}

Scene::Scene(const string & filename)
{
	// const string Names[20] =
	// {
	// 	"aeroplane", "bicycle", "bird", "boat", "bottle", "bus", "car", "cat", "chair", "cow",
	// 	"diningtable", "dog", "horse", "motorbike", "person", "pottedplant", "sheep", "sofa",
	// 	"train", "tvmonitor"
	// };

        const string Names[80] =
        {
            "airplane", "apple", "backpack", "banana", "baseball bat",
            "baseball glove", "bear", "bed", "bench", "bicycle", "bird",
            "boat", "book", "bottle", "bowl", "broccoli", "bus", "cake",
            "car", "carrot", "cat", "cell phone", "chair", "clock", "couch",
            "cow", "cup", "dining table", "dog", "donut", "elephant",
            "fire hydrant", "fork", "frisbee", "giraffe", "hair drier",
            "handbag", "horse", "hot dog", "keyboard", "kite", "knife",
            "laptop", "microwave", "motorcycle", "mouse", "orange",
            "oven", "parking meter", "person", "pizza", "potted plant",
            "refrigerator", "remote", "sandwich", "scissors", "sheep",
            "sink", "skateboard", "skis", "snowboard", "spoon", "sports ball",
            "stop sign", "suitcase", "surfboard", "teddy bear", "tennis racket",
            "tie", "toaster", "toilet", "toothbrush", "traffic light", "train",
            "truck", "tv", "umbrella", "vase", "wine", "zebra"
        };

	const string Poses[4] =
	{
		"Frontal", "Left", "Rear", "Right"
	};

	xmlDoc * doc = xmlParseFile(filename.c_str());

	if (doc == NULL) {
		cerr << "Could not open " << filename << endl;
		return;
	}

	xmlNodePtr cur = xmlDocGetRootElement(doc);

	if (cur == NULL) {
		xmlFreeDoc(doc);
		cerr << "Could not open " << filename << endl;
		return;
	}

	if (xmlStrcmp(cur->name, reinterpret_cast<const xmlChar *>("annotation"))) {
		xmlFreeDoc(doc);
		cerr << "Could not open " << filename << endl;
		return;
	}

	cur = cur->xmlChildrenNode;

	while (cur != NULL) {
		if (!xmlStrcmp(cur->name, reinterpret_cast<const xmlChar *>("filename"))) {
			// Full path
			size_t last = filename.rfind('/');

			if (last != string::npos) {
				last = filename.rfind('/', last - 1);

				if (last != string::npos)
					filename_ = filename.substr(0, last) + "/JPEGImages/" +
								content<string>(cur);
			}
		}
		else if (!xmlStrcmp(cur->name, reinterpret_cast<const xmlChar *>("size"))) {
			xmlNodePtr cur2 = cur->xmlChildrenNode;

			while (cur2 != NULL) {
				if (!xmlStrcmp(cur2->name, reinterpret_cast<const xmlChar *>("width")))
					width_ = content<int>(cur2);
				else if (!xmlStrcmp(cur2->name, reinterpret_cast<const xmlChar *>("height")))
					height_ = content<int>(cur2);
				else if (!xmlStrcmp(cur2->name, reinterpret_cast<const xmlChar *>("depth")))
					depth_ = content<int>(cur2);

				cur2 = cur2->next;
			}
		}
		else if (!xmlStrcmp(cur->name, reinterpret_cast<const xmlChar *>("object"))) {
			objects_.push_back(Object());

			xmlNodePtr cur2 = cur->xmlChildrenNode;

			while (cur2 != NULL) {
				if (!xmlStrcmp(cur2->name, reinterpret_cast<const xmlChar *>("name"))) {
					const string * iter =
						find(Names, Names + 80, content<string>(cur2));

					if (iter != Names + 80)
						objects_.back().setName(static_cast<Object::Name>(iter - Names));
				}
				else if (!xmlStrcmp(cur2->name, reinterpret_cast<const xmlChar *>("pose"))) {
					const string * iter =
						find(Poses, Poses + 4, content<string>(cur2));

					if (iter != Poses + 4)
						objects_.back().setPose(static_cast<Object::Pose>(iter - Poses));
				}
				else if (!xmlStrcmp(cur2->name, reinterpret_cast<const xmlChar *>("truncated"))) {
					objects_.back().setTruncated(content<bool>(cur2));
				}
				else if (!xmlStrcmp(cur2->name, reinterpret_cast<const xmlChar *>("difficult"))) {
					objects_.back().setDifficult(content<bool>(cur2));
				}
				else if (!xmlStrcmp(cur2->name, reinterpret_cast<const xmlChar *>("bndbox"))) {
					Rectangle bndbox;

					xmlNodePtr cur3 = cur2->xmlChildrenNode;

					while (cur3 != NULL) {
						if (!xmlStrcmp(cur3->name, reinterpret_cast<const xmlChar *>("xmin")))
							bndbox.setX(content<int>(cur3));
						else if (!xmlStrcmp(cur3->name, reinterpret_cast<const xmlChar *>("ymin")))
							bndbox.setY(content<int>(cur3));
						else if (!xmlStrcmp(cur3->name, reinterpret_cast<const xmlChar *>("xmax")))
							bndbox.setWidth(content<int>(cur3));
						else if (!xmlStrcmp(cur3->name, reinterpret_cast<const xmlChar *>("ymax")))
							bndbox.setHeight(content<int>(cur3));

						cur3 = cur3->next;
					}

					// Only set the bounding box if all values have been assigned
					if (bndbox.x() && bndbox.y() && bndbox.width() && bndbox.height()) {
						bndbox.setX(bndbox.x() - 1);
						bndbox.setY(bndbox.y() - 1);
						bndbox.setWidth(bndbox.width() - bndbox.x());
						bndbox.setHeight(bndbox.height() - bndbox.y());
						objects_.back().setBndbox(bndbox);
					}
				}

				cur2 = cur2->next;
			}
		}

		cur = cur->next;
	}

	xmlFreeDoc(doc);
}

int Scene::width() const
{
	return width_;
}

void Scene::setWidth(int width)
{
	width_ = width;
}

int Scene::height() const
{
	return height_;
}

void Scene::setHeight(int height)
{
	height_ = height;
}

int Scene::depth() const
{
	return depth_;
}

void Scene::setDepth(int depth)
{
	depth_ = depth;
}

const string & Scene::filename() const
{
	return filename_;
}

void Scene::setFilename(const string &filename)
{
	filename_ = filename;
}

const vector<Object> & Scene::objects() const
{
	return objects_;
}

void Scene::setObjects(const vector<Object> &objects)
{
	objects_ = objects;
}

ostream & FFLD::operator<<(ostream & os, const Scene & scene)
{
	os << scene.width() << ' ' << scene.height() << ' ' << scene.depth() << ' '
	   << scene.objects().size() << ' ' << scene.filename() << endl;

	for (int i = 0; i < scene.objects().size(); ++i)
		os << scene.objects()[i] << endl;

	return os;
}

istream & FFLD::operator>>(istream & is, Scene & scene)
{
	int width, height, depth, nbObjects;

    is >> width >> height >> depth >> nbObjects;
	is.get(); // Remove the space

	string filename;
	getline(is, filename);

	vector<Object> objects(nbObjects);

	for (int i = 0; i < nbObjects; ++i)
		is >> objects[i];

	if (!is) {
		scene = Scene();
		return is;
	}

	scene = Scene(width, height, depth, filename, objects);

	return is;
}
<|endoftext|>


<commit_before>//--------------------------------------------------------------------------------------------------
// Implementation of the papers "Exact Acceleration of Linear Object Detectors", 12th European
// Conference on Computer Vision, 2012 and "Deformable Part Models with Individual Part Scaling",
// 24th British Machine Vision Conference, 2013.
//
// Copyright (c) 2013 Idiap Research Institute, <http://www.idiap.ch/>
// Written by Charles Dubout <charles.dubout@idiap.ch>
//
// This file is part of FFLDv2 (the Fast Fourier Linear Detector version 2)
//
// FFLDv2 is free software: you can redistribute it and/or modify it under the terms of the GNU
// Affero General Public License version 3 as published by the Free Software Foundation.
//
// FFLDv2 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 Affero
// General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License along with FFLDv2. If
// not, see <http://www.gnu.org/licenses/>.
//--------------------------------------------------------------------------------------------------

#include "Scene.h"

#include <algorithm>
#include <iostream>
#include <sstream>

#include <libxml/parser.h>

using namespace FFLD;
using namespace std;

Scene::Scene() : width_(0), height_(0), depth_(0)
{
}

Scene::Scene(int width, int height, int depth, const string & filename,
			 const vector<Object> & objects) : width_(width), height_(height), depth_(depth),
filename_(filename), objects_(objects)
{
}

bool Scene::empty() const
{
	return ((width() <= 0) || (height() <= 0) || (depth() <= 0) || filename().empty()) &&
		   objects().empty();
}

template <typename Result>
static inline Result content(const xmlNodePtr cur)
{
	if ((cur == NULL) || (cur->xmlChildrenNode == NULL))
		return Result();

	istringstream iss(reinterpret_cast<const char *>(cur->xmlChildrenNode->content));
	Result result;
	iss >> result;
	return result;
}

Scene::Scene(const string & filename)
{
	// const string Names[20] =
	// {
	// 	"aeroplane", "bicycle", "bird", "boat", "bottle", "bus", "car", "cat", "chair", "cow",
	// 	"diningtable", "dog", "horse", "motorbike", "person", "pottedplant", "sheep", "sofa",
	// 	"train", "tvmonitor"
	// };

        const string Names[80] =
        {
            "airplane", "apple", "backpack", "banana", "baseball bat",
            "baseball glove", "bear", "bed", "bench", "bicycle", "bird",
            "boat", "book", "bottle", "bowl", "broccoli", "bus", "cake",
            "car", "carrot", "cat", "cell phone", "chair", "clock", "couch",
            "cow", "cup", "dining table", "dog", "donut", "elephant",
            "fire hydrant", "fork", "frisbee", "giraffe", "hair drier",
            "handbag", "horse", "hot dog", "keyboard", "kite", "knife",
            "laptop", "microwave", "motorcycle", "mouse", "orange",
            "oven", "parking meter", "person", "pizza", "potted plant",
            "refrigerator", "remote", "sandwich", "scissors", "sheep",
            "sink", "skateboard", "skis", "snowboard", "spoon", "sports ball",
            "stop sign", "suitcase", "surfboard", "teddy bear", "tennis racket",
            "tie", "toaster", "toilet", "toothbrush", "traffic light", "train",
            "truck", "tv", "umbrella", "vase", "wine", "zebra"
        };

	const string Poses[4] =
	{
		"Frontal", "Left", "Rear", "Right"
	};

	xmlDoc * doc = xmlParseFile(filename.c_str());

	if (doc == NULL) {
		cerr << "Could not open " << filename << endl;
		return;
	}

	xmlNodePtr cur = xmlDocGetRootElement(doc);

	if (cur == NULL) {
		xmlFreeDoc(doc);
		cerr << "Could not open " << filename << endl;
		return;
	}

	if (xmlStrcmp(cur->name, reinterpret_cast<const xmlChar *>("annotation"))) {
		xmlFreeDoc(doc);
		cerr << "Could not open " << filename << endl;
		return;
	}

	cur = cur->xmlChildrenNode;

	while (cur != NULL) {
		if (!xmlStrcmp(cur->name, reinterpret_cast<const xmlChar *>("filename"))) {
			// Full path
			size_t last = filename.rfind('/');

			if (last != string::npos) {
				last = filename.rfind('/', last - 1);

				if (last != string::npos)
					filename_ = filename.substr(0, last) + "/JPEGImages/" +
								content<string>(cur);
			}
		}
		else if (!xmlStrcmp(cur->name, reinterpret_cast<const xmlChar *>("size"))) {
			xmlNodePtr cur2 = cur->xmlChildrenNode;

			while (cur2 != NULL) {
				if (!xmlStrcmp(cur2->name, reinterpret_cast<const xmlChar *>("width")))
					width_ = content<int>(cur2);
				else if (!xmlStrcmp(cur2->name, reinterpret_cast<const xmlChar *>("height")))
					height_ = content<int>(cur2);
				else if (!xmlStrcmp(cur2->name, reinterpret_cast<const xmlChar *>("depth")))
					depth_ = content<int>(cur2);

				cur2 = cur2->next;
			}
		}
		else if (!xmlStrcmp(cur->name, reinterpret_cast<const xmlChar *>("object"))) {
			objects_.push_back(Object());

			xmlNodePtr cur2 = cur->xmlChildrenNode;

			while (cur2 != NULL) {
				if (!xmlStrcmp(cur2->name, reinterpret_cast<const xmlChar *>("name"))) {
					const string * iter =
						find(Names, Names + 80, content<string>(cur2));

					if (iter != Names + 80)
						objects_.back().setName(static_cast<Object::Name>(iter - Names));
				}
				else if (!xmlStrcmp(cur2->name, reinterpret_cast<const xmlChar *>("pose"))) {
					const string * iter =
						find(Poses, Poses + 4, content<string>(cur2));

					if (iter != Poses + 4)
						objects_.back().setPose(static_cast<Object::Pose>(iter - Poses));
				}
				else if (!xmlStrcmp(cur2->name, reinterpret_cast<const xmlChar *>("truncated"))) {
					objects_.back().setTruncated(content<bool>(cur2));
				}
				else if (!xmlStrcmp(cur2->name, reinterpret_cast<const xmlChar *>("difficult"))) {
					objects_.back().setDifficult(content<bool>(cur2));
				}
				else if (!xmlStrcmp(cur2->name, reinterpret_cast<const xmlChar *>("bndbox"))) {
					Rectangle bndbox;

					xmlNodePtr cur3 = cur2->xmlChildrenNode;

					while (cur3 != NULL) {
						if (!xmlStrcmp(cur3->name, reinterpret_cast<const xmlChar *>("xmin")))
							bndbox.setX(content<int>(cur3));
						else if (!xmlStrcmp(cur3->name, reinterpret_cast<const xmlChar *>("ymin")))
							bndbox.setY(content<int>(cur3));
						else if (!xmlStrcmp(cur3->name, reinterpret_cast<const xmlChar *>("xmax")))
							bndbox.setWidth(content<int>(cur3));
						else if (!xmlStrcmp(cur3->name, reinterpret_cast<const xmlChar *>("ymax")))
							bndbox.setHeight(content<int>(cur3));

						cur3 = cur3->next;
					}

					// Only set the bounding box if all values have been assigned
					if (bndbox.x() && bndbox.y() && bndbox.width() && bndbox.height()) {
						bndbox.setX(bndbox.x() - 1);
						bndbox.setY(bndbox.y() - 1);
						bndbox.setWidth(bndbox.width() - bndbox.x());
						bndbox.setHeight(bndbox.height() - bndbox.y());
						objects_.back().setBndbox(bndbox);
					}
				}

				cur2 = cur2->next;
			}
		}

		cur = cur->next;
	}

	xmlFreeDoc(doc);
}

int Scene::width() const
{
	return width_;
}

void Scene::setWidth(int width)
{
	width_ = width;
}

int Scene::height() const
{
	return height_;
}

void Scene::setHeight(int height)
{
	height_ = height;
}

int Scene::depth() const
{
	return depth_;
}

void Scene::setDepth(int depth)
{
	depth_ = depth;
}

const string & Scene::filename() const
{
	return filename_;
}

void Scene::setFilename(const string &filename)
{
	filename_ = filename;
}

const vector<Object> & Scene::objects() const
{
	return objects_;
}

void Scene::setObjects(const vector<Object> &objects)
{
	objects_ = objects;
}

ostream & FFLD::operator<<(ostream & os, const Scene & scene)
{
	os << scene.width() << ' ' << scene.height() << ' ' << scene.depth() << ' '
	   << scene.objects().size() << ' ' << scene.filename() << endl;

	for (int i = 0; i < scene.objects().size(); ++i)
		os << scene.objects()[i] << endl;

	return os;
}

istream & FFLD::operator>>(istream & is, Scene & scene)
{
	int width, height, depth, nbObjects;

    is >> width >> height >> depth >> nbObjects;
	is.get(); // Remove the space

	string filename;
	getline(is, filename);

	vector<Object> objects(nbObjects);

	for (int i = 0; i < nbObjects; ++i)
		is >> objects[i];

	if (!is) {
		scene = Scene();
		return is;
	}

	scene = Scene(width, height, depth, filename, objects);

	return is;
}
<commit_msg>noskipws<commit_after>//--------------------------------------------------------------------------------------------------
// Implementation of the papers "Exact Acceleration of Linear Object Detectors", 12th European
// Conference on Computer Vision, 2012 and "Deformable Part Models with Individual Part Scaling",
// 24th British Machine Vision Conference, 2013.
//
// Copyright (c) 2013 Idiap Research Institute, <http://www.idiap.ch/>
// Written by Charles Dubout <charles.dubout@idiap.ch>
//
// This file is part of FFLDv2 (the Fast Fourier Linear Detector version 2)
//
// FFLDv2 is free software: you can redistribute it and/or modify it under the terms of the GNU
// Affero General Public License version 3 as published by the Free Software Foundation.
//
// FFLDv2 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 Affero
// General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License along with FFLDv2. If
// not, see <http://www.gnu.org/licenses/>.
//--------------------------------------------------------------------------------------------------

#include "Scene.h"

#include <algorithm>
#include <iostream>
#include <sstream>

#include <libxml/parser.h>

using namespace FFLD;
using namespace std;

Scene::Scene() : width_(0), height_(0), depth_(0)
{
}

Scene::Scene(int width, int height, int depth, const string & filename,
			 const vector<Object> & objects) : width_(width), height_(height), depth_(depth),
filename_(filename), objects_(objects)
{
}

bool Scene::empty() const
{
	return ((width() <= 0) || (height() <= 0) || (depth() <= 0) || filename().empty()) &&
		   objects().empty();
}

template <typename Result>
static inline Result content(const xmlNodePtr cur)
{
	if ((cur == NULL) || (cur->xmlChildrenNode == NULL))
		return Result();

	istringstream iss(reinterpret_cast<const char *>(cur->xmlChildrenNode->content));
	Result result;
	iss >> noskipws >> result;
	return result;
}

Scene::Scene(const string & filename)
{
	// const string Names[20] =
	// {
	// 	"aeroplane", "bicycle", "bird", "boat", "bottle", "bus", "car", "cat", "chair", "cow",
	// 	"diningtable", "dog", "horse", "motorbike", "person", "pottedplant", "sheep", "sofa",
	// 	"train", "tvmonitor"
	// };

        const string Names[80] =
        {
            "airplane", "apple", "backpack", "banana", "baseball bat",
            "baseball glove", "bear", "bed", "bench", "bicycle", "bird",
            "boat", "book", "bottle", "bowl", "broccoli", "bus", "cake",
            "car", "carrot", "cat", "cell phone", "chair", "clock", "couch",
            "cow", "cup", "dining table", "dog", "donut", "elephant",
            "fire hydrant", "fork", "frisbee", "giraffe", "hair drier",
            "handbag", "horse", "hot dog", "keyboard", "kite", "knife",
            "laptop", "microwave", "motorcycle", "mouse", "orange",
            "oven", "parking meter", "person", "pizza", "potted plant",
            "refrigerator", "remote", "sandwich", "scissors", "sheep",
            "sink", "skateboard", "skis", "snowboard", "spoon", "sports ball",
            "stop sign", "suitcase", "surfboard", "teddy bear", "tennis racket",
            "tie", "toaster", "toilet", "toothbrush", "traffic light", "train",
            "truck", "tv", "umbrella", "vase", "wine", "zebra"
        };

	const string Poses[4] =
	{
		"Frontal", "Left", "Rear", "Right"
	};

	xmlDoc * doc = xmlParseFile(filename.c_str());

	if (doc == NULL) {
		cerr << "Could not open " << filename << endl;
		return;
	}

	xmlNodePtr cur = xmlDocGetRootElement(doc);

	if (cur == NULL) {
		xmlFreeDoc(doc);
		cerr << "Could not open " << filename << endl;
		return;
	}

	if (xmlStrcmp(cur->name, reinterpret_cast<const xmlChar *>("annotation"))) {
		xmlFreeDoc(doc);
		cerr << "Could not open " << filename << endl;
		return;
	}

	cur = cur->xmlChildrenNode;

	while (cur != NULL) {
		if (!xmlStrcmp(cur->name, reinterpret_cast<const xmlChar *>("filename"))) {
			// Full path
			size_t last = filename.rfind('/');

			if (last != string::npos) {
				last = filename.rfind('/', last - 1);

				if (last != string::npos)
					filename_ = filename.substr(0, last) + "/JPEGImages/" +
								content<string>(cur);
			}
		}
		else if (!xmlStrcmp(cur->name, reinterpret_cast<const xmlChar *>("size"))) {
			xmlNodePtr cur2 = cur->xmlChildrenNode;

			while (cur2 != NULL) {
				if (!xmlStrcmp(cur2->name, reinterpret_cast<const xmlChar *>("width")))
					width_ = content<int>(cur2);
				else if (!xmlStrcmp(cur2->name, reinterpret_cast<const xmlChar *>("height")))
					height_ = content<int>(cur2);
				else if (!xmlStrcmp(cur2->name, reinterpret_cast<const xmlChar *>("depth")))
					depth_ = content<int>(cur2);

				cur2 = cur2->next;
			}
		}
		else if (!xmlStrcmp(cur->name, reinterpret_cast<const xmlChar *>("object"))) {
			objects_.push_back(Object());

			xmlNodePtr cur2 = cur->xmlChildrenNode;

			while (cur2 != NULL) {
				if (!xmlStrcmp(cur2->name, reinterpret_cast<const xmlChar *>("name"))) {
					const string * iter =
						find(Names, Names + 80, content<string>(cur2));

					if (iter != Names + 80)
						objects_.back().setName(static_cast<Object::Name>(iter - Names));
				}
				else if (!xmlStrcmp(cur2->name, reinterpret_cast<const xmlChar *>("pose"))) {
					const string * iter =
						find(Poses, Poses + 4, content<string>(cur2));

					if (iter != Poses + 4)
						objects_.back().setPose(static_cast<Object::Pose>(iter - Poses));
				}
				else if (!xmlStrcmp(cur2->name, reinterpret_cast<const xmlChar *>("truncated"))) {
					objects_.back().setTruncated(content<bool>(cur2));
				}
				else if (!xmlStrcmp(cur2->name, reinterpret_cast<const xmlChar *>("difficult"))) {
					objects_.back().setDifficult(content<bool>(cur2));
				}
				else if (!xmlStrcmp(cur2->name, reinterpret_cast<const xmlChar *>("bndbox"))) {
					Rectangle bndbox;

					xmlNodePtr cur3 = cur2->xmlChildrenNode;

					while (cur3 != NULL) {
						if (!xmlStrcmp(cur3->name, reinterpret_cast<const xmlChar *>("xmin")))
							bndbox.setX(content<int>(cur3));
						else if (!xmlStrcmp(cur3->name, reinterpret_cast<const xmlChar *>("ymin")))
							bndbox.setY(content<int>(cur3));
						else if (!xmlStrcmp(cur3->name, reinterpret_cast<const xmlChar *>("xmax")))
							bndbox.setWidth(content<int>(cur3));
						else if (!xmlStrcmp(cur3->name, reinterpret_cast<const xmlChar *>("ymax")))
							bndbox.setHeight(content<int>(cur3));

						cur3 = cur3->next;
					}

					// Only set the bounding box if all values have been assigned
					if (bndbox.x() && bndbox.y() && bndbox.width() && bndbox.height()) {
						bndbox.setX(bndbox.x() - 1);
						bndbox.setY(bndbox.y() - 1);
						bndbox.setWidth(bndbox.width() - bndbox.x());
						bndbox.setHeight(bndbox.height() - bndbox.y());
						objects_.back().setBndbox(bndbox);
					}
				}

				cur2 = cur2->next;
			}
		}

		cur = cur->next;
	}

	xmlFreeDoc(doc);
}

int Scene::width() const
{
	return width_;
}

void Scene::setWidth(int width)
{
	width_ = width;
}

int Scene::height() const
{
	return height_;
}

void Scene::setHeight(int height)
{
	height_ = height;
}

int Scene::depth() const
{
	return depth_;
}

void Scene::setDepth(int depth)
{
	depth_ = depth;
}

const string & Scene::filename() const
{
	return filename_;
}

void Scene::setFilename(const string &filename)
{
	filename_ = filename;
}

const vector<Object> & Scene::objects() const
{
	return objects_;
}

void Scene::setObjects(const vector<Object> &objects)
{
	objects_ = objects;
}

ostream & FFLD::operator<<(ostream & os, const Scene & scene)
{
	os << scene.width() << ' ' << scene.height() << ' ' << scene.depth() << ' '
	   << scene.objects().size() << ' ' << scene.filename() << endl;

	for (int i = 0; i < scene.objects().size(); ++i)
		os << scene.objects()[i] << endl;

	return os;
}

istream & FFLD::operator>>(istream & is, Scene & scene)
{
	int width, height, depth, nbObjects;

    is >> width >> height >> depth >> nbObjects;
	is.get(); // Remove the space

	string filename;
	getline(is, filename);

	vector<Object> objects(nbObjects);

	for (int i = 0; i < nbObjects; ++i)
		is >> objects[i];

	if (!is) {
		scene = Scene();
		return is;
	}

	scene = Scene(width, height, depth, filename, objects);

	return is;
}
<|endoftext|>


<commit_before>#include "State.h"

Context::Context(char * cursor) : start(0) {
   this->cursor = cursor;
   this->currentState = new OpenDTA();
}

void * Context::advance() {

    for (start = cursor; cursor && *cursor != '>'; cursor++);

    if (cursor && *cursor == '>') {
      cursor++;
      strncpy(buffer, start, cursor - start);
      buffer[cursor-start]='\0';
    }

    while(this->currentState->check(this->buffer))
    {
        currentState->process(*this);
        this->currentState = this->currentState->advanceState();
    }

    return (void *)(start);
}

// OpenDTA State
bool OpenDTA::process(Context & ctx)
{
   ctx.advance();
   return true;
}

State * OpenDTA::advanceState() {
   return new OpenHeader();
}

// OpenHeader State
bool OpenHeader::process(Context & ctx)
{
     ctx.advance();
     return true;
}

State * OpenHeader::advanceState()
{
  return new OpenRelease();
}

// OpenRelease State
State * OpenRelease::advanceState() {
  return new OpenByteOrder();
}

bool OpenRelease::process(Context & ctx)
{
     string version = ctx.getChars(3);
     cout << version << endl;
     switch(strtol(version.c_str(), NULL, 10))
     {
	      case 117:
               ctx.hdr.fileRelease = R117;
               break;

        default:
               ctx.hdr.fileRelease = R117;
               break;

     }

     ctx.advance(); // CONTENT
     ctx.advance(); // </release>
     return true;
}

// OpenByteOrder State
State * OpenByteOrder::advanceState()
{
  return new OpenK();
}

bool OpenByteOrder::process(Context & ctx)
{
      string byteOrder = ctx.getChars(3);

      if (!strcasecmp(byteOrder.c_str(), XML_LSF))
        ctx.hdr.fileByteorder = LSF;
      else
        ctx.hdr.fileByteorder = MSF;

      ctx.advance(); // ORDER
      ctx.advance(); // </byteorder>

      return true;
}

// OpenK State
State * OpenK::advanceState()
{
  return new OpenN();
}

bool OpenK::process(Context & ctx)
{

    if (ctx.hdr.fileByteorder == LSF) {
        char * ctxbuf = (char *) ctx.advance();

        switch(ctx.hdr.fileRelease)
        {
          // 4 byte
          case R119:
          case R118:
                ctx.hdr.variables = GetLSF<int>(ctxbuf, 4);
                break;

          // 2 byte
          case R117:
               ctx.hdr.variables = GetLSF<int>(ctxbuf, 2);
               break;

          default:

                break;
        }

    } else {
         // MSF not implemented yet
    }

    ctx.advance();

    return true;
}

// OpenN State
State * OpenN::advanceState()
{
  return new OpenLabel();
}

bool OpenN::process(Context & ctx)
{
    char * ctxbuf = (char *) ctx.advance();

    if (ctx.hdr.fileByteorder == LSF)
    {
      switch(ctx.hdr.fileRelease)
      {
        // 8 byte
        case R119:
        case R118:
              ctx.hdr.observations = GetLSF<uint64_t>(ctxbuf, 8);
              break;

        // 4 byte
        case R117:
            ctx.hdr.observations = GetLSF<int>(ctxbuf, 4);
            break;

        default:
             break;
       }
    }
    else
    {
        // MSF not implemented yet
    }

    cout << "Observations: " << ctx.hdr.observations << endl;
    ctx.advance();
    return true;
}

// OpenLabel State
State * OpenLabel::advanceState()
{
  return new OpenTimeStamp();
}

bool OpenLabel::process(Context & ctx)
{
  char * ctxbuf = (char *) ctx.advance();
  int label_count = 0;

  if (ctx.hdr.fileByteorder == LSF)
  {
    switch(ctx.hdr.fileRelease)
    {
      case R119:
      case R118:
          label_count = GetLSF<int>(ctxbuf, 2);
          ctx.hdr.datalabel.assign(&ctxbuf[2],label_count);
          break;

      case R117:
          label_count = GetLSF<int>(ctxbuf, 1);
          ctx.hdr.datalabel.assign(&ctxbuf[1],label_count);
          break;

      default:
           break;
     }
  }
  else
  {
      // not implemented yet
  }

  cout << "Label Count: " << label_count << " " << ctx.hdr.datalabel << endl;
  ctx.advance();

  return true;
}

State * OpenTimeStamp::advanceState()
{
  return new CloseHeader();
}

bool OpenTimeStamp::process(Context & ctx)
{
  char * ctxbuf = (char *) ctx.advance();
  int label_count = 0;

  switch(ctx.hdr.fileRelease)
  {

    case R119:
    case R118:
    case R117:
        label_count = GetLSF<int>(ctxbuf, 1);
        ctx.hdr.ts.assign(&ctxbuf[1],label_count);
        break;
  }

  cout << "timeStamp: " << ctx.hdr.ts << endl;
  ctx.advance();
  return true;
}

State * CloseHeader::advanceState()
{
  return new OpenMap();
}

bool CloseHeader::process(Context & ctx)
{
  ctx.advance();
  return true;
}

State * OpenMap::advanceState()
{
  return new OpenMap();
}

bool OpenMap::process(Context & ctx)
{
    #define MAP_COUNT 14
    char * ctxbuf = (char *)ctx.advance();
    int i, j;
    cout << "here" << endl;

    string map_names[] = {
        "stata_data_start",
        "map",
        "variable_types",
        "varnames",
        "sortlist",
        "formats",
        "value_label_names",
        "variable_labels",
        "characteristics",
        "data",
        "strls",
        "value_labels",
        "stata_data_end",
        "eof"
    };

    for (i = 0; i < MAP_COUNT; i++, ctxbuf += 8)
    {
        ctx.map.stata_map[map_names[i].c_str()] = GetLSF<uint64_t>(ctxbuf, 8);
        cout << map_names[i].c_str() << " " << ctx.map.stata_map[map_names[i].c_str()] << endl;
    }

    return true;

}<commit_msg>done with vartypes<commit_after>#include "State.h"

Context::Context(char * cursor) : start(0) {
   this->cursor = cursor;
   this->currentState = new OpenDTA();
}

void * Context::advance() {

    for (start = cursor; cursor && *cursor != '>'; cursor++);

    if (cursor && *cursor == '>') {
      cursor++;
      strncpy(buffer, start, cursor - start);
      buffer[cursor-start]='\0';
    }

    while(this->currentState->check(this->buffer))
    {
        currentState->process(*this);
        this->currentState = this->currentState->advanceState();
    }

    return (void *)(start);
}

// OpenDTA State
bool OpenDTA::process(Context & ctx)
{
   ctx.advance();
   return true;
}

State * OpenDTA::advanceState() {
   return new OpenHeader();
}

// OpenHeader State
bool OpenHeader::process(Context & ctx)
{
     ctx.advance();
     return true;
}

State * OpenHeader::advanceState()
{
  return new OpenRelease();
}

// OpenRelease State
State * OpenRelease::advanceState() {
  return new OpenByteOrder();
}

bool OpenRelease::process(Context & ctx)
{
     string version = ctx.getChars(3);
     cout << version << endl;
     switch(strtol(version.c_str(), NULL, 10))
     {
	      case 117:
               ctx.hdr.fileRelease = R117;
               break;

        default:
               ctx.hdr.fileRelease = R117;
               break;

     }

     ctx.advance(); // CONTENT
     ctx.advance(); // </release>
     return true;
}

// OpenByteOrder State
State * OpenByteOrder::advanceState()
{
  return new OpenK();
}

bool OpenByteOrder::process(Context & ctx)
{
      string byteOrder = ctx.getChars(3);

      if (!strcasecmp(byteOrder.c_str(), XML_LSF))
        ctx.hdr.fileByteorder = LSF;
      else
        ctx.hdr.fileByteorder = MSF;

      ctx.advance(); // ORDER
      ctx.advance(); // </byteorder>

      return true;
}

// OpenK State
State * OpenK::advanceState()
{
  return new OpenN();
}

bool OpenK::process(Context & ctx)
{

    if (ctx.hdr.fileByteorder == LSF) {
        char * ctxbuf = (char *) ctx.advance();

        switch(ctx.hdr.fileRelease)
        {
          // 4 byte
          case R119:
          case R118:
                ctx.hdr.variables = GetLSF<int>(ctxbuf, 4);
                break;

          // 2 byte
          case R117:
               ctx.hdr.variables = GetLSF<int>(ctxbuf, 2);
               break;

          default:

                break;
        }

    } else {
         // MSF not implemented yet
    }

    ctx.advance();

    return true;
}

// OpenN State
State * OpenN::advanceState()
{
  return new OpenLabel();
}

bool OpenN::process(Context & ctx)
{
    char * ctxbuf = (char *) ctx.advance();

    if (ctx.hdr.fileByteorder == LSF)
    {
      switch(ctx.hdr.fileRelease)
      {
        // 8 byte
        case R119:
        case R118:
              ctx.hdr.observations = GetLSF<uint64_t>(ctxbuf, 8);
              break;

        // 4 byte
        case R117:
            ctx.hdr.observations = GetLSF<int>(ctxbuf, 4);
            break;

        default:
             break;
       }
    }
    else
    {
        // MSF not implemented yet
    }

    cout << "Observations: " << ctx.hdr.observations << endl;
    ctx.advance();
    return true;
}

// OpenLabel State
State * OpenLabel::advanceState()
{
  return new OpenTimeStamp();
}

bool OpenLabel::process(Context & ctx)
{
  char * ctxbuf = (char *) ctx.advance();
  int label_count = 0;

  if (ctx.hdr.fileByteorder == LSF)
  {
    switch(ctx.hdr.fileRelease)
    {
      case R119:
      case R118:
          label_count = GetLSF<int>(ctxbuf, 2);
          ctx.hdr.datalabel.assign(&ctxbuf[2],label_count);
          break;

      case R117:
          label_count = GetLSF<int>(ctxbuf, 1);
          ctx.hdr.datalabel.assign(&ctxbuf[1],label_count);
          break;

      default:
           break;
     }
  }
  else
  {
      // not implemented yet
  }

  cout << "Label Count: " << label_count << " " << ctx.hdr.datalabel << endl;
  ctx.advance();

  return true;
}

State * OpenTimeStamp::advanceState()
{
  return new CloseHeader();
}

bool OpenTimeStamp::process(Context & ctx)
{
  char * ctxbuf = (char *) ctx.advance();
  int label_count = 0;

  switch(ctx.hdr.fileRelease)
  {

    case R119:
    case R118:
    case R117:
        label_count = GetLSF<int>(ctxbuf, 1);
        ctx.hdr.ts.assign(&ctxbuf[1],label_count);
        break;
  }

  cout << "timeStamp: " << ctx.hdr.ts << endl;
  ctx.advance();
  return true;
}

State * CloseHeader::advanceState()
{
  return new OpenMap();
}

bool CloseHeader::process(Context & ctx)
{
  ctx.advance();
  return true;
}

State * OpenMap::advanceState()
{
  return new OpenVarTypes();
}

bool OpenMap::process(Context & ctx)
{
    #define MAP_COUNT 14
    char * ctxbuf = (char *)ctx.advance();
    int i, j;

    string map_names[] = {
        "stata_data_start",
        "map",
        "variable_types",
        "varnames",
        "sortlist",
        "formats",
        "value_label_names",
        "variable_labels",
        "characteristics",
        "data",
        "strls",
        "value_labels",
        "stata_data_end",
        "eof"
    };

    for (i = 0; i < MAP_COUNT; i++, ctxbuf += 8)
        ctx.map.stata_map[map_names[i].c_str()] = GetLSF<uint64_t>(ctxbuf, 8);

    ctx.advance();

    return true;

}

State * OpenVarTypes::advanceState()
{
  cout << "done vartypes" << endl;
  return NULL; //new OpenMap();
}

bool OpenVarTypes::process(Context & ctx)
{
  char * ctxbuf = (char *) ctx.advance();
  int curr = 0;

  if (ctx.hdr.fileByteorder == LSF) {

     while (*ctxbuf != '<') {
          StataVariables * sta = new StataVariables();
          sta->type = GetLSF<unsigned int>(ctxbuf, 2);
          cout << "type: " << sta->type << endl;
          ctx.vList.push_back(sta);
          ctxbuf += 2;
          curr++;
      }

  } else {
      // not implemented yet
  }

  ctx.advance();

  return true;
}<|endoftext|>


<commit_before>/*
 * Copyright (c) 2010 ARM Limited
 * All rights reserved
 *
 * The license below extends only to copyright in the software and shall
 * not be construed as granting a license to any other intellectual
 * property including but not limited to intellectual property relating
 * to a hardware implementation of the functionality of the software
 * licensed hereunder.  You may use the software subject to the license
 * terms below provided that you ensure that this notice is replicated
 * unmodified and in its entirety in all distributions of the software,
 * modified or unmodified, in source code or in binary form.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Ali Saidi
 */

#include "base/trace.hh"
#include "dev/arm/rv_ctrl.hh"
#include "mem/packet.hh"
#include "mem/packet_access.hh"

RealViewCtrl::RealViewCtrl(Params *p)
    : BasicPioDevice(p)
{
    pioSize = 0xD4;
}

Tick
RealViewCtrl::read(PacketPtr pkt)
{
    assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
    assert(pkt->getSize() == 4);
    Addr daddr = pkt->getAddr() - pioAddr;
    pkt->allocate();

    switch(daddr) {
      case ProcId:
        pkt->set(params()->proc_id);
        break;
      case Clock24:
        Tick clk;
        clk = (Tick)(curTick() / (24 * SimClock::Float::MHz));
        pkt->set((uint32_t)(clk));
        break;
      case Clock100:
        Tick clk100;
        clk100 = (Tick)(curTick() / (100 * SimClock::Float::MHz));
        pkt->set((uint32_t)(clk100));
        break;
      case Flash:
        pkt->set<uint32_t>(0);
        break;
      case Clcd:
        pkt->set<uint32_t>(0x00001F00);
        break;
      case Osc0:
        pkt->set<uint32_t>(0x00012C5C);
        break;
      case Osc1:
        pkt->set<uint32_t>(0x00002CC0);
        break;
      case Osc2:
        pkt->set<uint32_t>(0x00002C75);
        break;
      case Osc3:
        pkt->set<uint32_t>(0x00020211);
        break;
      case Osc4:
        pkt->set<uint32_t>(0x00002C75);
        break;
      case Lock:
        pkt->set<uint32_t>(sysLock);
        break;
      default:
        panic("Tried to read RealView I/O at offset %#x that doesn't exist\n", daddr);
        break;
    }
    pkt->makeAtomicResponse();
    return pioDelay;

}

Tick
RealViewCtrl::write(PacketPtr pkt)
{
    assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);

    Addr daddr = pkt->getAddr() - pioAddr;
    switch (daddr) {
      case Flash:
      case Clcd:
      case Osc0:
      case Osc1:
      case Osc2:
      case Osc3:
      case Osc4:
        break;
      case Lock:
        sysLock.lockVal = pkt->get<uint16_t>();
        break;
      default:
        panic("Tried to write RVIO at offset %#x that doesn't exist\n", daddr);
        break;
    }
    pkt->makeAtomicResponse();
    return pioDelay;
}

void
RealViewCtrl::serialize(std::ostream &os)
{
}

void
RealViewCtrl::unserialize(Checkpoint *cp, const std::string &section)
{
}

RealViewCtrl *
RealViewCtrlParams::create()
{
    return new RealViewCtrl(this);
}
<commit_msg>RealView: Fix the 24 and 100MHz clocks which were providing incorrect values.<commit_after>/*
 * Copyright (c) 2010 ARM Limited
 * All rights reserved
 *
 * The license below extends only to copyright in the software and shall
 * not be construed as granting a license to any other intellectual
 * property including but not limited to intellectual property relating
 * to a hardware implementation of the functionality of the software
 * licensed hereunder.  You may use the software subject to the license
 * terms below provided that you ensure that this notice is replicated
 * unmodified and in its entirety in all distributions of the software,
 * modified or unmodified, in source code or in binary form.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Ali Saidi
 */

#include "base/trace.hh"
#include "dev/arm/rv_ctrl.hh"
#include "mem/packet.hh"
#include "mem/packet_access.hh"

RealViewCtrl::RealViewCtrl(Params *p)
    : BasicPioDevice(p)
{
    pioSize = 0xD4;
}

Tick
RealViewCtrl::read(PacketPtr pkt)
{
    assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
    assert(pkt->getSize() == 4);
    Addr daddr = pkt->getAddr() - pioAddr;
    pkt->allocate();

    switch(daddr) {
      case ProcId:
        pkt->set(params()->proc_id);
        break;
      case Clock24:
        Tick clk;
        clk = (Tick)(curTick() / (24 * SimClock::Int::us));
        pkt->set((uint32_t)(clk));
        break;
      case Clock100:
        Tick clk100;
        clk100 = (Tick)(curTick() / (100 * SimClock::Int::us));
        pkt->set((uint32_t)(clk100));
        break;
      case Flash:
        pkt->set<uint32_t>(0);
        break;
      case Clcd:
        pkt->set<uint32_t>(0x00001F00);
        break;
      case Osc0:
        pkt->set<uint32_t>(0x00012C5C);
        break;
      case Osc1:
        pkt->set<uint32_t>(0x00002CC0);
        break;
      case Osc2:
        pkt->set<uint32_t>(0x00002C75);
        break;
      case Osc3:
        pkt->set<uint32_t>(0x00020211);
        break;
      case Osc4:
        pkt->set<uint32_t>(0x00002C75);
        break;
      case Lock:
        pkt->set<uint32_t>(sysLock);
        break;
      default:
        panic("Tried to read RealView I/O at offset %#x that doesn't exist\n", daddr);
        break;
    }
    pkt->makeAtomicResponse();
    return pioDelay;

}

Tick
RealViewCtrl::write(PacketPtr pkt)
{
    assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);

    Addr daddr = pkt->getAddr() - pioAddr;
    switch (daddr) {
      case Flash:
      case Clcd:
      case Osc0:
      case Osc1:
      case Osc2:
      case Osc3:
      case Osc4:
        break;
      case Lock:
        sysLock.lockVal = pkt->get<uint16_t>();
        break;
      default:
        panic("Tried to write RVIO at offset %#x that doesn't exist\n", daddr);
        break;
    }
    pkt->makeAtomicResponse();
    return pioDelay;
}

void
RealViewCtrl::serialize(std::ostream &os)
{
}

void
RealViewCtrl::unserialize(Checkpoint *cp, const std::string &section)
{
}

RealViewCtrl *
RealViewCtrlParams::create()
{
    return new RealViewCtrl(this);
}
<|endoftext|>


<commit_before>///
/// @file   tos_counters.hpp
/// @brief  This file contains functions to initialize, update and query
///         the special tree data structure used for summing the
///         number of unsieved elements in the Lagarias-Miller-Odlyzko
///         and Deleglise-Rivat prime summing algorithms.
///
///         The implementation is a modified version of the
///         algorithm described in the paper:
///
///         Tomás Oliveira e Silva, Computing pi(x): the combinatorial method,
///         Revista do DETUA, vol. 4, no. 6, March 2006, pp. 767-768.
///         http://sweet.ua.pt/tos/bib/5.4.pdf
///
/// Copyright (C) 2016 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#ifndef TOS_COUNTERS_HPP
#define TOS_COUNTERS_HPP

#include <stdint.h>
#include <vector>

namespace primesum {

/// Initialize the counters from the sieve array.
/// @pre segment_size is a power of 2.
/// @pre sieve[i] = 1 for unsieved elements and sieve[i] = 0
///      for crossed-off elements.
/// Runtime: O(N log N).
///
template <typename T1, typename T2>
inline void cnt_finit(const T1& sieve,
                      std::vector<T2>& cnt,
                      int64_t low,
                      int64_t segment_size)
{
  for (T2 i = 0; i < segment_size; i++)
  {
    cnt[i] = (low + i) * sieve[i];
    for (T2 k = (i + 1) & ~i, j = i; k >>= 1; j &= j - 1)
      cnt[i] += cnt[j - 1];
  }
}

/// Update the counters after that an element has been
/// crossed-off for the first time in the sieve array.
/// @pre segment_size is a power of 2.
/// Runtime: O(log N).
///
template <typename T>
inline void cnt_update(std::vector<T>& cnt,
                       int64_t n,
                       int64_t low,
                       int64_t segment_size)
{
  int64_t i = n - low;
  do
  {
    cnt[i] -= n;
    i |= i + 1;
  }
  while (i < segment_size);
}

/// Get the sum of the unsieved elements <= pos
/// in the current segment (sieve array).
/// Runtime: O(log N).
///
template <typename T>
inline T cnt_query(const std::vector<T>& cnt, int64_t pos)
{
  T sum = cnt[pos++];
  for (; pos &= pos - 1; sum += cnt[pos - 1]);
  return sum;
}

} // namespace

#endif
<commit_msg>Silence compiler warning<commit_after>///
/// @file   tos_counters.hpp
/// @brief  This file contains functions to initialize, update and query
///         the special tree data structure used for summing the
///         number of unsieved elements in the Lagarias-Miller-Odlyzko
///         and Deleglise-Rivat prime summing algorithms.
///
///         The implementation is a modified version of the
///         algorithm described in the paper:
///
///         Tomás Oliveira e Silva, Computing pi(x): the combinatorial method,
///         Revista do DETUA, vol. 4, no. 6, March 2006, pp. 767-768.
///         http://sweet.ua.pt/tos/bib/5.4.pdf
///
/// Copyright (C) 2016 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#ifndef TOS_COUNTERS_HPP
#define TOS_COUNTERS_HPP

#include <stdint.h>
#include <vector>

namespace primesum {

/// Initialize the counters from the sieve array.
/// @pre segment_size is a power of 2.
/// @pre sieve[i] = 1 for unsieved elements and sieve[i] = 0
///      for crossed-off elements.
/// Runtime: O(N log N).
///
template <typename T1, typename T2>
inline void cnt_finit(const T1& sieve,
                      std::vector<T2>& cnt,
                      int64_t low,
                      int64_t segment_size)
{
  for (int64_t i = 0; i < segment_size; i++)
  {
    cnt[i] = (low + i) * sieve[i];
    for (int64_t k = (i + 1) & ~i, j = i; k >>= 1; j &= j - 1)
      cnt[i] += cnt[j - 1];
  }
}

/// Update the counters after that an element has been
/// crossed-off for the first time in the sieve array.
/// @pre segment_size is a power of 2.
/// Runtime: O(log N).
///
template <typename T>
inline void cnt_update(std::vector<T>& cnt,
                       int64_t n,
                       int64_t low,
                       int64_t segment_size)
{
  int64_t i = n - low;
  do
  {
    cnt[i] -= n;
    i |= i + 1;
  }
  while (i < segment_size);
}

/// Get the sum of the unsieved elements <= pos
/// in the current segment (sieve array).
/// Runtime: O(log N).
///
template <typename T>
inline T cnt_query(const std::vector<T>& cnt, int64_t pos)
{
  T sum = cnt[pos++];
  for (; pos &= pos - 1; sum += cnt[pos - 1]);
  return sum;
}

} // namespace

#endif
<|endoftext|>


<commit_before>#ifndef VSMC_RNG_AES_HPP
#define VSMC_RNG_AES_HPP

#include <vsmc/rng/ars.hpp>

#define VSMC_DEFINE_RNG_AES_ROUND_CONSTANT(N, val) \
    template <> struct AESRoundConstantValue< N > :                          \
        public cxx11::integral_constant<int, val > {};

/// \brief AESEngine default blocks
/// \ingroup Config
#ifndef VSMC_RNG_AES_BLOCKS
#define VSMC_RNG_AES_BLOCKS 1
#endif

namespace vsmc {

namespace internal {

template <std::size_t N> struct AESRoundConstantValue;

VSMC_DEFINE_RNG_AES_ROUND_CONSTANT(0, 0x01)
VSMC_DEFINE_RNG_AES_ROUND_CONSTANT(1, 0x02)
VSMC_DEFINE_RNG_AES_ROUND_CONSTANT(2, 0x04)
VSMC_DEFINE_RNG_AES_ROUND_CONSTANT(3, 0x08)
VSMC_DEFINE_RNG_AES_ROUND_CONSTANT(4, 0x10)
VSMC_DEFINE_RNG_AES_ROUND_CONSTANT(5, 0x20)
VSMC_DEFINE_RNG_AES_ROUND_CONSTANT(6, 0x40)
VSMC_DEFINE_RNG_AES_ROUND_CONSTANT(7, 0x80)
VSMC_DEFINE_RNG_AES_ROUND_CONSTANT(8, 0x1B)
VSMC_DEFINE_RNG_AES_ROUND_CONSTANT(9, 0x36)

} // namespace vsmc::internal

namespace traits {

/// \brief AESEngine round constant traits
/// \ingroup Traits
///
/// The specialization for `N = 0` to `N = 9` are used as the ten round
/// constants in AESEngine
template <std::size_t N>
struct AESRoundConstantTrait :
    public ::vsmc::internal::AESRoundConstantValue<N> {};

} // namespace traits

/// \brief Default AESEngine key sequence generator
/// \ingroup R123RNG
template <std::size_t R>
class AESKeySeq
{
    public :

    typedef StaticVector<__m128i, R + 1> key_seq_type;

    AESKeySeq () : tmp0_(), tmp1_(), tmp2_() {}

    void generate (const __m128i &ukey, key_seq_type &key_seq)
    {
        tmp0_ = ukey;
        generate<0>(key_seq, cxx11::true_type());
    }

    private :

    __m128i tmp0_;
    __m128i tmp1_;
    __m128i tmp2_;

    template <std::size_t>
    void generate (key_seq_type &key_seq, cxx11::false_type)
    {key_seq.back() = tmp0_;}

    template <std::size_t N>
    void generate (key_seq_type &key_seq, cxx11::true_type)
    {
        key_seq[Position<N>()] = tmp0_;
        tmp1_ = _mm_aeskeygenassist_si128(tmp0_,
                traits::AESRoundConstantTrait<N>::value);
        generate_assit();
        generate<N + 1>(key_seq, cxx11::integral_constant<bool, N + 1 < R>());
    }

    void generate_assit ()
    {
        tmp1_ = _mm_shuffle_epi32 (tmp1_ ,0xFF);
        tmp2_ = _mm_slli_si128    (tmp0_, 0x04);
        tmp0_ = _mm_xor_si128     (tmp0_, tmp2_);
        tmp2_ = _mm_slli_si128    (tmp2_, 0x04);
        tmp0_ = _mm_xor_si128     (tmp0_, tmp2_);
        tmp2_ = _mm_slli_si128    (tmp2_, 0x04);
        tmp0_ = _mm_xor_si128     (tmp0_, tmp2_);
        tmp0_ = _mm_xor_si128     (tmp0_, tmp1_);
    }
}; // class AESKeySeq

/// \brief AES RNG engine reimplemented
/// \ingroup R123RNG
///
/// \details
/// This is a reimplementation of the algorithm AES as described in [Parallel
/// Random Numbers: As Easy as 1, 2, 3][r123paper] and implemented in
/// [Random123][r123lib].
///
/// [r123paper]:http://sc11.supercomputing.org/schedule/event_detail.php?evid=pap274
/// [r123lib]: https://www.deshawresearch.com/resources_random123.html
///
/// The algorithm is almost identical to the original. Compared to
/// `r123:Engine<r123::AESNI4x32>`, when using the default constructor or the
/// one with a single seed, the output shall be exactly the same for the first
/// \f$2^32\f$ iterations. Further iterations may produce different results, as
/// vSMC increment the counter slightly differently, but it still cover the
/// same range and has the same period as the original.
///
/// The implementation however is much different the original. See the source
/// for how the ARSEngine is used as the base of AESEngine, and how to
/// implement similar engines.
///
/// The second template argument specify the number of blocks
///
/// \sa AESKeySeq.
/// \sa ARSEngine.
template <typename ResultType, std::size_t Blocks = VSMC_RNG_AES_BLOCKS>
class AESEngine : public ARSEngine<ResultType, Blocks, 10, AESKeySeq<10> >
{
    typedef ARSEngine<ResultType, Blocks, 10, AESKeySeq<10> > base;

    public :

    explicit AESEngine (ResultType s = 0) : base(s) {}

    template <typename SeedSeq>
    explicit AESEngine (SeedSeq &seq, typename cxx11::enable_if<
            !internal::is_seed_seq<SeedSeq, ResultType>::value>::type * =
            VSMC_NULLPTR) : base(seq) {}
}; // class AESEngine

/// \brief AES RNG engine returning 32-bits integers with default blocks
/// \ingroup R123RNG
typedef AESEngine<uint32_t> AES4x32;

/// \brief AES RNG engine returning 64-bits integers with default blocks
/// \ingroup R123RNG
typedef AESEngine<uint64_t> AES2x64;

/// \brief AES RNG engine returning 128-bits integers with default blocks
/// \ingroup R123RNG
typedef AESEngine<__m128i>  AES1x128;

/// \brief AES RNG engine returning 32-bits integers with 1 block
/// \ingroup R123RNG
typedef AESEngine<uint32_t, 1> AES4x32_1;

/// \brief AES RNG engine returning 64-bits integers with 1 block
/// \ingroup R123RNG
typedef AESEngine<uint64_t, 1> AES2x64_1;

/// \brief AES RNG engine returning 128-bits integers with 1 block
/// \ingroup R123RNG
typedef AESEngine<__m128i, 1>  AES1x128_1;

/// \brief AES RNG engine returning 32-bits integers with 2 block
/// \ingroup R123RNG
typedef AESEngine<uint32_t, 2> AES4x32_2;

/// \brief AES RNG engine returning 64-bits integers with 2 block
/// \ingroup R123RNG
typedef AESEngine<uint64_t, 2> AES2x64_2;

/// \brief AES RNG engine returning 128-bits integers with 2 block
/// \ingroup R123RNG
typedef AESEngine<__m128i, 2>  AES1x128_2;

/// \brief AES RNG engine returning 32-bits integers with 4 block
/// \ingroup R123RNG
typedef AESEngine<uint32_t, 4> AES4x32_4;

/// \brief AES RNG engine returning 64-bits integers with 4 block
/// \ingroup R123RNG
typedef AESEngine<uint64_t, 4> AES2x64_4;

/// \brief AES RNG engine returning 128-bits integers with 4 block
/// \ingroup R123RNG
typedef AESEngine<__m128i, 4>  AES1x128_4;

/// \brief AES RNG engine returning 32-bits integers with 8 block
/// \ingroup R123RNG
typedef AESEngine<uint32_t, 8> AES4x32_8;

/// \brief AES RNG engine returning 64-bits integers with 8 block
/// \ingroup R123RNG
typedef AESEngine<uint64_t, 8> AES2x64_8;

/// \brief AES RNG engine returning 128-bits integers with 8 block
/// \ingroup R123RNG
typedef AESEngine<__m128i, 8>  AES1x128_8;

} // namespace vsmc

#endif // VSMC_RNG_AES_HPP
<commit_msg>doc fix<commit_after>#ifndef VSMC_RNG_AES_HPP
#define VSMC_RNG_AES_HPP

#include <vsmc/rng/ars.hpp>

#define VSMC_DEFINE_RNG_AES_ROUND_CONSTANT(N, val) \
    template <> struct AESRoundConstantValue< N > :                          \
        public cxx11::integral_constant<int, val > {};

/// \brief AESEngine default blocks
/// \ingroup Config
#ifndef VSMC_RNG_AES_BLOCKS
#define VSMC_RNG_AES_BLOCKS 1
#endif

namespace vsmc {

namespace internal {

template <std::size_t N> struct AESRoundConstantValue;

VSMC_DEFINE_RNG_AES_ROUND_CONSTANT(0, 0x01)
VSMC_DEFINE_RNG_AES_ROUND_CONSTANT(1, 0x02)
VSMC_DEFINE_RNG_AES_ROUND_CONSTANT(2, 0x04)
VSMC_DEFINE_RNG_AES_ROUND_CONSTANT(3, 0x08)
VSMC_DEFINE_RNG_AES_ROUND_CONSTANT(4, 0x10)
VSMC_DEFINE_RNG_AES_ROUND_CONSTANT(5, 0x20)
VSMC_DEFINE_RNG_AES_ROUND_CONSTANT(6, 0x40)
VSMC_DEFINE_RNG_AES_ROUND_CONSTANT(7, 0x80)
VSMC_DEFINE_RNG_AES_ROUND_CONSTANT(8, 0x1B)
VSMC_DEFINE_RNG_AES_ROUND_CONSTANT(9, 0x36)

} // namespace vsmc::internal

namespace traits {

/// \brief AESEngine round constant traits
/// \ingroup Traits
///
/// The specialization for `N = 0` to `N = 9` are used as the ten round
/// constants in AESEngine
template <std::size_t N>
struct AESRoundConstantTrait :
    public ::vsmc::internal::AESRoundConstantValue<N> {};

} // namespace traits

/// \brief AESEngine key sequence generator
/// \ingroup R123RNG
template <std::size_t R>
class AESKeySeq
{
    public :

    typedef StaticVector<__m128i, R + 1> key_seq_type;

    AESKeySeq () : tmp0_(), tmp1_(), tmp2_() {}

    void generate (const __m128i &ukey, key_seq_type &key_seq)
    {
        tmp0_ = ukey;
        generate<0>(key_seq, cxx11::true_type());
    }

    private :

    __m128i tmp0_;
    __m128i tmp1_;
    __m128i tmp2_;

    template <std::size_t>
    void generate (key_seq_type &key_seq, cxx11::false_type)
    {key_seq.back() = tmp0_;}

    template <std::size_t N>
    void generate (key_seq_type &key_seq, cxx11::true_type)
    {
        key_seq[Position<N>()] = tmp0_;
        tmp1_ = _mm_aeskeygenassist_si128(tmp0_,
                traits::AESRoundConstantTrait<N>::value);
        generate_assit();
        generate<N + 1>(key_seq, cxx11::integral_constant<bool, N + 1 < R>());
    }

    void generate_assit ()
    {
        tmp1_ = _mm_shuffle_epi32 (tmp1_ ,0xFF);
        tmp2_ = _mm_slli_si128    (tmp0_, 0x04);
        tmp0_ = _mm_xor_si128     (tmp0_, tmp2_);
        tmp2_ = _mm_slli_si128    (tmp2_, 0x04);
        tmp0_ = _mm_xor_si128     (tmp0_, tmp2_);
        tmp2_ = _mm_slli_si128    (tmp2_, 0x04);
        tmp0_ = _mm_xor_si128     (tmp0_, tmp2_);
        tmp0_ = _mm_xor_si128     (tmp0_, tmp1_);
    }
}; // class AESKeySeq

/// \brief AES RNG engine reimplemented
/// \ingroup R123RNG
///
/// \details
/// This is a reimplementation of the algorithm AES as described in [Parallel
/// Random Numbers: As Easy as 1, 2, 3][r123paper] and implemented in
/// [Random123][r123lib].
///
/// [r123paper]:http://sc11.supercomputing.org/schedule/event_detail.php?evid=pap274
/// [r123lib]: https://www.deshawresearch.com/resources_random123.html
///
/// The algorithm is almost identical to the original. Compared to
/// `r123:Engine<r123::AESNI4x32>`, when using the default constructor or the
/// one with a single seed, the output shall be exactly the same for the first
/// \f$2^32\f$ iterations. Further iterations may produce different results, as
/// vSMC increment the counter slightly differently, but it still cover the
/// same range and has the same period as the original.
///
/// The implementation however is much different the original. See the source
/// for how the ARSEngine is used as the base of AESEngine, and how to
/// implement similar engines.
///
/// The second template argument specify the number of blocks
///
/// \sa AESKeySeq.
/// \sa ARSEngine.
template <typename ResultType, std::size_t Blocks = VSMC_RNG_AES_BLOCKS>
class AESEngine : public ARSEngine<ResultType, Blocks, 10, AESKeySeq<10> >
{
    typedef ARSEngine<ResultType, Blocks, 10, AESKeySeq<10> > base;

    public :

    explicit AESEngine (ResultType s = 0) : base(s) {}

    template <typename SeedSeq>
    explicit AESEngine (SeedSeq &seq, typename cxx11::enable_if<
            !internal::is_seed_seq<SeedSeq, ResultType>::value>::type * =
            VSMC_NULLPTR) : base(seq) {}
}; // class AESEngine

/// \brief AES RNG engine returning 32-bits integers with default blocks
/// \ingroup R123RNG
typedef AESEngine<uint32_t> AES4x32;

/// \brief AES RNG engine returning 64-bits integers with default blocks
/// \ingroup R123RNG
typedef AESEngine<uint64_t> AES2x64;

/// \brief AES RNG engine returning 128-bits integers with default blocks
/// \ingroup R123RNG
typedef AESEngine<__m128i>  AES1x128;

/// \brief AES RNG engine returning 32-bits integers with 1 block
/// \ingroup R123RNG
typedef AESEngine<uint32_t, 1> AES4x32_1;

/// \brief AES RNG engine returning 64-bits integers with 1 block
/// \ingroup R123RNG
typedef AESEngine<uint64_t, 1> AES2x64_1;

/// \brief AES RNG engine returning 128-bits integers with 1 block
/// \ingroup R123RNG
typedef AESEngine<__m128i, 1>  AES1x128_1;

/// \brief AES RNG engine returning 32-bits integers with 2 block
/// \ingroup R123RNG
typedef AESEngine<uint32_t, 2> AES4x32_2;

/// \brief AES RNG engine returning 64-bits integers with 2 block
/// \ingroup R123RNG
typedef AESEngine<uint64_t, 2> AES2x64_2;

/// \brief AES RNG engine returning 128-bits integers with 2 block
/// \ingroup R123RNG
typedef AESEngine<__m128i, 2>  AES1x128_2;

/// \brief AES RNG engine returning 32-bits integers with 4 block
/// \ingroup R123RNG
typedef AESEngine<uint32_t, 4> AES4x32_4;

/// \brief AES RNG engine returning 64-bits integers with 4 block
/// \ingroup R123RNG
typedef AESEngine<uint64_t, 4> AES2x64_4;

/// \brief AES RNG engine returning 128-bits integers with 4 block
/// \ingroup R123RNG
typedef AESEngine<__m128i, 4>  AES1x128_4;

/// \brief AES RNG engine returning 32-bits integers with 8 block
/// \ingroup R123RNG
typedef AESEngine<uint32_t, 8> AES4x32_8;

/// \brief AES RNG engine returning 64-bits integers with 8 block
/// \ingroup R123RNG
typedef AESEngine<uint64_t, 8> AES2x64_8;

/// \brief AES RNG engine returning 128-bits integers with 8 block
/// \ingroup R123RNG
typedef AESEngine<__m128i, 8>  AES1x128_8;

} // namespace vsmc

#endif // VSMC_RNG_AES_HPP
<|endoftext|>


<commit_before>#ifndef VG_FEATURES_HPP_INCLUDED
#define VG_FEATURES_HPP_INCLUDED

/// \file
/// features.hpp: utilities for working with Feature and FeatureType from the VG Protobuf

#include <vg.pb.h>

#include "json2pb.h"

#include <vector>
#include <string>
#include <type_traits>

namespace vg {

using namespace std;

// We template over Alignment and MultipathAlignment because they have the same
// features methods but no base class.

// We use a Protobuf-style pointer-for-mutable interface. All the mutator
// methods take pointers, while the read methods take const references.

////////////////////////////////////////////////////////////////////////
// API
////////////////////////////////////////////////////////////////////////

/// Determine if the given alignment has ther given tag feature, or any
/// instances of the given numerical or list feature.
template<typename Item, typename Enabled = typename enable_if<!is_pointer<Item>::value>::type>
bool has_feature(const Item& item, const FeatureType& feature);

template<typename Item>
bool has_feature(const Item* item, const FeatureType& feature);

/// Get the numerical value of the given single-value feature on the given
/// item. Throws an error if the feature isn't present. Should not be called on
/// multi-valued features.
template<typename Item, typename Enabled = typename enable_if<!is_pointer<Item>::value>::type>
double get_feature(const Item& item, const FeatureType& feature);

template<typename Item>
double get_feature(const Item* item, const FeatureType& feature);

/// Get the numerical values of the given multi-valued feature, or an empty
/// vector if the feature isn't present.
template<typename Item, typename Enabled = typename enable_if<!is_pointer<Item>::value>::type>
vector<double> get_features(const Item& item, const FeatureType& feature);

template<typename Item>
vector<double> get_features(const Item* item, const FeatureType& feature);

/// Add the given tag feature to the given item, assuming it is not present already.
template<typename Item>
void add_feature(Item* item, const FeatureType& feature);

/// Add the given tag feature if the given flkag is set, assuming it is not present already.
template<typename Item>
void add_feature(Item* item, const FeatureType& feature, const bool& flag);

/// Append the given value to the given multi-valued feature, or add the given
/// value for the given single-valued feature it it is not yet set.
template<typename Item>
void add_feature(Item* item, const FeatureType& feature, const double& value);

/// Append the given value to the given multi-valued feature, or add the given
/// value for the given single-valued feature it it is not yet set.
/// Coerces integral values to double.
template<typename Item, typename Integral,
    typename Enabled = typename enable_if<is_integral<Integral>::value && !is_same<Integral, bool>::value>::type>
void add_feature(Item* item, const FeatureType& feature, const Integral& value);

/// Set the given tag feature to the given value, even if it is already present.
template<typename Item>
void set_feature(Item* item, const FeatureType& feature, const bool& flag);

/// Set the given single-valued feature to the given value, adding it if it doesn't exist yet.
template<typename Item>
void set_feature(Item* item, const FeatureType& feature, const double& value);

/// Set the given single-valued feature to the given value, adding it if it doesn't exist yet.
/// Coerces integral values to double.
template<typename Item, typename Integral,
    typename Enabled = typename enable_if<is_integral<Integral>::value && !is_same<Integral, bool>::value>::type>
void set_feature(Item* item, const FeatureType& feature, const Integral& value);

/// Remove the given tag frature, or all instances of the given single- or
/// multi-valued feature, form the given item, if any are present.
template<typename Item>
void remove_feature(Item* item, const FeatureType& feature);

////////////////////////////////////////////////////////////////////////
// Implementation
////////////////////////////////////////////////////////////////////////

template<typename Item, typename Enabled>
bool has_feature(const Item& item, const FeatureType& feature) {
    for (auto& record : item.feature()) {
        // Do a linear scan
        if (record.type() == feature) {
            // And if we find it, return it
            return true;
        }
    }
    // Otherwise we didn't find it
    return false;
}

template<typename Item>
bool has_feature(const Item* item, const FeatureType& feature) {
    return has_feature(*item, feature);
}

template<typename Item, typename Enabled>
double get_feature(const Item& item, const FeatureType& feature) {
    for (auto& record : item.feature()) {
        // Do a linear scan
        if (record.type() == feature) {
            // And if we find it, return it
            return record.value();
        }
    }
    // Otherwise we didn't find it
    throw runtime_error("Feature " + to_string(feature) + " not found in " + pb2json(item));
}

template<typename Item>
double get_feature(const Item* item, const FeatureType& feature) {
    return get_feature(*item, feature);
}

template<typename Item, typename Enabled>
vector<double> get_features(const Item& item, const FeatureType& feature) {
    vector<double> to_return;
    for (auto& record : item.feature()) {
        // Do a linear scan
        if (record.type() == feature) {
            // And if we find it, gather it up
            to_return.push_back(record.value());
        }
    }
    return to_return;
}

template<typename Item>
vector<double> get_features(const Item* item, const FeatureType& feature) {
    return get_features(*item, feature);
}

template<typename Item>
void add_feature(Item* item, const FeatureType& feature) {
    Feature* added = item->add_feature();
    added->set_type(feature);
}

template<typename Item>
void add_feature(Item* item, const FeatureType& feature, const bool& flag) {
    if (flag) {
        // If the flag is true, actually add it.
        add_feature(item, feature);
    }
}

template<typename Item>
void add_feature(Item* item, const FeatureType& feature, const double& value) {
    // Always add it
    Feature* added = item->add_feature();
    added->set_type(feature);
    // And set the value
    added->set_value(value);
}

template<typename Item, typename Integral, typename Enabled>
void add_feature(Item* item, const FeatureType& feature, const Integral& value) {
    add_feature(item, feature, (double)value);
}

template<typename Item>
void set_feature(Item* item, const FeatureType& feature, const bool& flag) {
    remove_feature(item, feature);
    add_feature(item, feature, flag);
}

template<typename Item>
void set_feature(Item* item, const FeatureType& feature, const double& value) {
    remove_feature(item, feature);
    add_feature(item, feature, value);
}

template<typename Item, typename Integral, typename Enabled>
void set_feature(Item* item, const FeatureType& feature, const Integral& value) {
    set_feature(item, feature, (double)value);
}

template<typename Item>
void remove_feature(Item* item, const FeatureType& feature) {
    for (size_t i = 0; i < item->feature_size();) {
        if (item->feature(i).type() == feature) {
            // We need to remove it
            // So swap it last
            item->mutable_feature()->SwapElements(i, item->feature_size());
            // And remove the last element
            item->mutable_feature()->RemoveLast();

            // Stay here so we can look at what we swapped into this position
        } else {
            // Don't need to remove anything, so look at the next item
            i++;
        }
    }
}

}

#endif
<commit_msg>Fix off-by-1 error in feature removal<commit_after>#ifndef VG_FEATURES_HPP_INCLUDED
#define VG_FEATURES_HPP_INCLUDED

/// \file
/// features.hpp: utilities for working with Feature and FeatureType from the VG Protobuf

#include <vg.pb.h>

#include "json2pb.h"

#include <vector>
#include <string>
#include <type_traits>

namespace vg {

using namespace std;

// We template over Alignment and MultipathAlignment because they have the same
// features methods but no base class.

// We use a Protobuf-style pointer-for-mutable interface. All the mutator
// methods take pointers, while the read methods take const references.

////////////////////////////////////////////////////////////////////////
// API
////////////////////////////////////////////////////////////////////////

/// Determine if the given alignment has ther given tag feature, or any
/// instances of the given numerical or list feature.
template<typename Item, typename Enabled = typename enable_if<!is_pointer<Item>::value>::type>
bool has_feature(const Item& item, const FeatureType& feature);

template<typename Item>
bool has_feature(const Item* item, const FeatureType& feature);

/// Get the numerical value of the given single-value feature on the given
/// item. Throws an error if the feature isn't present. Should not be called on
/// multi-valued features.
template<typename Item, typename Enabled = typename enable_if<!is_pointer<Item>::value>::type>
double get_feature(const Item& item, const FeatureType& feature);

template<typename Item>
double get_feature(const Item* item, const FeatureType& feature);

/// Get the numerical values of the given multi-valued feature, or an empty
/// vector if the feature isn't present.
template<typename Item, typename Enabled = typename enable_if<!is_pointer<Item>::value>::type>
vector<double> get_features(const Item& item, const FeatureType& feature);

template<typename Item>
vector<double> get_features(const Item* item, const FeatureType& feature);

/// Add the given tag feature to the given item, assuming it is not present already.
template<typename Item>
void add_feature(Item* item, const FeatureType& feature);

/// Add the given tag feature if the given flkag is set, assuming it is not present already.
template<typename Item>
void add_feature(Item* item, const FeatureType& feature, const bool& flag);

/// Append the given value to the given multi-valued feature, or add the given
/// value for the given single-valued feature it it is not yet set.
template<typename Item>
void add_feature(Item* item, const FeatureType& feature, const double& value);

/// Append the given value to the given multi-valued feature, or add the given
/// value for the given single-valued feature it it is not yet set.
/// Coerces integral values to double.
template<typename Item, typename Integral,
    typename Enabled = typename enable_if<is_integral<Integral>::value && !is_same<Integral, bool>::value>::type>
void add_feature(Item* item, const FeatureType& feature, const Integral& value);

/// Set the given tag feature to the given value, even if it is already present.
template<typename Item>
void set_feature(Item* item, const FeatureType& feature, const bool& flag);

/// Set the given single-valued feature to the given value, adding it if it doesn't exist yet.
template<typename Item>
void set_feature(Item* item, const FeatureType& feature, const double& value);

/// Set the given single-valued feature to the given value, adding it if it doesn't exist yet.
/// Coerces integral values to double.
template<typename Item, typename Integral,
    typename Enabled = typename enable_if<is_integral<Integral>::value && !is_same<Integral, bool>::value>::type>
void set_feature(Item* item, const FeatureType& feature, const Integral& value);

/// Remove the given tag frature, or all instances of the given single- or
/// multi-valued feature, form the given item, if any are present.
template<typename Item>
void remove_feature(Item* item, const FeatureType& feature);

////////////////////////////////////////////////////////////////////////
// Implementation
////////////////////////////////////////////////////////////////////////

template<typename Item, typename Enabled>
bool has_feature(const Item& item, const FeatureType& feature) {
    for (auto& record : item.feature()) {
        // Do a linear scan
        if (record.type() == feature) {
            // And if we find it, return it
            return true;
        }
    }
    // Otherwise we didn't find it
    return false;
}

template<typename Item>
bool has_feature(const Item* item, const FeatureType& feature) {
    return has_feature(*item, feature);
}

template<typename Item, typename Enabled>
double get_feature(const Item& item, const FeatureType& feature) {
    for (auto& record : item.feature()) {
        // Do a linear scan
        if (record.type() == feature) {
            // And if we find it, return it
            return record.value();
        }
    }
    // Otherwise we didn't find it
    throw runtime_error("Feature " + to_string(feature) + " not found in " + pb2json(item));
}

template<typename Item>
double get_feature(const Item* item, const FeatureType& feature) {
    return get_feature(*item, feature);
}

template<typename Item, typename Enabled>
vector<double> get_features(const Item& item, const FeatureType& feature) {
    vector<double> to_return;
    for (auto& record : item.feature()) {
        // Do a linear scan
        if (record.type() == feature) {
            // And if we find it, gather it up
            to_return.push_back(record.value());
        }
    }
    return to_return;
}

template<typename Item>
vector<double> get_features(const Item* item, const FeatureType& feature) {
    return get_features(*item, feature);
}

template<typename Item>
void add_feature(Item* item, const FeatureType& feature) {
    Feature* added = item->add_feature();
    added->set_type(feature);
}

template<typename Item>
void add_feature(Item* item, const FeatureType& feature, const bool& flag) {
    if (flag) {
        // If the flag is true, actually add it.
        add_feature(item, feature);
    }
}

template<typename Item>
void add_feature(Item* item, const FeatureType& feature, const double& value) {
    // Always add it
    Feature* added = item->add_feature();
    added->set_type(feature);
    // And set the value
    added->set_value(value);
}

template<typename Item, typename Integral, typename Enabled>
void add_feature(Item* item, const FeatureType& feature, const Integral& value) {
    add_feature(item, feature, (double)value);
}

template<typename Item>
void set_feature(Item* item, const FeatureType& feature, const bool& flag) {
    remove_feature(item, feature);
    add_feature(item, feature, flag);
}

template<typename Item>
void set_feature(Item* item, const FeatureType& feature, const double& value) {
    remove_feature(item, feature);
    add_feature(item, feature, value);
}

template<typename Item, typename Integral, typename Enabled>
void set_feature(Item* item, const FeatureType& feature, const Integral& value) {
    set_feature(item, feature, (double)value);
}

template<typename Item>
void remove_feature(Item* item, const FeatureType& feature) {
    for (size_t i = 0; i < item->feature_size();) {
        if (item->feature(i).type() == feature) {
            // We need to remove it
            // So swap it last
            item->mutable_feature()->SwapElements(i, item->feature_size() - 1);
            // And remove the last element
            item->mutable_feature()->RemoveLast();

            // Stay here so we can look at what we swapped into this position
        } else {
            // Don't need to remove anything, so look at the next item
            i++;
        }
    }
}

}

#endif
<|endoftext|>