<commit_before>/***********************************************************************************************************************
 * VExtendable.cpp
 *
 *  Created on: Dec 14, 2010
 *      Author: Dimitar Asenov
 **********************************************************************************************************************/

#include "items/VExtendable.h"

#include "items/Text.h"

#include <QtCore/QString>
#include <QtCore/QPair>
#include <QtCore/QList>

namespace Visualization {

ITEM_COMMON_DEFINITIONS(VExtendable)

VExtendable::VExtendable(Item* parent, Model::ExtendableNode* node, const VExtendableStyle* style) :
	ModelItem(parent, node, style), header( new SequentialLayout(this, &style->smallHeaderStyle())), layout(NULL), attributes(NULL), expanded_(style->expanded())
{
	header->append(new Text(header, node->typeName()));
	if (!expanded_) removeShape();
}

VExtendable::~VExtendable()
{
	if ( expanded_ )
	{
		SAFE_DELETE_ITEM(layout);

		// These were automatically deleted by layout's destructor
		header = NULL ;
		attributes = NULL;
	}
	else SAFE_DELETE_ITEM(header);
}

void VExtendable::determineChildren()
{
	Model::ExtendableNode* node = static_cast<Model::ExtendableNode*> (getNode());

	// Set the name if any
	if ( node->hasAttribute("name") )
	{
		Model::Node* name = node->get("name");
		if ( header->length() == 1 ) header->prepend(renderer()->render(header, name));
		if ( header->length() == 2 && header->at<ModelItem> (0)->getNode() != name )
		{
			header->remove(0);
			header->prepend(renderer()->render(header, name));
		}
	}
	else
	{
		if ( header->length() > 1 ) header->remove(0);
	}

	// Clean up when switching styles
	if ( expandedSwtiched() )
	{
		if ( expanded_ )
		{
			useShape();
			layout = new PanelBorderLayout(this, &style()->borderStyle());
			attributes = new SequentialLayout(NULL, &style()->attributesStyle());

			layout->setTop(true);
			layout->top()->setMiddle(header);
			layout->setContent(attributes);
		}
		else
		{
			removeShape();
			// This is the header. We do not want this to be removed by layout's destructor
			layout->top()->setMiddle(NULL, false);
			header->setParentItem(this);

			SAFE_DELETE_ITEM(layout);

			attributes = NULL; // This was automatically deleted by layout's destructor
		}
	}

	// TODO: find a better way and place to determine the style of children. Is doing this causing too many updates?
	// TODO: consider the performance of this. Possibly introduce a style updated boolean for all items so that they know
	//			what's the reason they are being updated.
	// The style needs to be updated every time since if our own style changes, so will that of the children.
	if (expanded_)
	{
		header->setStyle(&style()->headerStyle());
		layout->setStyle(&style()->borderStyle());
		attributes->setStyle(&style()->attributesStyle());
	}
	else header->setStyle(&style()->smallHeaderStyle());

	if ( expanded_ )
	{
		// Set the attributes
		// NOTE: This procedure assumes that the order of the named attributes will never change. Attributes might be
		// deleted or added but their ordering should be kept constant.
		// TODO: document this somewhere more visible.
		QList<QPair<QString, Model::Node*> > attr = node->getAllAttributes();

		// Remove elements from attributes which are outdated
		for(int i = attributes->length() - 1; i>=0; --i)
		{
			bool found = false;
			for (int k = 0; k<attr.size(); ++k)
			{
				if (attr[k].second == attributes->at<ModelItem>(i)->getNode())
				{
					found = true;
					break;
				}
			}

			if (!found) attributes->remove(i);
		}

		int attributeIndex = 0;
		for (int i = 0; i < attr.size(); ++i)
		{
			if ( attr[i].first == "name" ) continue;

			if (attributes->length() <= i || attributes->at<ModelItem>(attributeIndex)->getNode() != attr[i].second)
			{
				SequentialLayout* s = new SequentialLayout(attributes);
				s->append(new Text(s, attr[i].first));
				s->append(renderer()->render(s, attr[i].second));
				attributes->insert(s, attributeIndex);
			}

			++attributeIndex;
		}
	}

}

void VExtendable::updateGeometry(int, int)
{
	if ( expanded_ )
	{
		if ( hasShape() )
		{
			getShape()->setOffset(layout->getXOffsetForExternalShape(), layout->getYOffsetForExternalShape());
			getShape()->setOutterSize(layout->getOutterWidthForExternalShape(), layout->getOutterHeightForExternalShape());
		}
		setSize( layout->size() );
	}
	else
	{
		if ( hasShape() )
		{
			getShape()->setOffset(0, 0);
			getShape()->setInnerSize(header->width(), header->height());
			header->setPos(getShape()->contentLeft(), getShape()->contentTop());
		}
		else
		{
			setSize(header->size());
			header->setPos(0,0);
		}
	}
}

void VExtendable::setExpanded(bool expanded)
{
	if ( expanded != expanded_ )
	{
		expanded_ = expanded;
		setUpdateNeeded();
	}
}

inline bool VExtendable::expandedSwtiched() const
{
	return (layout && attributes) != expanded_;
}

}
<commit_msg>Fixed a visualization bug.<commit_after>/***********************************************************************************************************************
 * VExtendable.cpp
 *
 *  Created on: Dec 14, 2010
 *      Author: Dimitar Asenov
 **********************************************************************************************************************/

#include "items/VExtendable.h"

#include "items/Text.h"

#include <QtCore/QString>
#include <QtCore/QPair>
#include <QtCore/QList>

#include <QtCore/QDebug>

namespace Visualization {

ITEM_COMMON_DEFINITIONS(VExtendable)

VExtendable::VExtendable(Item* parent, Model::ExtendableNode* node, const VExtendableStyle* style) :
	ModelItem(parent, node, style), header( new SequentialLayout(this, &style->smallHeaderStyle())), layout(NULL), attributes(NULL), expanded_(style->expanded())
{
	header->append(new Text(header, node->typeName()));
	if (!expanded_) removeShape();
}

VExtendable::~VExtendable()
{
	if ( expanded_ )
	{
		SAFE_DELETE_ITEM(layout);

		// These were automatically deleted by layout's destructor
		header = NULL ;
		attributes = NULL;
	}
	else SAFE_DELETE_ITEM(header);
}

void VExtendable::determineChildren()
{
	Model::ExtendableNode* node = static_cast<Model::ExtendableNode*> (getNode());

	// Set the name if any
	if ( node->hasAttribute("name") )
	{
		Model::Node* name = node->get("name");
		if ( header->length() == 1 ) header->prepend(renderer()->render(header, name));
		if ( header->length() == 2 && header->at<ModelItem> (0)->getNode() != name )
		{
			header->remove(0);
			header->prepend(renderer()->render(header, name));
		}
	}
	else
	{
		if ( header->length() > 1 ) header->remove(0);
	}

	// Clean up when switching styles
	if ( expandedSwtiched() )
	{
		if ( expanded_ )
		{
			useShape();
			layout = new PanelBorderLayout(this, &style()->borderStyle());
			attributes = new SequentialLayout(NULL, &style()->attributesStyle());

			layout->setTop(true);
			layout->top()->setMiddle(header);
			layout->setContent(attributes);
		}
		else
		{
			removeShape();
			// This is the header. We do not want this to be removed by layout's destructor
			layout->top()->setMiddle(NULL, false);
			header->setParentItem(this);

			SAFE_DELETE_ITEM(layout);

			attributes = NULL; // This was automatically deleted by layout's destructor
		}
	}

	// TODO: find a better way and place to determine the style of children. Is doing this causing too many updates?
	// TODO: consider the performance of this. Possibly introduce a style updated boolean for all items so that they know
	//			what's the reason they are being updated.
	// The style needs to be updated every time since if our own style changes, so will that of the children.
	if (expanded_)
	{
		header->setStyle(&style()->headerStyle());
		layout->setStyle(&style()->borderStyle());
		attributes->setStyle(&style()->attributesStyle());
	}
	else header->setStyle(&style()->smallHeaderStyle());

	if ( expanded_ )
	{
		// Set the attributes
		// NOTE: This procedure assumes that the order of the named attributes will never change. Attributes might be
		// deleted or added but their ordering should be kept constant.
		// TODO: document this somewhere more visible.
		QList<QPair<QString, Model::Node*> > attr = node->getAllAttributes();

		// Remove elements from attributes which are outdated
		for(int i = attributes->length() - 1; i>=0; --i)
		{
			bool found = false;
			for (int k = 0; k<attr.size(); ++k)
			{
				if (attr[k].second == attributes->at<SequentialLayout>(i)->at<ModelItem>(1)->getNode())
				{
					found = true;
					break;
				}
			}

			if (!found) { attributes->remove(i); qDebug() << "remove" << i;}
		}

		int attributeIndex = 0;
		for (int i = 0; i < attr.size(); ++i)
		{
			if ( attr[i].first == "name" ) continue;

			if (attributes->length() <= attributeIndex || attributes->at<SequentialLayout>(attributeIndex)->at<ModelItem>(1)->getNode() != attr[i].second)
			{
				SequentialLayout* s = new SequentialLayout(attributes);
				s->append(new Text(s, attr[i].first));
				s->append(renderer()->render(s, attr[i].second));
				attributes->insert(s, attributeIndex);
			}

			++attributeIndex;
		}
	}

}

void VExtendable::updateGeometry(int, int)
{
	if ( expanded_ )
	{
		if ( hasShape() )
		{
			getShape()->setOffset(layout->getXOffsetForExternalShape(), layout->getYOffsetForExternalShape());
			getShape()->setOutterSize(layout->getOutterWidthForExternalShape(), layout->getOutterHeightForExternalShape());
		}
		setSize( layout->size() );
	}
	else
	{
		if ( hasShape() )
		{
			getShape()->setOffset(0, 0);
			getShape()->setInnerSize(header->width(), header->height());
			header->setPos(getShape()->contentLeft(), getShape()->contentTop());
		}
		else
		{
			setSize(header->size());
			header->setPos(0,0);
		}
	}
}

void VExtendable::setExpanded(bool expanded)
{
	if ( expanded != expanded_ )
	{
		expanded_ = expanded;
		setUpdateNeeded();
	}
}

inline bool VExtendable::expandedSwtiched() const
{
	return (layout && attributes) != expanded_;
}

}
<|endoftext|>


<commit_before>// ========================================================================== //
// This file is part of DO++, a basic set of libraries in C++ for computer
// vision.
//
// Copyright (C) 2013 David Ok <david.ok8@gmail.com>
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License v. 2.0. If a copy of the MPL was not distributed with this file,
// you can obtain one at http://mozilla.org/MPL/2.0/.
// ========================================================================== //

#ifndef DO_GEOMETRY_BBOX_HPP
#define DO_GEOMETRY_BBOX_HPP

#include <DO/Core/EigenExtension.hpp>
#include <vector>

namespace DO {

  class BBox
  {
    Point2d tl_, br_;
  public:
    BBox() {}
    BBox(const Point2d& topLeft, const Point2d& bottomRight)
      : tl_(topLeft), br_(bottomRight)
    {
      if ( tl_.x() > br_.x() ||
           tl_.y() > br_.y() )
      {
        const char *msg = "Top-left and bottom-right corners are wrong!";
        throw std::logic_error(msg);
      }
    }
    BBox(const Point2d *begin, const Point2d *end)
    {
      if (!begin)
      {
        const char *msg = "The array of points seems wrong.";
        throw std::logic_error(msg);
      }
      tl_ = br_ = *begin;
      for (const Point2d *p = begin; p != end; ++p)
      {
        tl_.x() = std::min(tl_.x(), p->x());
        tl_.y() = std::min(tl_.y(), p->y());
        br_.x() = std::max(br_.x(), p->x());
        br_.y() = std::max(br_.y(), p->y());
      }
    }
    BBox(const std::vector<Point2d>& points);

    Point2d& topLeft()     { return tl_; }
    Point2d& bottomRight() { return br_; }
    double& x1() { return  tl_.x(); }
    double& y1() { return  tl_.y(); }
    double& x2() { return  br_.x(); }
    double& y2() { return  br_.y(); }

    const Point2d& topLeft()     const { return tl_; }
    const Point2d& bottomRight() const { return br_; }
    Point2d        topRight()    const { return tl_+Point2d(width(), 0); }
    Point2d        bottomLeft()  const { return br_-Point2d(width(), 0); }

    double x1() const { return  tl_.x(); }
    double y1() const { return  tl_.y(); }
    double x2() const { return  br_.x(); }
    double y2() const { return  br_.y(); }

    double width() const  { return std::abs(br_.x() - tl_.x()); }
    double height() const { return std::abs(br_.y() - tl_.y()); }

    static BBox infinite()
    {
      BBox b;
      b.topLeft().fill(-std::numeric_limits<double>::infinity());
      b.bottomRight().fill(std::numeric_limits<double>::infinity());
      return b;
    }
    static BBox zero()
    {
      BBox b(Point2d::Zero(), Point2d::Zero());
      return b;
    }
  };

  // Utility functions.
  double area(const BBox& bbox);
  bool inside(const Point2d& p, const BBox& bbox);
  bool degenerate(const BBox& bbox, double eps = 1e-3);
  bool intersect(const BBox& bbox1, const BBox& bbox2);
  double jaccardSimilarity(const BBox& bbox1, const BBox& bbox2);
  double jaccardDistance(const BBox& bbox1, const BBox& bbox2);

  // I/O.
  std::ostream& operator<<(std::ostream& os, const BBox& bbox);

  // Intersection test.
  BBox intersection(const BBox& bbox1, const BBox& bbox2);

} /* namespace DO */

#endif /* DO_GEOMETRY_BBOX_HPP */
<commit_msg>[Geometry] Added sizes() method to BBox class<commit_after>// ========================================================================== //
// This file is part of DO++, a basic set of libraries in C++ for computer
// vision.
//
// Copyright (C) 2013 David Ok <david.ok8@gmail.com>
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License v. 2.0. If a copy of the MPL was not distributed with this file,
// you can obtain one at http://mozilla.org/MPL/2.0/.
// ========================================================================== //

#ifndef DO_GEOMETRY_BBOX_HPP
#define DO_GEOMETRY_BBOX_HPP

#include <DO/Core/EigenExtension.hpp>
#include <vector>

namespace DO {

  class BBox
  {
    Point2d tl_, br_;
  public:
    BBox() {}
    BBox(const Point2d& topLeft, const Point2d& bottomRight)
      : tl_(topLeft), br_(bottomRight)
    {
      if ( tl_.x() > br_.x() ||
           tl_.y() > br_.y() )
      {
        const char *msg = "Top-left and bottom-right corners are wrong!";
        throw std::logic_error(msg);
      }
    }
    BBox(const Point2d *begin, const Point2d *end)
    {
      if (!begin)
      {
        const char *msg = "The array of points seems wrong.";
        throw std::logic_error(msg);
      }
      tl_ = br_ = *begin;
      for (const Point2d *p = begin; p != end; ++p)
      {
        tl_.x() = std::min(tl_.x(), p->x());
        tl_.y() = std::min(tl_.y(), p->y());
        br_.x() = std::max(br_.x(), p->x());
        br_.y() = std::max(br_.y(), p->y());
      }
    }
    BBox(const std::vector<Point2d>& points);

    Point2d& topLeft()     { return tl_; }
    Point2d& bottomRight() { return br_; }
    double& x1() { return  tl_.x(); }
    double& y1() { return  tl_.y(); }
    double& x2() { return  br_.x(); }
    double& y2() { return  br_.y(); }

    const Point2d& topLeft()     const { return tl_; }
    const Point2d& bottomRight() const { return br_; }
    Point2d        topRight()    const { return tl_+Point2d(width(), 0); }
    Point2d        bottomLeft()  const { return br_-Point2d(width(), 0); }

    double x1() const { return  tl_.x(); }
    double y1() const { return  tl_.y(); }
    double x2() const { return  br_.x(); }
    double y2() const { return  br_.y(); }

    double width() const  { return std::abs(br_.x() - tl_.x()); }
    double height() const { return std::abs(br_.y() - tl_.y()); }
    Vector2d sizes() const { return br_ - tl_; }

    static BBox infinite()
    {
      BBox b;
      b.topLeft().fill(-std::numeric_limits<double>::infinity());
      b.bottomRight().fill(std::numeric_limits<double>::infinity());
      return b;
    }
    static BBox zero()
    {
      BBox b(Point2d::Zero(), Point2d::Zero());
      return b;
    }
  };

  // Utility functions.
  double area(const BBox& bbox);
  bool inside(const Point2d& p, const BBox& bbox);
  bool degenerate(const BBox& bbox, double eps = 1e-3);
  bool intersect(const BBox& bbox1, const BBox& bbox2);
  double jaccardSimilarity(const BBox& bbox1, const BBox& bbox2);
  double jaccardDistance(const BBox& bbox1, const BBox& bbox2);

  // I/O.
  std::ostream& operator<<(std::ostream& os, const BBox& bbox);

  // Intersection test.
  BBox intersection(const BBox& bbox1, const BBox& bbox2);

} /* namespace DO */

#endif /* DO_GEOMETRY_BBOX_HPP */
<|endoftext|>


<commit_before><commit_msg>Fixed selection not switching to new entities<commit_after><|endoftext|>


<commit_before>// CZone Delta Correlation Prefetcher
// Computer Acvhitecture NTNU 2017
// Anders Liland and Adrian Ribe

#include <iostream>
#include <list>
#include <map>
#include <stdint.h>
#include <string.h>
#include <vector>
#include <array>

#include "interface.hh"

#define BLOCK_SIZE 64
#define MAX_QUEUE_SIZE 100
#define MAX_PHYS_MEM_ADDR ((uint64_t)(256*1024*1024) - 1) // 268 MB

using std::cout;
using std::endl;
using std::vector;

//const int DELTA_CORRELATION_SEQUENCE_LENGTH = 2;
//const int CZONE_SIZE = 64; // KB
//const int PREFETCH_DEGREE = 4;
const int GHB_LENGTH_MAX = 10;
const int CZoneMask = 2; // number of digits to mask away

enum State{CZone,pushGHB, key_first, key_second, traverse, prefetch };

/* PRINT_ELEMENTS()
 * - prints optional C-string optcstr followed by
 * - all elements of the collection coll
 * - separated by spaces
 */
template <class T>
inline void PRINT_ELEMENTS (const T& coll, const char* optcstr="")
{
    typename T::const_iterator pos;

    std::cout << optcstr;
    for (pos=coll.begin(); pos!=coll.end(); ++pos) {
        //std::cout << *pos << ' ';
    }
    std::cout << std::endl;
}

struct GHBEntry{
    GHBEntry();
    GHBEntry(Addr mem_addr, int delta);
    Addr mem_addr, pc;
    int delta, key_first, key_second;
    //struct GHBEntry *next, *prev; // no longer needed wince GHBEntry is in vector
    GHBEntry *next, *prev;
};
GHBEntry::GHBEntry() : mem_addr(0), pc(0), delta(0), next(NULL), prev(NULL){}
GHBEntry::GHBEntry(Addr mem_addr, int delta) : mem_addr(mem_addr), pc(0),delta(delta), next(NULL), prev(NULL){}

class GHBTable{
    public:
        Addr calculatePrefetchAddr(Addr mem_addr);
        Addr maskCZoneAddr(Addr mem_addr);
        State state;

    private:
        std::map<Addr, GHBEntry*> indexTable;
        std::map<Addr, GHBEntry*>::iterator indexTableIterator;
        std::list<GHBEntry> ghb_list;
        std::vector<int> delta_buffer;

        std::array<int, 2> key_register;
        //std::array<int , 2> compare_register;

};

static GHBTable * table;

Addr GHBTable::maskCZoneAddr(Addr mem_addr){
    return mem_addr/(10*CZoneMask) ;
}

Addr GHBTable::calculatePrefetchAddr(Addr mem_addr){
    Addr CZoneTag;
    Addr pf_addr = -1;
    GHBEntry *CZoneHead = NULL;
    GHBEntry *entry = new GHBEntry();

    //GHBEntry *entryPtr = &entry;
    //new(entryPtr) GHBEntry();

    for (;;){
    switch (state) {
        case CZone:
            //cout << "CZone" << endl;s
            CZoneTag = maskCZoneAddr(mem_addr); // mask CZone tag
            indexTableIterator = indexTable.find(CZoneTag);
            if (indexTableIterator != indexTable.end()){ // CZone tag found in Index Table
                    //CZoneTag = indexTableIterator->first;
                    CZoneHead = indexTableIterator->second; // ptr to newest element in same CZone in GHB

                    //cout << "Found CZoneTag: " << CZoneTag << " *CZoneHead: " << CZoneHead << " CZoneHead->mem_addr: " << CZoneHead->mem_addr << endl;
            }else{ // tag not found
                CZoneHead = entry;
                CZoneHead->mem_addr = mem_addr;
                indexTable.insert(std::pair<Addr, GHBEntry*>(CZoneTag, CZoneHead));
                //cout << "CZoneTag not found, add new: " << "CZoneTag: " << CZoneTag << " *CZoneHead: " << CZoneHead << " CZoneHead->mem_addr: " << CZoneHead->mem_addr << endl;
            }
            state = pushGHB;
        break;
        case pushGHB:
            entry->mem_addr = mem_addr;
            entry->delta = mem_addr - CZoneHead->mem_addr;
            entry->next = CZoneHead;
            entry->prev = NULL;
            cout << "mem_addr: " << entry->mem_addr << " Delta: " << entry->delta << " struct addr: " << entry << endl;

            //update value in Inde prt Table
            CZoneHead->prev = entry;
            CZoneHead = entry;
            indexTableIterator->second = entry; // update ptr in map to point to newest emelent in CZone
            //cout << "Update Index Table: CZoneTag " << CZoneTag << " *CZoneHead: " << CZoneHead << " CZoneHead->mem_addr: " << CZoneHead->mem_addr << endl;
            indexTable.insert(std::pair<Addr, GHBEntry*>(CZoneTag, CZoneHead));
            ghb_list.push_front(*entry);

            //if (ghb_list.size() >= GHB_LENGTH_MAX){ // ghb_list is a FIFO. Pop end when list is too long.
            //    cout << "popGHB: " << ghb_list.back().mem_addr << endl;
            //    ghb_list.pop_back();
            //}
            state = key_first;
        break;
        case key_first:
            key_register[0] = entry->delta;
            key_register[1] = CZoneHead->delta;
            //cout << "key_register[0] = " << key_register[0] << "\t" << "key_register[1] = " << key_register[1] << endl;

            state = traverse;
        break;
        case key_second:

        break;
        case traverse:
            //cout << "traverse" << endl;
            // (traverse GHB and add deltas to Comparison Register

            //GHBEntry *n = head;
            //while(n != NULL){
            //}
            state = prefetch;
        break;
        case prefetch:
            //cout << "prefetch" << endl;
            for(std::list<GHBEntry>::iterator it = ghb_list.begin(); it != ghb_list.end(); it++){
                //cout << "Addr: " <<  it->mem_addr << " Delta: " << it->delta << endl;

            }

            //PRINT_ELEMENTS(ghb_list, "ghb_list:\t");
            pf_addr = -1;
            state = CZone;
            return pf_addr;

        break;
    }

}

    // Add two first deltas to Correlation Key Register

    //delta_buffer.push_back(table->add_begin(mem_addr));
    //delta_buffer.push_back(table->add_begin(mem_addr));

    //for(vector<int>::const_iterator i = delta_buffer.begin(); i != delta_buffer.end(); i++){
    //    cout << *i << ' ';
    //}
    //cout << endl;
    return -1;
}

// --------- PREFETCH SIMULATED FUNCTIONS ------------------------
void prefetch_init(void){
    std::cout << "prefetch_init" << std::endl;
    table = new GHBTable;

}

void prefetch_access(AccessStat stat){
    Addr pf_addr;
    if(stat.miss){
        pf_addr = table->calculatePrefetchAddr(stat.mem_addr);
        if(pf_addr < MAX_PHYS_MEM_ADDR && pf_addr != -1){
            cout << "Issue prefetch for address: " << pf_addr << endl;
            //issue_prefetch( pf_addr );
        }

    }
}
void prefetch_complete(Addr addr){
    cout << "prefetch_complete" << endl;
}

int main( ) {
    AccessStat stat;
    prefetch_init();

    int miss_addresses[9] = {1147,1149,1154,1156,1158,1163,1165,1170,1180};
    for (int i = 0; i < 9; i++ ){
        stat.pc = 55;
        stat.mem_addr = miss_addresses[i];
        stat.time = 1;
        stat.miss = 1;
        prefetch_access(stat);
    }

    prefetch_complete(stat.mem_addr);
    return 0;
}
<commit_msg>TODO for next time<commit_after>// CZone Delta Correlation Prefetcher
// Computer Acvhitecture NTNU 2017
// Anders Liland and Adrian Ribe

#include <iostream>
#include <list>
#include <map>
#include <stdint.h>
#include <string.h>
#include <vector>
#include <array>

#include "interface.hh"

#define BLOCK_SIZE 64
#define MAX_QUEUE_SIZE 100
#define MAX_PHYS_MEM_ADDR ((uint64_t)(256*1024*1024) - 1) // 268 MB

using std::cout;
using std::endl;
using std::vector;

//const int DELTA_CORRELATION_SEQUENCE_LENGTH = 2;
//const int CZONE_SIZE = 64; // KB
//const int PREFETCH_DEGREE = 4;
const int GHB_LENGTH_MAX = 10;
const int CZoneMask = 2; // number of digits to mask away

enum State{CZone,pushGHB, key_first, key_second, traverse, prefetch };

/* PRINT_ELEMENTS()
 * - prints optional C-string optcstr followed by
 * - all elements of the collection coll
 * - separated by spaces
 */
template <class T>
inline void PRINT_ELEMENTS (const T& coll, const char* optcstr="")
{
    typename T::const_iterator pos;

    std::cout << optcstr;
    for (pos=coll.begin(); pos!=coll.end(); ++pos) {
        //std::cout << *pos << ' ';
    }
    std::cout << std::endl;
}

struct GHBEntry{
    GHBEntry();
    GHBEntry(Addr mem_addr, int delta);
    Addr mem_addr, pc;
    int delta, key_first, key_second;
    //struct GHBEntry *next, *prev; // no longer needed wince GHBEntry is in vector
    GHBEntry *next, *prev;
};
GHBEntry::GHBEntry() : mem_addr(0), pc(0), delta(0), next(NULL), prev(NULL){}
GHBEntry::GHBEntry(Addr mem_addr, int delta) : mem_addr(mem_addr), pc(0),delta(delta), next(NULL), prev(NULL){}

class GHBTable{
    public:
        Addr calculatePrefetchAddr(Addr mem_addr);
        Addr maskCZoneAddr(Addr mem_addr);
        State state;

    private:
        std::map<Addr, GHBEntry*> indexTable;
        std::map<Addr, GHBEntry*>::iterator indexTableIterator;
        std::list<GHBEntry> ghb_list;
        std::vector<int> delta_buffer;

        std::array<int, 2> key_register;
        //std::array<int , 2> compare_register;

};

static GHBTable * table;

Addr GHBTable::maskCZoneAddr(Addr mem_addr){
    return mem_addr/(10*CZoneMask) ;
}

Addr GHBTable::calculatePrefetchAddr(Addr mem_addr){
    Addr CZoneTag;
    Addr pf_addr = -1;
    GHBEntry *CZoneHead = NULL;
    GHBEntry *entry = new GHBEntry();

    //GHBEntry *entryPtr = &entry;
    //new(entryPtr) GHBEntry();

    for (;;){
    switch (state) {
        case CZone:
            //cout << "CZone" << endl;s
            CZoneTag = maskCZoneAddr(mem_addr); // mask CZone tag
            indexTableIterator = indexTable.find(CZoneTag);
            if (indexTableIterator != indexTable.end()){ // CZone tag found in Index Table
                    //CZoneTag = indexTableIterator->first;
                    CZoneHead = indexTableIterator->second; // ptr to newest element in same CZone in GHB

                    //cout << "Found CZoneTag: " << CZoneTag << " *CZoneHead: " << CZoneHead << " CZoneHead->mem_addr: " << CZoneHead->mem_addr << endl;
            }else{ // tag not found
                CZoneHead = entry;
                CZoneHead->mem_addr = mem_addr;
                indexTable.insert(std::pair<Addr, GHBEntry*>(CZoneTag, CZoneHead));
                //cout << "CZoneTag not found, add new: " << "CZoneTag: " << CZoneTag << " *CZoneHead: " << CZoneHead << " CZoneHead->mem_addr: " << CZoneHead->mem_addr << endl;
            }
            state = pushGHB;
        break;
        case pushGHB:
            entry->mem_addr = mem_addr;
            entry->delta = mem_addr - CZoneHead->mem_addr;
            entry->next = CZoneHead;
            entry->prev = NULL;
            cout << "mem_addr: " << entry->mem_addr << " Delta: " << entry->delta << " struct addr: " << entry << endl;

            //update value in Inde prt Table
            CZoneHead->prev = entry;
            CZoneHead = entry;
            indexTableIterator->second = entry; // update ptr in map to point to newest emelent in CZone
            //cout << "Update Index Table: CZoneTag " << CZoneTag << " *CZoneHead: " << CZoneHead << " CZoneHead->mem_addr: " << CZoneHead->mem_addr << endl;
            indexTable.insert(std::pair<Addr, GHBEntry*>(CZoneTag, CZoneHead));
            ghb_list.push_front(*entry);

            // TODO: figure out why ghb_list is poped every time?
            //if (ghb_list.size() >= GHB_LENGTH_MAX){ // ghb_list is a FIFO. Pop end when list is too long.
            //    cout << "popGHB: " << ghb_list.back().mem_addr << endl;
            //    ghb_list.pop_back();
            //}
            state = key_first;
        break;
        case key_first:
            key_register[0] = entry->delta;
            key_register[1] = CZoneHead->delta;
            //cout << "key_register[0] = " << key_register[0] << "\t" << "key_register[1] = " << key_register[1] << endl;

            state = traverse;
        break;
        case key_second:

        break;
        case traverse:
            //cout << "traverse" << endl;
            // (traverse GHB and add deltas to Comparison Register

            //GHBEntry *n = head;
            //while(n != NULL){
            //}
            state = prefetch;
        break;
        case prefetch:
            //cout << "prefetch" << endl;
            for(std::list<GHBEntry>::iterator it = ghb_list.begin(); it != ghb_list.end(); it++){
                //cout << "Addr: " <<  it->mem_addr << " Delta: " << it->delta << endl;

            }

            //PRINT_ELEMENTS(ghb_list, "ghb_list:\t");
            pf_addr = -1;
            state = CZone;
            return pf_addr;

        break;
    }

}

    // Add two first deltas to Correlation Key Register

    //delta_buffer.push_back(table->add_begin(mem_addr));
    //delta_buffer.push_back(table->add_begin(mem_addr));

    //for(vector<int>::const_iterator i = delta_buffer.begin(); i != delta_buffer.end(); i++){
    //    cout << *i << ' ';
    //}
    //cout << endl;
    return -1;
}

// --------- PREFETCH SIMULATED FUNCTIONS ------------------------
void prefetch_init(void){
    std::cout << "prefetch_init" << std::endl;
    table = new GHBTable;

}

void prefetch_access(AccessStat stat){
    Addr pf_addr;
    if(stat.miss){
        pf_addr = table->calculatePrefetchAddr(stat.mem_addr);
        if(pf_addr < MAX_PHYS_MEM_ADDR && pf_addr != -1){
            cout << "Issue prefetch for address: " << pf_addr << endl;
            //issue_prefetch( pf_addr );
        }

    }
}
void prefetch_complete(Addr addr){
    cout << "prefetch_complete" << endl;
}

int main( ) {
    AccessStat stat;
    prefetch_init();

    int miss_addresses[9] = {1147,1149,1154,1156,1158,1163,1165,1170,1180};
    for (int i = 0; i < 9; i++ ){
        stat.pc = 55;
        stat.mem_addr = miss_addresses[i];
        stat.time = 1;
        stat.miss = 1;
        prefetch_access(stat);
    }

    prefetch_complete(stat.mem_addr);
    return 0;
}
<|endoftext|>


<commit_before><commit_msg>Use lstat instead of stat<commit_after><|endoftext|>


<commit_before>#include "DebugUtils.hpp"
#include <stdexcept>

void dataAssert(const char* description, const char* file, int line)
{
    throw std::invalid_argument(std::string(file) + ":" + std::to_string(line) + ": " + description);
}
<commit_msg>Add string header to DebugUtils.cpp<commit_after>#include "DebugUtils.hpp"
#include <stdexcept>
#include <string>

void dataAssert(const char* description, const char* file, int line)
{
    throw std::invalid_argument(std::string(file) + ":" + std::to_string(line) + ": " + description);
}
<|endoftext|>


<commit_before>#include <cmath>
#include <cstddef>
#include <cassert>
#include "Directions.hpp"
#include "MathUtils.hpp"

namespace
{
    // Class presents mesh nodes on the union sphere.
    // Holds the dot and it neighbors for creating more detailed mesh
    class PointWithNeighbors
    {
        public:
            PointWithNeighbors()
                : pos_{}
            {};

            void set(Vector3d const& position)
            {
                pos_ = position.normalized();
            }

            inline Vector3d vector() const
            {
                return pos_;
            }

            void setMiddle(PointWithNeighbors const *d1, PointWithNeighbors const *d2)
            {
                pos_ = (d1->pos_ + d2->pos_).normalized();
                midpointsNumber_ = 0;
            }

            inline std::uint32_t midpointsNumber() const
            { return midpointsNumber_; }

            inline PointWithNeighbors const *neighbor(std::uint32_t const i) const
            { return neighbors_[i]; }

            inline PointWithNeighbors *midpoint(std::uint32_t const i)
            { return midpoints_[i]; }

            void addMidpoint(PointWithNeighbors const *neighbor, PointWithNeighbors *midpoint)
            {
                neighbors_[midpointsNumber_] = neighbor;
                midpoints_[midpointsNumber_] = midpoint;
                ++midpointsNumber_;
            }

            inline void removeMidpoints()
            { midpointsNumber_ = 0; }

        private:
            Vector3d pos_;
            std::uint32_t midpointsNumber_{ 0 };
            PointWithNeighbors const *neighbors_[6]{};
            PointWithNeighbors *midpoints_[6]{};
    };

    // Element of a mesh on the union sphere
    class SphericalTriangle
    {
        public:
            SphericalTriangle() = default;

            void set(PointWithNeighbors *dot1, PointWithNeighbors *dot2, PointWithNeighbors *dot3)
            {
                dots_[0] = dot1;
                dots_[1] = dot2;
                dots_[2] = dot3;
            }

            Vector3d median() const
            {
                return (dots_[0]->vector() + dots_[1]->vector() + dots_[2]->vector()).normalized();
            }

            double square() const
            {
                double const triple = tripleProduct(
                    dots_[0]->vector(),
                    dots_[1]->vector(),
                    dots_[2]->vector());

                double const r0r1 = dots_[0]->vector() * dots_[1]->vector();
                double const r1r2 = dots_[1]->vector() * dots_[2]->vector();
                double const r0r2 = dots_[0]->vector() * dots_[2]->vector();

                return 2. * std::atan(triple / (1. + r0r1 + r1r2 + r0r2));
            }

            PointWithNeighbors *readyMeadpoint(int const i, int const j)
            {
                assert(0 <= i && i <= 2 && 0 <= j && j <= 2);

                for(std::uint32_t cnt=0; cnt!=dots_[i]->midpointsNumber(); ++cnt )
                {
                    if (dots_[i]->neighbor(cnt) == dots_[j])
                    {
                        return dots_[i]->midpoint(cnt);
                    }
                }

                return nullptr;
            }

            PointWithNeighbors *operator[](int i)
            { return dots_[i]; }

        private:
            PointWithNeighbors *dots_[3]{};
    };

    class IcosahedronMesh
    {
        public:
            explicit IcosahedronMesh(std::uint32_t directionsLevels)
                : directionsNumber_{ 0 }
                , readyPoints_{ 0 }
                , nodes_{ new PointWithNeighbors[nodesNumber(directionsLevels)]{} }
                , triangles_{ nullptr }
            {
                buildInitialMesh();

                for(std::uint32_t cnt=1; cnt<directionsLevels; ++cnt)
                {
                    splitMesh();
                }
            }

            ~IcosahedronMesh()
            {
                delete[] nodes_;
                delete[] triangles_;
            }

            Vector3d* points() const
            {
                auto points = new Vector3d[ directionsNumber_ ];

                for (std::uint64_t cnt=0; cnt<directionsNumber_; ++cnt)
                {
                    points[cnt] = triangles_[cnt].median();
                }

                return points;
            }

            double* weights() const
            {
                auto weights = new double[ directionsNumber_ ];

                for (std::uint64_t cnt=0; cnt<directionsNumber_; ++cnt)
                {
                    weights[cnt] = triangles_[cnt].square() * directionsNumber_ / 4. / PI;
                }

                return weights;
            }

            std::uint64_t directionsNumber() const
            {
                return directionsNumber_;
            }

        private:
            static std::uint32_t const ICOSAHEDRON_FACES{ 20 };
            static std::uint32_t const ICOSAHEDRON_VERTICES{ 12 };

            static std::uint64_t nodesNumber(std::uint32_t const directionsLevels)
            {
                std::uint64_t directionPointsNumber = ICOSAHEDRON_VERTICES;
                std::uint64_t directionsNumber = ICOSAHEDRON_FACES;

                for (std::uint64_t cnt=1; cnt<directionsLevels; ++cnt)
                {
                    directionPointsNumber = directionPointsNumber + (directionsNumber * 3) / 2;
                    directionsNumber *= 4;
                }

                return directionPointsNumber;
            }

            void buildInitialMesh()
            {
                directionsNumber_ = ICOSAHEDRON_FACES;
                readyPoints_ = ICOSAHEDRON_VERTICES;
                triangles_ = new SphericalTriangle[directionsNumber_]{};

                // initial sphere conditions
                nodes_[0].set(Vector3d{0.0, 0.0, std::sqrt(5.0)/2.0});
                for (int cnt=0; cnt!=5; ++cnt)
                {
                    double const angle = cnt * 72.;
                    nodes_[cnt+1].set(Vector3d{ std::cos(radians(angle)),  std::sin(radians(angle)),  0.5 });
                    nodes_[cnt+6].set(Vector3d{ std::cos(radians(36.+angle)),  std::sin(radians(36.+angle)),  -0.5});
                }
                nodes_[11].set(Vector3d{0.0, 0.0, -std::sqrt(5.0)/2.0});

                // triangles
                triangles_[0].set(&nodes_[0], &nodes_[1], &nodes_[2]);
                triangles_[1].set(&nodes_[0], &nodes_[2], &nodes_[3]);
                triangles_[2].set(&nodes_[0], &nodes_[3], &nodes_[4]);
                triangles_[3].set(&nodes_[0], &nodes_[4], &nodes_[5]);
                triangles_[4].set(&nodes_[0], &nodes_[5], &nodes_[1]);
                triangles_[5].set(&nodes_[10], &nodes_[11], &nodes_[6]);
                triangles_[6].set(&nodes_[11], &nodes_[7], &nodes_[6]);
                triangles_[7].set(&nodes_[11], &nodes_[8], &nodes_[7]);
                triangles_[8].set(&nodes_[11], &nodes_[9], &nodes_[8]);
                triangles_[9].set(&nodes_[11], &nodes_[10], &nodes_[9]);
                triangles_[10].set(&nodes_[6], &nodes_[1], &nodes_[10]);
                triangles_[11].set(&nodes_[2], &nodes_[6], &nodes_[7]);
                triangles_[12].set(&nodes_[3], &nodes_[7], &nodes_[8]);
                triangles_[13].set(&nodes_[4], &nodes_[8], &nodes_[9]);
                triangles_[14].set(&nodes_[5], &nodes_[9], &nodes_[10]);
                triangles_[15].set(&nodes_[6], &nodes_[2], &nodes_[1]);
                triangles_[16].set(&nodes_[7], &nodes_[3], &nodes_[2]);
                triangles_[17].set(&nodes_[8], &nodes_[4], &nodes_[3]);
                triangles_[18].set(&nodes_[9], &nodes_[5], &nodes_[4]);
                triangles_[19].set(&nodes_[10], &nodes_[1], &nodes_[5]);
            }

            PointWithNeighbors *getMidpoint(std::uint64_t const triangleId, int const i, int const j)
            {
                assert(0 <= i && i <= 2 && 0 <= j && j <= 2);

                // search for ready midpoint
                PointWithNeighbors *midpoint = triangles_[triangleId].readyMeadpoint(i, j);

                if (!midpoint)
                {
                    nodes_[readyPoints_].setMiddle(triangles_[triangleId][i], triangles_[triangleId][j]);
                    midpoint = &(nodes_[readyPoints_]);
                    ++readyPoints_;
                    triangles_[triangleId][i]->addMidpoint(triangles_[triangleId][j], midpoint);
                    triangles_[triangleId][j]->addMidpoint(triangles_[triangleId][i], midpoint);
                }

                return midpoint;
            }

            void splitMesh()
            {
                auto newTriangles = new SphericalTriangle[directionsNumber_ * 4]{};

                for(std::uint64_t cnt = 0; cnt < directionsNumber_; ++cnt)
                {
                    PointWithNeighbors *d_rib01 = getMidpoint(cnt, 0, 1);
                    PointWithNeighbors *d_rib02 = getMidpoint(cnt, 0, 2);
                    PointWithNeighbors *d_rib12 = getMidpoint(cnt, 1, 2);

                    newTriangles[ 4 * cnt     ].set(triangles_[cnt][0], d_rib01, d_rib02);
                    newTriangles[ 4 * cnt + 1 ].set(triangles_[cnt][1], d_rib12, d_rib01);
                    newTriangles[ 4 * cnt + 2 ].set(triangles_[cnt][2], d_rib02, d_rib12);
                    newTriangles[ 4 * cnt + 3 ].set(d_rib01, d_rib12, d_rib02);
                }

                delete[] triangles_;
                triangles_ = newTriangles;

                for (std::uint64_t cnt=0; cnt!=readyPoints_; ++cnt)
                {
                    nodes_[cnt].removeMidpoints();
                }

                directionsNumber_ *= 4;
            }

            std::uint64_t directionsNumber_;
            std::uint64_t readyPoints_;
            PointWithNeighbors *nodes_;
            SphericalTriangle *triangles_;
    };
}

// directions
Directions::Directions(std::uint32_t NumOfDirectionsLevels)
{
    IcosahedronMesh mesh(NumOfDirectionsLevels);
    points_ = mesh.points();
    w_	  = mesh.weights();
    directionsNumber_ = mesh.directionsNumber();
}
#include "iostream"

// directions
Directions::Directions(std::uint32_t Nside, bool)
{
    directionsNumber_ = 12 * Nside * Nside;
    points_ = new Vector3d[directionsNumber_]{};

    std::uint32_t p = 0;
    // North polar cap
    for (; p!= 2 * Nside * (Nside - 1); ++p)
    {
        double ph = (p + 1.) / 2;
        std::uint32_t i = std::sqrt(ph - std::sqrt(std::floor(ph))) + 1;
        std::uint32_t j = p + 1 - 2*i*(i-1);

        //    std::cout << ph << "\t" << std::sqrt(ph) << "\t" << ph - std::sqrt(std::floor(ph)) << "\t" << std::sqrt(ph - std::sqrt(std::floor(ph))) + 1 << "\t" << i << "\t" << j << std::endl;
        assert(1 <= i && i < Nside);
        assert(1 <= j && j <= 4 * i);

        double z = 1 - (i*i) / (3. * Nside * Nside);
        double phi = PI / (2 * i) * (j - 0.5);
        points_[p] = Vector3d(phi, std::acos(z));
    }

    // North equatorial belt
    for (; p!= 6 * Nside * Nside; ++p)
    {
        std::uint32_t pp = p - 2 * Nside * (Nside - 1);
        std::uint32_t i = pp / (4 * Nside) + Nside;
        std::uint32_t j = pp % (4 * Nside) + 1;

        assert(Nside <= i && i <= 2 * Nside);
        assert(1 <= j && j <= 4 * Nside);

        double z = 4. / 3 - (2 * i) / (3. * Nside);
        double s = (i - Nside + 1) % 2;
        double phi = PI / (2 * Nside) * (j - 0.5 * s);
        points_[p] = Vector3d(phi, std::acos(z));
    }

    for (p = 0 ; p!= 6 * Nside * Nside; ++p)
    {
        std::cout << points_[p].x() << " " << points_[p].y() << " " << points_[p].z() << "\n";
    }

    w_	  = new double[directionsNumber_]{};

    for (std::uint32_t i=0; i!=directionsNumber_; ++i)
    {
        w_[i] = 1.;
    }
}
<commit_msg>HEALPix: add the south half of the grid<commit_after>#include <cmath>
#include <cstddef>
#include <cassert>
#include "Directions.hpp"
#include "MathUtils.hpp"

namespace
{
    // Class presents mesh nodes on the union sphere.
    // Holds the dot and it neighbors for creating more detailed mesh
    class PointWithNeighbors
    {
        public:
            PointWithNeighbors()
                : pos_{}
            {};

            void set(Vector3d const& position)
            {
                pos_ = position.normalized();
            }

            inline Vector3d vector() const
            {
                return pos_;
            }

            void setMiddle(PointWithNeighbors const *d1, PointWithNeighbors const *d2)
            {
                pos_ = (d1->pos_ + d2->pos_).normalized();
                midpointsNumber_ = 0;
            }

            inline std::uint32_t midpointsNumber() const
            { return midpointsNumber_; }

            inline PointWithNeighbors const *neighbor(std::uint32_t const i) const
            { return neighbors_[i]; }

            inline PointWithNeighbors *midpoint(std::uint32_t const i)
            { return midpoints_[i]; }

            void addMidpoint(PointWithNeighbors const *neighbor, PointWithNeighbors *midpoint)
            {
                neighbors_[midpointsNumber_] = neighbor;
                midpoints_[midpointsNumber_] = midpoint;
                ++midpointsNumber_;
            }

            inline void removeMidpoints()
            { midpointsNumber_ = 0; }

        private:
            Vector3d pos_;
            std::uint32_t midpointsNumber_{ 0 };
            PointWithNeighbors const *neighbors_[6]{};
            PointWithNeighbors *midpoints_[6]{};
    };

    // Element of a mesh on the union sphere
    class SphericalTriangle
    {
        public:
            SphericalTriangle() = default;

            void set(PointWithNeighbors *dot1, PointWithNeighbors *dot2, PointWithNeighbors *dot3)
            {
                dots_[0] = dot1;
                dots_[1] = dot2;
                dots_[2] = dot3;
            }

            Vector3d median() const
            {
                return (dots_[0]->vector() + dots_[1]->vector() + dots_[2]->vector()).normalized();
            }

            double square() const
            {
                double const triple = tripleProduct(
                    dots_[0]->vector(),
                    dots_[1]->vector(),
                    dots_[2]->vector());

                double const r0r1 = dots_[0]->vector() * dots_[1]->vector();
                double const r1r2 = dots_[1]->vector() * dots_[2]->vector();
                double const r0r2 = dots_[0]->vector() * dots_[2]->vector();

                return 2. * std::atan(triple / (1. + r0r1 + r1r2 + r0r2));
            }

            PointWithNeighbors *readyMeadpoint(int const i, int const j)
            {
                assert(0 <= i && i <= 2 && 0 <= j && j <= 2);

                for(std::uint32_t cnt=0; cnt!=dots_[i]->midpointsNumber(); ++cnt )
                {
                    if (dots_[i]->neighbor(cnt) == dots_[j])
                    {
                        return dots_[i]->midpoint(cnt);
                    }
                }

                return nullptr;
            }

            PointWithNeighbors *operator[](int i)
            { return dots_[i]; }

        private:
            PointWithNeighbors *dots_[3]{};
    };

    class IcosahedronMesh
    {
        public:
            explicit IcosahedronMesh(std::uint32_t directionsLevels)
                : directionsNumber_{ 0 }
                , readyPoints_{ 0 }
                , nodes_{ new PointWithNeighbors[nodesNumber(directionsLevels)]{} }
                , triangles_{ nullptr }
            {
                buildInitialMesh();

                for(std::uint32_t cnt=1; cnt<directionsLevels; ++cnt)
                {
                    splitMesh();
                }
            }

            ~IcosahedronMesh()
            {
                delete[] nodes_;
                delete[] triangles_;
            }

            Vector3d* points() const
            {
                auto points = new Vector3d[ directionsNumber_ ];

                for (std::uint64_t cnt=0; cnt<directionsNumber_; ++cnt)
                {
                    points[cnt] = triangles_[cnt].median();
                }

                return points;
            }

            double* weights() const
            {
                auto weights = new double[ directionsNumber_ ];

                for (std::uint64_t cnt=0; cnt<directionsNumber_; ++cnt)
                {
                    weights[cnt] = triangles_[cnt].square() * directionsNumber_ / 4. / PI;
                }

                return weights;
            }

            std::uint64_t directionsNumber() const
            {
                return directionsNumber_;
            }

        private:
            static std::uint32_t const ICOSAHEDRON_FACES{ 20 };
            static std::uint32_t const ICOSAHEDRON_VERTICES{ 12 };

            static std::uint64_t nodesNumber(std::uint32_t const directionsLevels)
            {
                std::uint64_t directionPointsNumber = ICOSAHEDRON_VERTICES;
                std::uint64_t directionsNumber = ICOSAHEDRON_FACES;

                for (std::uint64_t cnt=1; cnt<directionsLevels; ++cnt)
                {
                    directionPointsNumber = directionPointsNumber + (directionsNumber * 3) / 2;
                    directionsNumber *= 4;
                }

                return directionPointsNumber;
            }

            void buildInitialMesh()
            {
                directionsNumber_ = ICOSAHEDRON_FACES;
                readyPoints_ = ICOSAHEDRON_VERTICES;
                triangles_ = new SphericalTriangle[directionsNumber_]{};

                // initial sphere conditions
                nodes_[0].set(Vector3d{0.0, 0.0, std::sqrt(5.0)/2.0});
                for (int cnt=0; cnt!=5; ++cnt)
                {
                    double const angle = cnt * 72.;
                    nodes_[cnt+1].set(Vector3d{ std::cos(radians(angle)),  std::sin(radians(angle)),  0.5 });
                    nodes_[cnt+6].set(Vector3d{ std::cos(radians(36.+angle)),  std::sin(radians(36.+angle)),  -0.5});
                }
                nodes_[11].set(Vector3d{0.0, 0.0, -std::sqrt(5.0)/2.0});

                // triangles
                triangles_[0].set(&nodes_[0], &nodes_[1], &nodes_[2]);
                triangles_[1].set(&nodes_[0], &nodes_[2], &nodes_[3]);
                triangles_[2].set(&nodes_[0], &nodes_[3], &nodes_[4]);
                triangles_[3].set(&nodes_[0], &nodes_[4], &nodes_[5]);
                triangles_[4].set(&nodes_[0], &nodes_[5], &nodes_[1]);
                triangles_[5].set(&nodes_[10], &nodes_[11], &nodes_[6]);
                triangles_[6].set(&nodes_[11], &nodes_[7], &nodes_[6]);
                triangles_[7].set(&nodes_[11], &nodes_[8], &nodes_[7]);
                triangles_[8].set(&nodes_[11], &nodes_[9], &nodes_[8]);
                triangles_[9].set(&nodes_[11], &nodes_[10], &nodes_[9]);
                triangles_[10].set(&nodes_[6], &nodes_[1], &nodes_[10]);
                triangles_[11].set(&nodes_[2], &nodes_[6], &nodes_[7]);
                triangles_[12].set(&nodes_[3], &nodes_[7], &nodes_[8]);
                triangles_[13].set(&nodes_[4], &nodes_[8], &nodes_[9]);
                triangles_[14].set(&nodes_[5], &nodes_[9], &nodes_[10]);
                triangles_[15].set(&nodes_[6], &nodes_[2], &nodes_[1]);
                triangles_[16].set(&nodes_[7], &nodes_[3], &nodes_[2]);
                triangles_[17].set(&nodes_[8], &nodes_[4], &nodes_[3]);
                triangles_[18].set(&nodes_[9], &nodes_[5], &nodes_[4]);
                triangles_[19].set(&nodes_[10], &nodes_[1], &nodes_[5]);
            }

            PointWithNeighbors *getMidpoint(std::uint64_t const triangleId, int const i, int const j)
            {
                assert(0 <= i && i <= 2 && 0 <= j && j <= 2);

                // search for ready midpoint
                PointWithNeighbors *midpoint = triangles_[triangleId].readyMeadpoint(i, j);

                if (!midpoint)
                {
                    nodes_[readyPoints_].setMiddle(triangles_[triangleId][i], triangles_[triangleId][j]);
                    midpoint = &(nodes_[readyPoints_]);
                    ++readyPoints_;
                    triangles_[triangleId][i]->addMidpoint(triangles_[triangleId][j], midpoint);
                    triangles_[triangleId][j]->addMidpoint(triangles_[triangleId][i], midpoint);
                }

                return midpoint;
            }

            void splitMesh()
            {
                auto newTriangles = new SphericalTriangle[directionsNumber_ * 4]{};

                for(std::uint64_t cnt = 0; cnt < directionsNumber_; ++cnt)
                {
                    PointWithNeighbors *d_rib01 = getMidpoint(cnt, 0, 1);
                    PointWithNeighbors *d_rib02 = getMidpoint(cnt, 0, 2);
                    PointWithNeighbors *d_rib12 = getMidpoint(cnt, 1, 2);

                    newTriangles[ 4 * cnt     ].set(triangles_[cnt][0], d_rib01, d_rib02);
                    newTriangles[ 4 * cnt + 1 ].set(triangles_[cnt][1], d_rib12, d_rib01);
                    newTriangles[ 4 * cnt + 2 ].set(triangles_[cnt][2], d_rib02, d_rib12);
                    newTriangles[ 4 * cnt + 3 ].set(d_rib01, d_rib12, d_rib02);
                }

                delete[] triangles_;
                triangles_ = newTriangles;

                for (std::uint64_t cnt=0; cnt!=readyPoints_; ++cnt)
                {
                    nodes_[cnt].removeMidpoints();
                }

                directionsNumber_ *= 4;
            }

            std::uint64_t directionsNumber_;
            std::uint64_t readyPoints_;
            PointWithNeighbors *nodes_;
            SphericalTriangle *triangles_;
    };
}

// directions
Directions::Directions(std::uint32_t NumOfDirectionsLevels)
{
    IcosahedronMesh mesh(NumOfDirectionsLevels);
    points_ = mesh.points();
    w_	  = mesh.weights();
    directionsNumber_ = mesh.directionsNumber();
}

// directions
Directions::Directions(std::uint32_t Nside, bool)
{
    directionsNumber_ = 12 * Nside * Nside;
    points_ = new Vector3d[directionsNumber_]{};

    std::uint32_t p = 0;
    // North polar cap
    for (; p!= 2 * Nside * (Nside - 1); ++p)
    {
        double ph = (p + 1.) / 2;
        std::uint32_t i = std::sqrt(ph - std::sqrt(std::floor(ph))) + 1;
        std::uint32_t j = p + 1 - 2*i*(i-1);

        assert(1 <= i && i < Nside);
        assert(1 <= j && j <= 4 * i);

        double z = 1 - (i*i) / (3. * Nside * Nside);
        double phi = PI / (2 * i) * (j - 0.5);
        points_[p] = Vector3d(phi, std::acos(z));
        points_[12 * Nside * Nside - 1 - p] = Vector3d(-phi, std::acos(-z));
    }

    // North equatorial belt
    for (; p!= 6 * Nside * Nside; ++p)
    {
        std::uint32_t pp = p - 2 * Nside * (Nside - 1);
        std::uint32_t i = pp / (4 * Nside) + Nside;
        std::uint32_t j = pp % (4 * Nside) + 1;

        assert(Nside <= i && i <= 2 * Nside);
        assert(1 <= j && j <= 4 * Nside);

        double z = 4. / 3 - (2 * i) / (3. * Nside);
        double s = (i - Nside + 1) % 2;
        double phi = PI / (2 * Nside) * (j - 0.5 * s);
        points_[p] = Vector3d(phi, std::acos(z));
        points_[12 * Nside * Nside - 1 - p] = Vector3d(-phi, std::acos(-z));
    }

    w_ = new double[directionsNumber_]{};

    for (std::uint32_t i=0; i!=directionsNumber_; ++i)
    {
        w_[i] = 1.;
    }
}
<|endoftext|>


<commit_before><commit_msg>Test_UpdateLocalData_WrongBoxes<commit_after><|endoftext|>


<commit_before>#include <iostream>
#include <string>
#include "TrelScript.h"
#include "Script.h"

TrelScript::TrelScript()
{
	m_filepath	= "{{use default}}";
	setInfo();
}

TrelScript::TrelScript(std::string a_filepath)
{
	m_filepath	= a_filepath;
	setInfo();
}

TrelScript::~TrelScript()
{
	std::cout << "Execution complete.";
}

void TrelScript::setInfo()
{
	m_name		= "Trel Script";
	m_version	= "0.2.5";
}

void TrelScript::runScript()
{
	std::cout << m_name + " v" + m_version << std::endl;

	Script *thisScript	= new Script(m_filepath);
	thisScript->executeScript();
}<commit_msg>fixed small derp<commit_after>#include <iostream>
#include <string>
#include "TrelScript.h"
#include "Script.h"

TrelScript::TrelScript()
{
	m_filepath	= "{{use default}}";
	setInfo();
}

TrelScript::TrelScript(std::string a_filepath)
{
	m_filepath	= a_filepath;
	setInfo();
}

TrelScript::~TrelScript()
{
	std::cout << "Execution complete.\n";
}

void TrelScript::setInfo()
{
	m_name		= "Trel Script";
	m_version	= "0.2.6";
}

void TrelScript::runScript()
{
	std::cout << m_name + " v" + m_version << std::endl;

	Script *thisScript	= new Script(m_filepath);
	thisScript->executeScript();
}<|endoftext|>


<commit_before><commit_msg>Related: fdo#61688 get strict ordering right<commit_after><|endoftext|>


<commit_before><commit_msg>Add checkpoints as a valid estimate for cold-staking activation<commit_after><|endoftext|>


<commit_before>#include <cstdlib>
#include <iomanip>
#include <iostream>
#include <iterator>
#include <regex>
#include <stdexcept>
#include <string>
#include <utility>
#include <vector>

#include <boost/filesystem.hpp>
#include <boost/icl/interval_set.hpp>
#include <boost/program_options.hpp>

#include "level_set_parser.hpp"
#include "logger.hpp"
#include "preparer.hpp"
#include "solver.hpp"

namespace fs = boost::filesystem;
namespace icl = boost::icl;
namespace opt = boost::program_options;

void check_conflicting_options(opt::variables_map& variables, std::string master, std::string slave);
int parse_max_taps(std::string text);
bool create_directory_if_not_exists(fs::path path);
void prepare_and_handle_files(
	std::vector<fs::path>& files_to_prepare,
	std::vector<fs::path>& files_to_handle,
	icl::interval_set<int>& levels_to_solve);
void solve_levels(
	icl::interval_set<int>& levels_to_solve,
	opt::variables_map& variables,
	int max_taps,
	Logger& logger);

int main(int argument_count, char** argument_values) {
	try {
		opt::options_description description(
			"Solves circuit500 levels.\n\n"

			"All operations are performed in the 'data/' directory relative to the current\n"
			"working directory, which should already exist and contain some reference images\n"
			"for the solver inside 'data/reference/'.\n\n"

			"Screenshots of the levels should be placed inside the 'data/raw/' directory.\n\n"

			"During the preparation phase the program extracts the level number from the\n"
			"screenshots and places a normalized version of the level area in an\n"
			"appropriately named file inside the 'data/levels/' directory.\n\n"

			"During the solving phase the program attempts to solve the levels and\n"
			"puts solutions in the 'data/solutions/' directory.\n\n"

			"Options");

		description.add_options()
			("help",
				"Prints this help message.\n")

			("log,l",
				"Logs statistics about the solving phase into a log file inside 'data/logs/'.\n")

			("dry,d",
				"Does not save solutions during the solving phase.\n")

			("unsolved,u",
				"Solves only those levels for which it cannot already find a solution inside "
				"'data/solutions/'.\n")

			("taps,t", opt::value<std::string>()->default_value("3"),
				("Specifies the maximum number of taps to check for solutions.\n"
				 "Must be between " + std::to_string(Solver::tap_minimum()) +
				 " and " + std::to_string(Solver::tap_maximum()) + " (both inclusive).\n").c_str())

			("prepare,p", opt::value<std::vector<std::string>>()->multitoken(),
				"Prepares the specified files.\n"
				"Must be followed by one or more filenames.\n"
				"Filenames must not include 'data/raw/'.\n")

			("prepare-all,P",
				"Prepares all files in 'data/raw/'.\n")

			("solve,s", opt::value<std::vector<std::string>>()->multitoken(),
				"Solves the specified levels.\n"
				"Must be followed by one or more level descriptions in the form of:\n"
				" X:   \twhere X is a level number between 1 and 500. "
				"Solves the specified level.\n"
				" X-Y: \twhere X and Y are level numbers between 1 and 500 and X is less than or "
				"equal to Y. Solves all levels between X and Y (both inclusive).\n")

			("solve-all,S",
				"Solves all levels.\n")

			("handle,h", opt::value<std::vector<std::string>>()->multitoken(),
				"Prepares the specified files and solves the levels they contain.\n")

			("handle-all,H",
				"Handles all files in 'data/raw/'.\n")
		;

		opt::options_description helper_description;
		helper_description.add_options()
			("__unrecognized__", opt::value<std::vector<std::string>>())
		;

		opt::options_description cmdline_options;
		cmdline_options.add(description).add(helper_description);

		opt::positional_options_description positional_description;
		positional_description.add("__unrecognized__", -1);

		opt::variables_map variables;
		opt::store(opt::command_line_parser(argument_count, argument_values)
			.options(cmdline_options).positional(positional_description).run(), variables);
		opt::notify(variables);

		if (variables.count("__unrecognized__"))
			throw std::runtime_error("unexpected argument: '" + variables["__unrecognized__"].as<std::vector<std::string>>()[0] + "'");
		check_conflicting_options(variables, "handle-all", "handle");
		check_conflicting_options(variables, "solve-all", "solve");
		check_conflicting_options(variables, "prepare-all", "prepare");

		if (variables.count("help")) {
			std::cout << description << std::endl;
		}

		fs::path reference_dir("data/reference/");

		if (!fs::is_directory(reference_dir)) {
			std::string error("could not find directory '" + reference_dir.string() + "'");
			if (!variables.count("help"))
				error.append("; use '--help' to get more information");
			throw std::runtime_error(error);
		}

		if (argument_count == 1) { // No options
			std::cout << "use '--help' to get usage information" << std::endl;
		}

		create_directory_if_not_exists("data/levels/");
		create_directory_if_not_exists("data/raw/");
		create_directory_if_not_exists("data/solutions/");
		create_directory_if_not_exists("data/logs/");

		std::vector<fs::path> files_to_prepare;
		std::vector<fs::path> files_to_handle;
		icl::interval_set<int> levels_to_solve;

		if (variables.count("prepare-all")) {
			for (auto&& entry : fs::directory_iterator("data/raw/")) {
				files_to_prepare.push_back(entry.path());
			}
		}
		if (variables.count("prepare")) {
			fs::path dir = "data/raw";
			std::vector<std::string> input_list = variables["prepare"].as<std::vector<std::string>>();
			for (auto&& entry : input_list) {
				files_to_prepare.push_back(dir / entry);
			}
		}

		if (variables.count("handle-all")) {
			for (auto&& entry : fs::directory_iterator("data/raw/")) {
				files_to_handle.push_back(entry.path());
			}
		}
		if (variables.count("handle")) {
			fs::path dir = "data/raw";
			std::vector<std::string> input_list = variables["handle"].as<std::vector<std::string>>();
			for (auto&& entry : input_list) {
				files_to_handle.push_back(dir / entry);
			}
		}

		if (variables.count("solve-all")) {
			levels_to_solve.insert(icl::interval<int>::closed(1, 500));
		}
		if (variables.count("solve")) {
			std::vector<std::string> input_list = variables["solve"].as<std::vector<std::string>>();
			levels_to_solve += Level_Set_Parser(input_list).parse();
		}

		int max_taps = parse_max_taps(variables["taps"].as<std::string>());

		Logger* logger = variables.count("log") ? Logger::create_file_logger() : Logger::create_fake_logger();
		if (!logger) {
			throw std::runtime_error("out of memory: failed to create logger");
		}

		prepare_and_handle_files(files_to_prepare, files_to_handle, levels_to_solve);
		solve_levels(levels_to_solve, variables, max_taps, *logger);

		delete logger;

		return EXIT_SUCCESS;
	} catch(std::exception& e) {
		std::cerr << e.what() << std::endl;
		return EXIT_FAILURE;
	}
}

void check_conflicting_options(opt::variables_map& variables, std::string master, std::string slave) {
	if (variables.count(master) && variables.count(slave))
			throw std::runtime_error(slave + " is not allowed if " + master + " is used");
}

int parse_max_taps(std::string text) {
	std::regex regex("\\d{1,3}");
	std::smatch match;

	if (!regex_match(text, match, regex))
		throw std::runtime_error("expected tap count, but found: '" + text + "'");

	int max_taps = std::stoi(match[0]);
	if (max_taps < Solver::tap_minimum())
		throw std::runtime_error("tap count must be " + std::to_string(Solver::tap_minimum()) + " or more, but was: '" + text + "'");
	if (max_taps > Solver::tap_maximum())
		throw std::runtime_error("tap count must be " + std::to_string(Solver::tap_maximum()) + " or less, but was: '" + text + "'");
	return max_taps;
}

bool create_directory_if_not_exists(fs::path path) {
	if (fs::is_directory(path)) return true;
	return fs::create_directory(path);
}

void prepare_and_handle_files(
	std::vector<fs::path>& files_to_prepare,
	std::vector<fs::path>& files_to_handle,
	icl::interval_set<int>& levels_to_solve) {

	Preparer preparer;
	if (!preparer.is_initialized()) return;

	int count = 0, total = files_to_prepare.size() + files_to_handle.size();

	for (auto&& it : files_to_prepare) {
		int progress = 100 * (++count) / total;
		std::cout << std::setfill(' ') << std::setw(3) << progress << "%: " << it.generic_string() << ": ";
		preparer.prepare(it);
	}

	for (auto&& it : files_to_handle) {
		int progress = 100 * (++count) / total;
		std::cout << std::setfill(' ') << std::setw(3) << progress << "%: " << it.generic_string() << ": ";
		int level_number = preparer.prepare(it);
		if (level_number != 0) levels_to_solve.insert(level_number);
	}
}

void solve_levels(icl::interval_set<int>& level_set, opt::variables_map& variables, int max_taps, Logger& logger) {
	Solver solver(logger, max_taps);
	solver.unsolved = variables.count("unsolved");
	solver.dry = variables.count("dry");
	for(icl::interval_set<int>::element_iterator level_it = elements_begin(level_set);
		level_it != elements_end(level_set);
		++level_it)
		solver.solve_level(*level_it);
}
<commit_msg>Inline parse_max_taps().<commit_after>#include <cstdlib>
#include <iomanip>
#include <iostream>
#include <iterator>
#include <regex>
#include <stdexcept>
#include <string>
#include <utility>
#include <vector>

#include <boost/filesystem.hpp>
#include <boost/icl/interval_set.hpp>
#include <boost/program_options.hpp>

#include "level_set_parser.hpp"
#include "logger.hpp"
#include "preparer.hpp"
#include "solver.hpp"

namespace fs = boost::filesystem;
namespace icl = boost::icl;
namespace opt = boost::program_options;

void check_conflicting_options(opt::variables_map& variables, std::string master, std::string slave);
bool create_directory_if_not_exists(fs::path path);
void prepare_and_handle_files(
	std::vector<fs::path>& files_to_prepare,
	std::vector<fs::path>& files_to_handle,
	icl::interval_set<int>& levels_to_solve);
void solve_levels(
	icl::interval_set<int>& levels_to_solve,
	opt::variables_map& variables,
	int max_taps,
	Logger& logger);

int main(int argument_count, char** argument_values) {
	try {
		opt::options_description description(
			"Solves circuit500 levels.\n\n"

			"All operations are performed in the 'data/' directory relative to the current\n"
			"working directory, which should already exist and contain some reference images\n"
			"for the solver inside 'data/reference/'.\n\n"

			"Screenshots of the levels should be placed inside the 'data/raw/' directory.\n\n"

			"During the preparation phase the program extracts the level number from the\n"
			"screenshots and places a normalized version of the level area in an\n"
			"appropriately named file inside the 'data/levels/' directory.\n\n"

			"During the solving phase the program attempts to solve the levels and\n"
			"puts solutions in the 'data/solutions/' directory.\n\n"

			"Options");

		description.add_options()
			("help",
				"Prints this help message.\n")

			("log,l",
				"Logs statistics about the solving phase into a log file inside 'data/logs/'.\n")

			("dry,d",
				"Does not save solutions during the solving phase.\n")

			("unsolved,u",
				"Solves only those levels for which it cannot already find a solution inside "
				"'data/solutions/'.\n")

			("taps,t", opt::value<std::string>()->default_value("3"),
				("Specifies the maximum number of taps to check for solutions.\n"
				 "Must be between " + std::to_string(Solver::tap_minimum()) +
				 " and " + std::to_string(Solver::tap_maximum()) + " (both inclusive).\n").c_str())

			("prepare,p", opt::value<std::vector<std::string>>()->multitoken(),
				"Prepares the specified files.\n"
				"Must be followed by one or more filenames.\n"
				"Filenames must not include 'data/raw/'.\n")

			("prepare-all,P",
				"Prepares all files in 'data/raw/'.\n")

			("solve,s", opt::value<std::vector<std::string>>()->multitoken(),
				"Solves the specified levels.\n"
				"Must be followed by one or more level descriptions in the form of:\n"
				" X:   \twhere X is a level number between 1 and 500. "
				"Solves the specified level.\n"
				" X-Y: \twhere X and Y are level numbers between 1 and 500 and X is less than or "
				"equal to Y. Solves all levels between X and Y (both inclusive).\n")

			("solve-all,S",
				"Solves all levels.\n")

			("handle,h", opt::value<std::vector<std::string>>()->multitoken(),
				"Prepares the specified files and solves the levels they contain.\n")

			("handle-all,H",
				"Handles all files in 'data/raw/'.\n")
		;

		opt::options_description helper_description;
		helper_description.add_options()
			("__unrecognized__", opt::value<std::vector<std::string>>())
		;

		opt::options_description cmdline_options;
		cmdline_options.add(description).add(helper_description);

		opt::positional_options_description positional_description;
		positional_description.add("__unrecognized__", -1);

		opt::variables_map variables;
		opt::store(opt::command_line_parser(argument_count, argument_values)
			.options(cmdline_options).positional(positional_description).run(), variables);
		opt::notify(variables);

		if (variables.count("__unrecognized__"))
			throw std::runtime_error("unexpected argument: '" + variables["__unrecognized__"].as<std::vector<std::string>>()[0] + "'");
		check_conflicting_options(variables, "handle-all", "handle");
		check_conflicting_options(variables, "solve-all", "solve");
		check_conflicting_options(variables, "prepare-all", "prepare");

		if (variables.count("help")) {
			std::cout << description << std::endl;
		}

		fs::path reference_dir("data/reference/");

		if (!fs::is_directory(reference_dir)) {
			std::string error("could not find directory '" + reference_dir.string() + "'");
			if (!variables.count("help"))
				error.append("; use '--help' to get more information");
			throw std::runtime_error(error);
		}

		if (argument_count == 1) { // No options
			std::cout << "use '--help' to get usage information" << std::endl;
		}

		create_directory_if_not_exists("data/levels/");
		create_directory_if_not_exists("data/raw/");
		create_directory_if_not_exists("data/solutions/");
		create_directory_if_not_exists("data/logs/");

		std::vector<fs::path> files_to_prepare;
		std::vector<fs::path> files_to_handle;
		icl::interval_set<int> levels_to_solve;

		if (variables.count("prepare-all")) {
			for (auto&& entry : fs::directory_iterator("data/raw/")) {
				files_to_prepare.push_back(entry.path());
			}
		}
		if (variables.count("prepare")) {
			fs::path dir = "data/raw";
			std::vector<std::string> input_list = variables["prepare"].as<std::vector<std::string>>();
			for (auto&& entry : input_list) {
				files_to_prepare.push_back(dir / entry);
			}
		}

		if (variables.count("handle-all")) {
			for (auto&& entry : fs::directory_iterator("data/raw/")) {
				files_to_handle.push_back(entry.path());
			}
		}
		if (variables.count("handle")) {
			fs::path dir = "data/raw";
			std::vector<std::string> input_list = variables["handle"].as<std::vector<std::string>>();
			for (auto&& entry : input_list) {
				files_to_handle.push_back(dir / entry);
			}
		}

		if (variables.count("solve-all")) {
			levels_to_solve.insert(icl::interval<int>::closed(1, 500));
		}
		if (variables.count("solve")) {
			std::vector<std::string> input_list = variables["solve"].as<std::vector<std::string>>();
			levels_to_solve += Level_Set_Parser(input_list).parse();
		}

		int max_taps;
		{
			std::string text = variables["taps"].as<std::string>();
			std::regex regex("\\d{1,3}");
			std::smatch match;

			if (!regex_match(text, match, regex))
				throw std::runtime_error("expected tap count, but found: '" + text + "'");

			max_taps = std::stoi(match[0]);
			if (max_taps < Solver::tap_minimum())
				throw std::runtime_error("tap count must be " + std::to_string(Solver::tap_minimum()) + " or more, but was: '" + text + "'");
			if (max_taps > Solver::tap_maximum())
				throw std::runtime_error("tap count must be " + std::to_string(Solver::tap_maximum()) + " or less, but was: '" + text + "'");
		}

		Logger* logger = variables.count("log") ? Logger::create_file_logger() : Logger::create_fake_logger();
		if (!logger)
			throw std::runtime_error("out of memory: failed to create logger");

		prepare_and_handle_files(files_to_prepare, files_to_handle, levels_to_solve);
		solve_levels(levels_to_solve, variables, max_taps, *logger);

		delete logger;

		return EXIT_SUCCESS;
	} catch(std::exception& e) {
		std::cerr << e.what() << std::endl;
		return EXIT_FAILURE;
	}
}

void check_conflicting_options(opt::variables_map& variables, std::string master, std::string slave) {
	if (variables.count(master) && variables.count(slave))
			throw std::runtime_error(slave + " is not allowed if " + master + " is used");
}

bool create_directory_if_not_exists(fs::path path) {
	if (fs::is_directory(path)) return true;
	return fs::create_directory(path);
}

void prepare_and_handle_files(
	std::vector<fs::path>& files_to_prepare,
	std::vector<fs::path>& files_to_handle,
	icl::interval_set<int>& levels_to_solve) {

	Preparer preparer;
	if (!preparer.is_initialized()) return;

	int count = 0, total = files_to_prepare.size() + files_to_handle.size();

	for (auto&& it : files_to_prepare) {
		int progress = 100 * (++count) / total;
		std::cout << std::setfill(' ') << std::setw(3) << progress << "%: " << it.generic_string() << ": ";
		preparer.prepare(it);
	}

	for (auto&& it : files_to_handle) {
		int progress = 100 * (++count) / total;
		std::cout << std::setfill(' ') << std::setw(3) << progress << "%: " << it.generic_string() << ": ";
		int level_number = preparer.prepare(it);
		if (level_number != 0) levels_to_solve.insert(level_number);
	}
}

void solve_levels(icl::interval_set<int>& level_set, opt::variables_map& variables, int max_taps, Logger& logger) {
	Solver solver(logger, max_taps);
	solver.unsolved = variables.count("unsolved");
	solver.dry = variables.count("dry");
	for(icl::interval_set<int>::element_iterator level_it = elements_begin(level_set);
		level_it != elements_end(level_set);
		++level_it)
		solver.solve_level(*level_it);
}
<|endoftext|>