<commit_before>/* Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License. */

#include "paddle/fluid/operators/controlflow/logical_op.h"
#include <string>
#include "paddle/fluid/framework/op_registry.h"

namespace paddle {
namespace operators {
template <typename OpComment>
class BinaryLogicalOpProtoMaker : public framework::OpProtoAndCheckerMaker {
 public:
  void Make() override {
    OpComment comment;
    AddInput("X",
             string::Sprintf("(LoDTensor) Left hand operand of %s operator",
                             comment.type));
    AddInput("Y",
             string::Sprintf("(LoDTensor) Right hand operand of %s operator",
                             comment.type));
    AddOutput("Out", string::Sprintf(
                         "(LoDTensor) n-dim bool tensor. Each element is %s",
                         comment.equation));
    AddComment(string::Sprintf(R"DOC(%s Operator

It operates element-wise on X and Y, and returns the Out. X, Y and Out are N-dim boolean tensors.
Each element of Out is calculated by %s
)DOC",
                               comment.type, comment.equation));
  }
};

template <typename OpComment>
class UnaryLogicalOpProtoMaker : public framework::OpProtoAndCheckerMaker {
 public:
  void Make() override {
    OpComment comment;
    AddInput("X", string::Sprintf("(LoDTensor) Operand of %s operator",
                                  comment.type));
    AddOutput("Out", string::Sprintf(
                         "(LoDTensor) n-dim bool tensor. Each element is %s",
                         comment.equation));
    AddComment(string::Sprintf(R"DOC(%s Operator

It operates element-wise on X, and returns the Out. X and Out are N-dim boolean tensors.
Each element of Out is calculated by %s
)DOC",
                               comment.type, comment.equation));
  }
};

template <typename OpComment>
class BinaryLogicalOpInferShape : public framework::InferShapeBase {
 public:
  void operator()(framework::InferShapeContext *context) const override {
    OpComment comment;
    PADDLE_ENFORCE(context->HasInput("X"),
                   "Input(X) of %s operator must not be null", comment.type);
    PADDLE_ENFORCE(context->HasInput("Y"),
                   "Input(Y) of %s operator must not be null", comment.type);
    auto dim_x = context->GetInputDim("X");
    auto dim_y = context->GetInputDim("Y");
    PADDLE_ENFORCE_EQ(framework::product(dim_x), framework::product(dim_y),
                      "The number of elements in X and Y should be same");

    context->SetOutputDim("Out", context->GetInputDim("X"));
    context->ShareLoD("X", "Out");
  }
};

template <typename OpComment>
class UnaryLogicalOpInferShape : public framework::InferShapeBase {
 public:
  void operator()(framework::InferShapeContext *context) const override {
    OpComment comment;
    PADDLE_ENFORCE(context->HasInput("X"),
                   "Input(X) of %s operator must not be null", comment.type);
    context->SetOutputDim("Out", context->GetInputDim("X"));
    context->ShareLoD("X", "Out");
  }
};

class LogicalOp : public framework::OperatorWithKernel {
 public:
  using framework::OperatorWithKernel::OperatorWithKernel;

 protected:
  framework::OpKernelType GetExpectedKernelType(
      const framework::ExecutionContext &ctx) const override {
    framework::OpKernelType kt = OperatorWithKernel::GetExpectedKernelType(ctx);
    // LogicalOp kernel's device type is decided by input tensor place
    kt.place_ = ctx.Input<framework::LoDTensor>("X")->place();
    return kt;
  }
};

}  // namespace operators
}  // namespace paddle

#define REGISTER_BINARY_LOGICAL_OP(op_type, _equation)                     \
  struct _##op_type##Comment {                                             \
    static char type[];                                                    \
    static char equation[];                                                \
  };                                                                       \
  char _##op_type##Comment::type[]{#op_type};                              \
  char _##op_type##Comment::equation[]{_equation};                         \
  REGISTER_OPERATOR(                                                       \
      op_type, ::paddle::operators::LogicalOp,                             \
      ::paddle::operators::BinaryLogicalOpProtoMaker<_##op_type##Comment>, \
      ::paddle::operators::BinaryLogicalOpInferShape<_##op_type##Comment>, \
      ::paddle::framework::EmptyGradOpMaker);

#define REGISTER_UNARY_LOGICAL_OP(op_type, _equation)                     \
  struct _##op_type##Comment {                                            \
    static char type[];                                                   \
    static char equation[];                                               \
  };                                                                      \
  char _##op_type##Comment::type[]{#op_type};                             \
  char _##op_type##Comment::equation[]{_equation};                        \
  REGISTER_OPERATOR(                                                      \
      op_type, ::paddle::operators::LogicalOp,                            \
      ::paddle::operators::UnaryLogicalOpProtoMaker<_##op_type##Comment>, \
      ::paddle::operators::UnaryLogicalOpInferShape<_##op_type##Comment>, \
      ::paddle::framework::EmptyGradOpMaker);

REGISTER_BINARY_LOGICAL_OP(logical_and, "$$Out = X \\&\\& Y$$");
REGISTER_BINARY_LOGICAL_KERNEL(logical_and, CPU,
                               paddle::operators::LogicalAndFunctor);
REGISTER_BINARY_LOGICAL_OP(logical_or, "$$Out = X || Y$$");
REGISTER_BINARY_LOGICAL_KERNEL(logical_or, CPU,
                               paddle::operators::LogicalOrFunctor);
REGISTER_UNARY_LOGICAL_OP(logical_not, "$$Out = !X$$");
REGISTER_UNARY_LOGICAL_KERNEL(logical_not, CPU,
                              paddle::operators::LogicalNotFunctor);
REGISTER_BINARY_LOGICAL_OP(logical_xor,
                           "$$Out = (X || Y) \\&\\& !(X \\&\\& Y)$$");
REGISTER_BINARY_LOGICAL_KERNEL(logical_xor, CPU,
                               paddle::operators::LogicalXorFunctor);
<commit_msg>fix logical op infershape<commit_after>/* Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License. */

#include "paddle/fluid/operators/controlflow/logical_op.h"
#include <string>
#include "paddle/fluid/framework/op_registry.h"

namespace paddle {
namespace operators {
template <typename OpComment>
class BinaryLogicalOpProtoMaker : public framework::OpProtoAndCheckerMaker {
 public:
  void Make() override {
    OpComment comment;
    AddInput("X",
             string::Sprintf("(LoDTensor) Left hand operand of %s operator",
                             comment.type));
    AddInput("Y",
             string::Sprintf("(LoDTensor) Right hand operand of %s operator",
                             comment.type));
    AddOutput("Out", string::Sprintf(
                         "(LoDTensor) n-dim bool tensor. Each element is %s",
                         comment.equation));
    AddComment(string::Sprintf(R"DOC(%s Operator

It operates element-wise on X and Y, and returns the Out. X, Y and Out are N-dim boolean tensors.
Each element of Out is calculated by %s
)DOC",
                               comment.type, comment.equation));
  }
};

template <typename OpComment>
class UnaryLogicalOpProtoMaker : public framework::OpProtoAndCheckerMaker {
 public:
  void Make() override {
    OpComment comment;
    AddInput("X", string::Sprintf("(LoDTensor) Operand of %s operator",
                                  comment.type));
    AddOutput("Out", string::Sprintf(
                         "(LoDTensor) n-dim bool tensor. Each element is %s",
                         comment.equation));
    AddComment(string::Sprintf(R"DOC(%s Operator

It operates element-wise on X, and returns the Out. X and Out are N-dim boolean tensors.
Each element of Out is calculated by %s
)DOC",
                               comment.type, comment.equation));
  }
};

template <typename OpComment>
class BinaryLogicalOpInferShape : public framework::InferShapeBase {
 public:
  void operator()(framework::InferShapeContext *context) const override {
    OpComment comment;
    PADDLE_ENFORCE(context->HasInput("X"),
                   "Input(X) of %s operator must not be null", comment.type);
    PADDLE_ENFORCE(context->HasInput("Y"),
                   "Input(Y) of %s operator must not be null", comment.type);
    auto dim_x = context->GetInputDim("X");
    auto dim_y = context->GetInputDim("Y");

    int product_x = framework::product(dim_x);
    int product_y = framework::product(dim_y);
    bool check = ctx->IsRuntime() && product_x >= 0 && product_y >= 0;
    if (check) {
      PADDLE_ENFORCE_EQ(framework::product(dim_x), framework::product(dim_y),
                        "The number of elements in X and Y should be same");
    }

    context->SetOutputDim("Out", context->GetInputDim("X"));
    context->ShareLoD("X", "Out");
  }
};

template <typename OpComment>
class UnaryLogicalOpInferShape : public framework::InferShapeBase {
 public:
  void operator()(framework::InferShapeContext *context) const override {
    OpComment comment;
    PADDLE_ENFORCE(context->HasInput("X"),
                   "Input(X) of %s operator must not be null", comment.type);
    context->SetOutputDim("Out", context->GetInputDim("X"));
    context->ShareLoD("X", "Out");
  }
};

class LogicalOp : public framework::OperatorWithKernel {
 public:
  using framework::OperatorWithKernel::OperatorWithKernel;

 protected:
  framework::OpKernelType GetExpectedKernelType(
      const framework::ExecutionContext &ctx) const override {
    framework::OpKernelType kt = OperatorWithKernel::GetExpectedKernelType(ctx);
    // LogicalOp kernel's device type is decided by input tensor place
    kt.place_ = ctx.Input<framework::LoDTensor>("X")->place();
    return kt;
  }
};

}  // namespace operators
}  // namespace paddle

#define REGISTER_BINARY_LOGICAL_OP(op_type, _equation)                     \
  struct _##op_type##Comment {                                             \
    static char type[];                                                    \
    static char equation[];                                                \
  };                                                                       \
  char _##op_type##Comment::type[]{#op_type};                              \
  char _##op_type##Comment::equation[]{_equation};                         \
  REGISTER_OPERATOR(                                                       \
      op_type, ::paddle::operators::LogicalOp,                             \
      ::paddle::operators::BinaryLogicalOpProtoMaker<_##op_type##Comment>, \
      ::paddle::operators::BinaryLogicalOpInferShape<_##op_type##Comment>, \
      ::paddle::framework::EmptyGradOpMaker);

#define REGISTER_UNARY_LOGICAL_OP(op_type, _equation)                     \
  struct _##op_type##Comment {                                            \
    static char type[];                                                   \
    static char equation[];                                               \
  };                                                                      \
  char _##op_type##Comment::type[]{#op_type};                             \
  char _##op_type##Comment::equation[]{_equation};                        \
  REGISTER_OPERATOR(                                                      \
      op_type, ::paddle::operators::LogicalOp,                            \
      ::paddle::operators::UnaryLogicalOpProtoMaker<_##op_type##Comment>, \
      ::paddle::operators::UnaryLogicalOpInferShape<_##op_type##Comment>, \
      ::paddle::framework::EmptyGradOpMaker);

REGISTER_BINARY_LOGICAL_OP(logical_and, "$$Out = X \\&\\& Y$$");
REGISTER_BINARY_LOGICAL_KERNEL(logical_and, CPU,
                               paddle::operators::LogicalAndFunctor);
REGISTER_BINARY_LOGICAL_OP(logical_or, "$$Out = X || Y$$");
REGISTER_BINARY_LOGICAL_KERNEL(logical_or, CPU,
                               paddle::operators::LogicalOrFunctor);
REGISTER_UNARY_LOGICAL_OP(logical_not, "$$Out = !X$$");
REGISTER_UNARY_LOGICAL_KERNEL(logical_not, CPU,
                              paddle::operators::LogicalNotFunctor);
REGISTER_BINARY_LOGICAL_OP(logical_xor,
                           "$$Out = (X || Y) \\&\\& !(X \\&\\& Y)$$");
REGISTER_BINARY_LOGICAL_KERNEL(logical_xor, CPU,
                               paddle::operators::LogicalXorFunctor);
<|endoftext|>


<commit_before>#include "sellpopup.h"
#include "ui_sellpopup.h"
#include <list>

Sellpopup::Sellpopup(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Sellpopup)
{
    ui->setupUi(this);
    layout = new QVBoxLayout(ui->scrollAreaWidgetContents);

    /*
    Player* player = new Player(new QGameItem(), 1);

    std::list<Block*> block_list = player->getBlocks();
    block_num = block_list.size();
    blocks = new SubjectBlock*[block_num];
    checks = new QCheckBox*[block_num];

    int index = 0;
    for(std::list<Block*>::iterator itor = block_list.begin(); itor != block_list.end(); itor++) {
        blocks[index] = (SubjectBlock*)*itor;
        index++;
    }

    for(int i=0; i < block_num; i++) {
        QString string = "Test";

        // append department
        string +=  convertDept(blocks[i]->getDept());

        string += " - ";

        // append Subject name
        string += blocks[i]->getName();

        string += " - ";

        // append grade
        string += convertGrade(blocks[i]->getGrade());

        QCheckBox* newCheck = new QCheckBox();
        newCheck->setText(string);

        checks[i] = newCheck;
        layout->addWidget(newCheck);
    }
    */

    // for test use
    block_num = 10;

    for(int i=0; i < 10; i++) {
        QString string = "Test";

        QCheckBox* newCheck = new QCheckBox();
        newCheck->setText(string);

        checks[i] = newCheck;
        layout->addWidget(newCheck);
    }
    // test end

    // connect
    connect(ui->sellButton, SIGNAL(clicked()), this, SLOT(sell()));
    connect(ui->cancelButton, SIGNAL(clicked()), this, SLOT(close()));
    connect(ui->bankruptButton, SIGNAL(clicked()), this, SLOT(bankrupt()));

}

Sellpopup::~Sellpopup()
{
    delete ui;
}

QString Sellpopup::convertDept(SubjectType::Type type)
{
    QString dept = "";

    switch(type) {
        using namespace SubjectType;
        case CSED:
            dept += "컴공과";
            break;
        case ME:
            dept += "기계과";
            break;
        case MATH:
            dept += "수학과";
            break;
        case EE:
            dept += "전자과";
            break;
        case PHYS:
            dept += "물리과";
            break;
        case BIO:
            dept += "생명과";
            break;
        case CHEM:
            dept += "화학과";
            break;
        case IME:
            dept += "산경과";
            break;
    }

    return dept;
}

QString Sellpopup::convertGrade(int grade)
{
    QString str = "";

    switch(grade) {
        case 2:
            str += "C";
            break;
        case 3:
            str += "B";
            break;
        case 4:
            str += "A";
            break;
    }

    return str;
}

void Sellpopup::sell()
{
    /*
    for(int i=0; i<block_num; i++) {
        if(checks[i]->isChecked())
            player->sellBlock(blocks[i]);
    }
    */
}
<commit_msg>slot 완성<commit_after>#include "sellpopup.h"
#include "ui_sellpopup.h"
#include <list>

Sellpopup::Sellpopup(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Sellpopup)
{
    ui->setupUi(this);
    layout = new QVBoxLayout(ui->scrollAreaWidgetContents);

    /*
    Player* player = new Player(new QGameItem(), 1);

    std::list<Block*> block_list = player->getBlocks();
    block_num = block_list.size();
    blocks = new SubjectBlock*[block_num];
    checks = new QCheckBox*[block_num];

    int index = 0;
    for(std::list<Block*>::iterator itor = block_list.begin(); itor != block_list.end(); itor++) {
        blocks[index] = (SubjectBlock*)*itor;
        index++;
    }

    for(int i=0; i < block_num; i++) {
        QString string = "Test";

        // append department
        string +=  convertDept(blocks[i]->getDept());

        string += " - ";

        // append Subject name
        string += blocks[i]->getName();

        string += " - ";

        // append grade
        string += convertGrade(blocks[i]->getGrade());

        QCheckBox* newCheck = new QCheckBox();
        newCheck->setText(string);

        checks[i] = newCheck;
        layout->addWidget(newCheck);
    }
    */

    // for test use
    block_num = 10;

    for(int i=0; i < 10; i++) {
        QString string = "Test";

        QCheckBox* newCheck = new QCheckBox();
        newCheck->setText(string);

        checks[i] = newCheck;
        layout->addWidget(newCheck);
    }
    // test end

    // connect
    connect(ui->sellButton, SIGNAL(clicked()), this, SLOT(sell()));
    connect(ui->cancelButton, SIGNAL(clicked()), this, SLOT(close()));
    connect(ui->bankruptButton, SIGNAL(clicked()), this, SLOT(bankrupt()));

}

Sellpopup::~Sellpopup()
{
    delete ui;
}

QString Sellpopup::convertDept(SubjectType::Type type)
{
    QString dept = "";

    switch(type) {
        using namespace SubjectType;
        case CSED:
            dept += "컴공과";
            break;
        case ME:
            dept += "기계과";
            break;
        case MATH:
            dept += "수학과";
            break;
        case EE:
            dept += "전자과";
            break;
        case PHYS:
            dept += "물리과";
            break;
        case BIO:
            dept += "생명과";
            break;
        case CHEM:
            dept += "화학과";
            break;
        case IME:
            dept += "산경과";
            break;
    }

    return dept;
}

QString Sellpopup::convertGrade(int grade)
{
    QString str = "";

    switch(grade) {
        case 2:
            str += "C";
            break;
        case 3:
            str += "B";
            break;
        case 4:
            str += "A";
            break;
    }

    return str;
}

void Sellpopup::sell()
{
    qDebug() << "Selling Block!";

    /*
    for(int i=0; i<block_num; i++) {
        if(checks[i]->isChecked())
            player->sellBlock(blocks[i]);
    }
    */

}

void Sellpopup::bankrupt()
{
    qDebug() << "Player " << player->getId() << "bankrupted!";

    //player->setBankrupt();
}
<|endoftext|>


<commit_before>#include <iostream>
#include <sqlite3.h>
#include <string>
#include <cstring>
#include <map>
#include <sstream>
#include "ReadGzip.h"
using namespace std;
#include "MBTileReader.h"
#include "vector_tile20/vector_tile.pb.h"

#include <string>
#include <sstream>
#include <vector>

using namespace std;

// http://stackoverflow.com/a/236803/4288232
void strsplit(const string &s, char delim, vector<string> &elems) {
    stringstream ss(s);
    string item;
    while (getline(ss, item, delim)) {
        elems.push_back(item);
    }
}

string FeatureTypeToStr(::vector_tile::Tile_GeomType type)
{
	if(type == ::vector_tile::Tile_GeomType_UNKNOWN)
		return "Unknown";
	if(type == ::vector_tile::Tile_GeomType_POINT)
		return "Point";
	if(type == ::vector_tile::Tile_GeomType_LINESTRING)
		return "LineString";
	if(type == ::vector_tile::Tile_GeomType_POLYGON)
		return "Polygon";
	return "Unknown type";
}

string ValueToStr(const ::vector_tile::Tile_Value &value)
{
	if(value.has_string_value())
		return value.string_value();
	if(value.has_float_value())
	{
		stringstream ss;
		ss << value.float_value();
		return ss.str();
	}
	if(value.has_double_value())
	{
		stringstream ss;
		ss << value.double_value();
		return ss.str();
	}
	if(value.has_int_value())
	{
		stringstream ss;
		ss << value.int_value();
		return ss.str();
	}
	if(value.has_uint_value())
	{
		stringstream ss;
		ss << value.uint_value();
		return ss.str();
	}
	if(value.has_sint_value())
	{
		stringstream ss;
		ss << value.sint_value();
		return ss.str();
	}
	if(value.has_bool_value())
	{
		stringstream ss;
		ss << value.bool_value();
		return ss.str();
	}
	return "Error: Unknown value type";
}

void DecodeGeometry(const ::vector_tile::Tile_Feature &feature)
{
	int cursorx = 0, cursory = 0;
	for(int i=0; i < feature.geometry_size(); i ++)
	{
		unsigned g = feature.geometry(i);
		unsigned cmdId = g & 0x7;
		unsigned cmdCount = g >> 3;
		if(cmdId == 1)//MoveTo
		{
			for(int j=0; j < cmdCount; j++)
			{
				unsigned v = feature.geometry(i+1);
				int value1 = ((v >> 1) ^ (-(v & 1)));
				v = feature.geometry(i+2);
				int value2 = ((v >> 1) ^ (-(v & 1)));
				cursorx += value1;
				cursory += value2;
				cout << "MoveTo " << cursorx << "," << cursory << endl;
				i += 2;
			}
		}
		if(cmdId == 2)//LineTo
		{
			for(int j=0; j < cmdCount; j++)
			{
				unsigned v = feature.geometry(i+1);
				int value1 = ((v >> 1) ^ (-(v & 1)));
				v = feature.geometry(i+2);
				int value2 = ((v >> 1) ^ (-(v & 1)));
				cursorx += value1;
				cursory += value2;
				cout << "LineTo " << cursorx << "," << cursory << endl;
				i += 2;
			}
		}
		if(cmdId == 7) //ClosePath
		{
			for(int j=0; j < cmdCount; j++)
			{
				cout << "ClosePath" << endl;
			}
		}

	}
}

int main(int argc, char **argv)
{
	class MBTileReader mbTileReader("cairo_egypt.mbtiles");

	cout << "name:" << mbTileReader.GetMetadata("name") << endl;
	cout << "type:" << mbTileReader.GetMetadata("type") << endl;
	string version = mbTileReader.GetMetadata("version");
	cout << "version:" << version << endl;
	vector<string> versionSplit;
	strsplit(version, '.', versionSplit);
	vector<int> versionInts;
	for (int i=0;i<versionSplit.size();i++) versionInts.push_back(atoi(versionSplit[i].c_str()));
	cout << "description:" << mbTileReader.GetMetadata("description") << endl;
	string format = mbTileReader.GetMetadata("format");
	cout << "format:" << format << endl;
	cout << "bounds:" << mbTileReader.GetMetadata("bounds") << endl;

	if(0) //Get metadata fields
	{
		std::vector<std::string> fieldNames;
		mbTileReader.GetMetadataFields(fieldNames);
		for(unsigned i=0;i<fieldNames.size();i++) cout << fieldNames[i] << endl;
	}

	if(0) //Get list of tiles
	{
		TileInfoRows tileInfoRows;
		mbTileReader.ListTiles(tileInfoRows);
		for(unsigned i=0;i < tileInfoRows.size(); i++)
		{
			for(size_t j=0; j < tileInfoRows[i].size(); j++)
				cout << tileInfoRows[i][j] << ",";
			cout << endl;
		}
	}

	string blob;
	mbTileReader.GetTile(14,9618,9611,blob);

	if(format == "pbf" && versionInts[0] == 2)
	{
		std::stringbuf buff;
		buff.sputn(blob.c_str(), blob.size());
		DecodeGzip dec(buff);

		string tileData;

		char tmp[1024];
		while(dec.in_avail())
		{
			streamsize bytes = dec.sgetn(tmp, 1024);
			tileData.append(tmp, bytes);
		}

		vector_tile::Tile tile;
		cout << "ParseFromString: " << tile.ParseFromString(tileData) << endl;
		cout << "Num layers: " << tile.layers_size() << endl;

		for(int layerNum = 0; layerNum < tile.layers_size(); layerNum++)
		{
			const ::vector_tile::Tile_Layer &layer = tile.layers(layerNum);
			cout << "layer version: " << layer.version() << endl;
			cout << "layer name: " << layer.name() << endl;
			cout << "layer extent: " << layer.extent() << endl;
			cout << "layer keys_size(): " << layer.keys_size() << endl;
			cout << "layer values_size(): " << layer.values_size() << endl;
			cout << "layer features_size(): " << layer.features_size() << endl;

			for(int featureNum = 0; featureNum < layer.features_size(); featureNum++)
			{
				const ::vector_tile::Tile_Feature &feature =layer.features(featureNum);
				cout << featureNum << "," << feature.type() << "," << FeatureTypeToStr(feature.type());
				if(feature.has_id())
					cout << ",id=" << feature.id();
				cout << endl;
				for(int tagNum = 0; tagNum < feature.tags_size(); tagNum+=2)
				{
					cout << layer.keys(feature.tags(tagNum)) << "=";
					const ::vector_tile::Tile_Value &value = layer.values(feature.tags(tagNum+1));
					cout << ValueToStr(value) << endl;
				}
				DecodeGeometry(feature);
			}
		}

	}
}

<commit_msg>Decode geometry to lat lon<commit_after>#include <iostream>
#include <sqlite3.h>
#include <string>
#include <cstring>
#include <map>
#include <sstream>
#include "ReadGzip.h"
using namespace std;
#include "MBTileReader.h"
#include "vector_tile20/vector_tile.pb.h"
#include <math.h>
#include <string>
#include <sstream>
#include <vector>

using namespace std;

// http://stackoverflow.com/a/236803/4288232
void strsplit(const string &s, char delim, vector<string> &elems) {
    stringstream ss(s);
    string item;
    while (getline(ss, item, delim)) {
        elems.push_back(item);
    }
}

string FeatureTypeToStr(::vector_tile::Tile_GeomType type)
{
	if(type == ::vector_tile::Tile_GeomType_UNKNOWN)
		return "Unknown";
	if(type == ::vector_tile::Tile_GeomType_POINT)
		return "Point";
	if(type == ::vector_tile::Tile_GeomType_LINESTRING)
		return "LineString";
	if(type == ::vector_tile::Tile_GeomType_POLYGON)
		return "Polygon";
	return "Unknown type";
}

string ValueToStr(const ::vector_tile::Tile_Value &value)
{
	if(value.has_string_value())
		return value.string_value();
	if(value.has_float_value())
	{
		stringstream ss;
		ss << value.float_value();
		return ss.str();
	}
	if(value.has_double_value())
	{
		stringstream ss;
		ss << value.double_value();
		return ss.str();
	}
	if(value.has_int_value())
	{
		stringstream ss;
		ss << value.int_value();
		return ss.str();
	}
	if(value.has_uint_value())
	{
		stringstream ss;
		ss << value.uint_value();
		return ss.str();
	}
	if(value.has_sint_value())
	{
		stringstream ss;
		ss << value.sint_value();
		return ss.str();
	}
	if(value.has_bool_value())
	{
		stringstream ss;
		ss << value.bool_value();
		return ss.str();
	}
	return "Error: Unknown value type";
}

void DecodeGeometry(const ::vector_tile::Tile_Feature &feature,
	int extent, int tileZoom, int tileColumn, int tileRow)
{
	long unsigned int numTiles = pow(2,tileZoom);
	double lonMin = tilex2long(tileColumn, tileZoom);
	double latMin = tiley2lat(numTiles-tileRow, tileZoom);//Why is latitude no where near expected?
	double lonMax = tilex2long(tileColumn+1, tileZoom);
	double latMax = tiley2lat(numTiles-tileRow-1, tileZoom);
	double dLat = latMax - latMin;
	double dLon = lonMax - lonMin;

	int cursorx = 0, cursory = 0;
	for(int i=0; i < feature.geometry_size(); i ++)
	{
		unsigned g = feature.geometry(i);
		unsigned cmdId = g & 0x7;
		unsigned cmdCount = g >> 3;
		if(cmdId == 1)//MoveTo
		{
			for(int j=0; j < cmdCount; j++)
			{
				unsigned v = feature.geometry(i+1);
				int value1 = ((v >> 1) ^ (-(v & 1)));
				v = feature.geometry(i+2);
				int value2 = ((v >> 1) ^ (-(v & 1)));
				cursorx += value1;
				cursory += value2;
				double px = dLon * double(cursorx) / double(extent) + lonMin;
				double py = - dLat * double(cursory) / double(extent) + latMax;
				cout << "MoveTo " << cursorx << "," << cursory << ",(" << px << "," << py << ")" << endl;
				i += 2;
			}
		}
		if(cmdId == 2)//LineTo
		{
			for(int j=0; j < cmdCount; j++)
			{
				unsigned v = feature.geometry(i+1);
				int value1 = ((v >> 1) ^ (-(v & 1)));
				v = feature.geometry(i+2);
				int value2 = ((v >> 1) ^ (-(v & 1)));
				cursorx += value1;
				cursory += value2;
				double px = dLon * double(cursorx) / double(extent) + lonMin;
				double py = - dLat * double(cursory) / double(extent) + latMax;
				cout << "LineTo " << cursorx << "," << cursory << ",(" << px << "," << py << ")" << endl;
				i += 2;
			}
		}
		if(cmdId == 7) //ClosePath
		{
			for(int j=0; j < cmdCount; j++)
			{
				cout << "ClosePath" << endl;
			}
		}

	}
}

int main(int argc, char **argv)
{
	class MBTileReader mbTileReader("cairo_egypt.mbtiles");

	cout << "name:" << mbTileReader.GetMetadata("name") << endl;
	cout << "type:" << mbTileReader.GetMetadata("type") << endl;
	string version = mbTileReader.GetMetadata("version");
	cout << "version:" << version << endl;
	vector<string> versionSplit;
	strsplit(version, '.', versionSplit);
	vector<int> versionInts;
	for (int i=0;i<versionSplit.size();i++) versionInts.push_back(atoi(versionSplit[i].c_str()));
	cout << "description:" << mbTileReader.GetMetadata("description") << endl;
	string format = mbTileReader.GetMetadata("format");
	cout << "format:" << format << endl;
	cout << "bounds:" << mbTileReader.GetMetadata("bounds") << endl;

	if(0) //Get metadata fields
	{
		std::vector<std::string> fieldNames;
		mbTileReader.GetMetadataFields(fieldNames);
		for(unsigned i=0;i<fieldNames.size();i++) cout << fieldNames[i] << endl;
	}

	if(0) //Get list of tiles
	{
		TileInfoRows tileInfoRows;
		mbTileReader.ListTiles(tileInfoRows);
		for(unsigned i=0;i < tileInfoRows.size(); i++)
		{
			for(size_t j=0; j < tileInfoRows[i].size(); j++)
				cout << tileInfoRows[i][j] << ",";
			cout << endl;
		}
	}

	string blob;
	int tileZoom = 14;
	int tileColumn = 9618;
	int tileRow = 9611;
	mbTileReader.GetTile(tileZoom, tileColumn, tileRow, blob);

	if(format == "pbf" && versionInts[0] == 2)
	{
		std::stringbuf buff;
		buff.sputn(blob.c_str(), blob.size());
		DecodeGzip dec(buff);

		string tileData;

		char tmp[1024];
		while(dec.in_avail())
		{
			streamsize bytes = dec.sgetn(tmp, 1024);
			tileData.append(tmp, bytes);
		}

		vector_tile::Tile tile;
		cout << "ParseFromString: " << tile.ParseFromString(tileData) << endl;
		cout << "Num layers: " << tile.layers_size() << endl;

		for(int layerNum = 0; layerNum < tile.layers_size(); layerNum++)
		{
			const ::vector_tile::Tile_Layer &layer = tile.layers(layerNum);
			cout << "layer version: " << layer.version() << endl;
			cout << "layer name: " << layer.name() << endl;
			cout << "layer extent: " << layer.extent() << endl;
			cout << "layer keys_size(): " << layer.keys_size() << endl;
			cout << "layer values_size(): " << layer.values_size() << endl;
			cout << "layer features_size(): " << layer.features_size() << endl;

			//The spec says "Decoders SHOULD parse the version first to ensure that
			//they are capable of decoding each layer." This has not been implemented.

			for(int featureNum = 0; featureNum < layer.features_size(); featureNum++)
			{
				const ::vector_tile::Tile_Feature &feature =layer.features(featureNum);
				cout << featureNum << "," << feature.type() << "," << FeatureTypeToStr(feature.type());
				if(feature.has_id())
					cout << ",id=" << feature.id();
				cout << endl;
				for(int tagNum = 0; tagNum < feature.tags_size(); tagNum+=2)
				{
					cout << layer.keys(feature.tags(tagNum)) << "=";
					const ::vector_tile::Tile_Value &value = layer.values(feature.tags(tagNum+1));
					cout << ValueToStr(value) << endl;
				}
				DecodeGeometry(feature, layer.extent(), tileZoom, tileColumn, tileRow);
			}
		}
	}
}

<|endoftext|>


<commit_before>/*

This file is part of VROOM.

Copyright (c) 2015-2022, Julien Coupey.
All rights reserved (see LICENSE).

*/

#include "problems/vrptw/operators/pd_shift.h"
#include "utils/helpers.h"

namespace vroom {
namespace vrptw {

PDShift::PDShift(const Input& input,
                 const utils::SolutionState& sol_state,
                 TWRoute& tw_s_route,
                 Index s_vehicle,
                 Index s_p_rank,
                 Index s_d_rank,
                 TWRoute& tw_t_route,
                 Index t_vehicle,
                 Gain gain_threshold)
  : cvrp::PDShift(input,
                  sol_state,
                  static_cast<RawRoute&>(tw_s_route),
                  s_vehicle,
                  s_p_rank,
                  s_d_rank,
                  static_cast<RawRoute&>(tw_t_route),
                  t_vehicle,
                  gain_threshold),
    _is_valid_removal(true),
    _source_without_pd(s_route.begin() + _s_p_rank + 1,
                       s_route.begin() + _s_d_rank),
    _tw_s_route(tw_s_route),
    _tw_t_route(tw_t_route) {
}

void PDShift::compute_gain() {
  // Check for valid removal wrt TW constraints.
  if (_s_d_rank == _s_p_rank + 1) {
    _is_valid_removal =
      _is_valid_removal && _tw_s_route.is_valid_removal(_input, _s_p_rank, 2);
  } else {
    _is_valid_removal =
      _is_valid_removal &&
      _tw_s_route.is_valid_addition_for_tw(_input,
                                           _source_without_pd.begin(),
                                           _source_without_pd.end(),
                                           _s_p_rank,
                                           _s_d_rank + 1);
  }
  if (!_is_valid_removal) {
    return;
  }

  const auto& v = _input.vehicles[t_vehicle];

  // For source vehicle, we consider the cost of removing P&D already
  // stored in remove_gain.

  // For target vehicle, we go through all insertion options for
  // pickup and delivery target ranks, storing best ranks along the
  // way.

  std::vector<Gain> t_d_gains(t_route.size() + 1);
  std::vector<unsigned char> valid_delivery_insertions(t_route.size() + 1);

  for (unsigned t_d_rank = 0; t_d_rank <= t_route.size(); ++t_d_rank) {
    t_d_gains[t_d_rank] =
      -utils::addition_cost(_input, s_route[_s_d_rank], v, t_route, t_d_rank);
    valid_delivery_insertions[t_d_rank] =
      target.is_valid_addition_for_tw(_input, s_route[_s_d_rank], t_d_rank);
  }

  for (unsigned t_p_rank = 0; t_p_rank <= t_route.size(); ++t_p_rank) {
    Gain t_p_gain =
      -utils::addition_cost(_input, s_route[_s_p_rank], v, t_route, t_p_rank);

    if (_remove_gain + t_p_gain < stored_gain) {
      // Even without delivery insertion, the gain is lower than best
      // known stored gain.
      continue;
    }

    if (!target
           .is_valid_addition_for_load(_input,
                                       _input.jobs[s_route[_s_p_rank]].pickup,
                                       t_p_rank) or
        !target.is_valid_addition_for_tw(_input,
                                         s_route[_s_p_rank],
                                         t_p_rank)) {
      continue;
    }

    std::vector<Index> modified_with_pd({s_route[_s_p_rank]});
    Amount modified_delivery = _input.zero_amount();

    for (unsigned t_d_rank = t_p_rank; t_d_rank <= t_route.size(); ++t_d_rank) {
      // Update state variables along the way before potential early
      // abort.
      if (t_p_rank < t_d_rank) {
        modified_with_pd.push_back(t_route[t_d_rank - 1]);
        const auto& new_modified_job = _input.jobs[t_route[t_d_rank - 1]];
        if (new_modified_job.type == JOB_TYPE::SINGLE) {
          modified_delivery += new_modified_job.delivery;
        }
      }

      if (!(bool)valid_delivery_insertions[t_d_rank]) {
        continue;
      }

      Gain target_gain;
      if (t_p_rank == t_d_rank) {
        target_gain = -utils::addition_cost(_input,
                                            s_route[_s_p_rank],
                                            v,
                                            t_route,
                                            t_p_rank,
                                            t_p_rank + 1);
      } else {
        target_gain = t_p_gain + t_d_gains[t_d_rank];
      }

      if (_remove_gain + target_gain > stored_gain) {
        modified_with_pd.push_back(s_route[_s_d_rank]);
        bool valid =
          target
            .is_valid_addition_for_capacity_inclusion(_input,
                                                      modified_delivery,
                                                      modified_with_pd.begin(),
                                                      modified_with_pd.end(),
                                                      t_p_rank,
                                                      t_d_rank);
        valid = valid &&
                _tw_t_route.is_valid_addition_for_tw(_input,
                                                     modified_with_pd.begin(),
                                                     modified_with_pd.end(),
                                                     t_p_rank,
                                                     t_d_rank);

        // Checking for removal validity is like checking insertion of
        // source portion without P&D in place.
        valid =
          valid &&
          _tw_s_route.is_valid_addition_for_tw(_input,
                                               s_route.begin() + _s_p_rank + 1,
                                               s_route.begin() + _s_d_rank,
                                               _s_p_rank,
                                               _s_d_rank + 1);

        modified_with_pd.pop_back();

        if (valid) {
          _valid = true;
          stored_gain = _remove_gain + target_gain;
          _best_t_p_rank = t_p_rank;
          _best_t_d_rank = t_d_rank;
        }
      }
    }
  }

  gain_computed = true;
}

void PDShift::apply() {
  std::vector<Index> target_with_pd({s_route[_s_p_rank]});
  std::copy(t_route.begin() + _best_t_p_rank,
            t_route.begin() + _best_t_d_rank,
            std::back_inserter(target_with_pd));
  target_with_pd.push_back(s_route[_s_d_rank]);

  _tw_t_route.replace(_input,
                      target_with_pd.begin(),
                      target_with_pd.end(),
                      _best_t_p_rank,
                      _best_t_d_rank);

  if (_s_d_rank == _s_p_rank + 1) {
    _tw_s_route.remove(_input, _s_p_rank, 2);
  } else {
    std::vector<Index> source_without_pd(s_route.begin() + _s_p_rank + 1,
                                         s_route.begin() + _s_d_rank);

    _tw_s_route.replace(_input,
                        _source_without_pd.begin(),
                        _source_without_pd.end(),
                        _s_p_rank,
                        _s_d_rank + 1);
  }
}

} // namespace vrptw
} // namespace vroom
<commit_msg>Remove unneccessary check<commit_after>/*

This file is part of VROOM.

Copyright (c) 2015-2022, Julien Coupey.
All rights reserved (see LICENSE).

*/

#include "problems/vrptw/operators/pd_shift.h"
#include "utils/helpers.h"

namespace vroom {
namespace vrptw {

PDShift::PDShift(const Input& input,
                 const utils::SolutionState& sol_state,
                 TWRoute& tw_s_route,
                 Index s_vehicle,
                 Index s_p_rank,
                 Index s_d_rank,
                 TWRoute& tw_t_route,
                 Index t_vehicle,
                 Gain gain_threshold)
  : cvrp::PDShift(input,
                  sol_state,
                  static_cast<RawRoute&>(tw_s_route),
                  s_vehicle,
                  s_p_rank,
                  s_d_rank,
                  static_cast<RawRoute&>(tw_t_route),
                  t_vehicle,
                  gain_threshold),
    _is_valid_removal(true),
    _source_without_pd(s_route.begin() + _s_p_rank + 1,
                       s_route.begin() + _s_d_rank),
    _tw_s_route(tw_s_route),
    _tw_t_route(tw_t_route) {
}

void PDShift::compute_gain() {
  // Check for valid removal wrt TW constraints.
  if (_s_d_rank == _s_p_rank + 1) {
    _is_valid_removal =
      _is_valid_removal && _tw_s_route.is_valid_removal(_input, _s_p_rank, 2);
  } else {
    _is_valid_removal =
      _is_valid_removal &&
      _tw_s_route.is_valid_addition_for_tw(_input,
                                           _source_without_pd.begin(),
                                           _source_without_pd.end(),
                                           _s_p_rank,
                                           _s_d_rank + 1);
  }
  if (!_is_valid_removal) {
    return;
  }

  const auto& v = _input.vehicles[t_vehicle];

  // For source vehicle, we consider the cost of removing P&D already
  // stored in remove_gain.

  // For target vehicle, we go through all insertion options for
  // pickup and delivery target ranks, storing best ranks along the
  // way.

  std::vector<Gain> t_d_gains(t_route.size() + 1);
  std::vector<unsigned char> valid_delivery_insertions(t_route.size() + 1);

  for (unsigned t_d_rank = 0; t_d_rank <= t_route.size(); ++t_d_rank) {
    t_d_gains[t_d_rank] =
      -utils::addition_cost(_input, s_route[_s_d_rank], v, t_route, t_d_rank);
    valid_delivery_insertions[t_d_rank] =
      target.is_valid_addition_for_tw(_input, s_route[_s_d_rank], t_d_rank);
  }

  for (unsigned t_p_rank = 0; t_p_rank <= t_route.size(); ++t_p_rank) {
    Gain t_p_gain =
      -utils::addition_cost(_input, s_route[_s_p_rank], v, t_route, t_p_rank);

    if (_remove_gain + t_p_gain < stored_gain) {
      // Even without delivery insertion, the gain is lower than best
      // known stored gain.
      continue;
    }

    if (!target
           .is_valid_addition_for_load(_input,
                                       _input.jobs[s_route[_s_p_rank]].pickup,
                                       t_p_rank) or
        !target.is_valid_addition_for_tw(_input,
                                         s_route[_s_p_rank],
                                         t_p_rank)) {
      continue;
    }

    std::vector<Index> modified_with_pd({s_route[_s_p_rank]});
    Amount modified_delivery = _input.zero_amount();

    for (unsigned t_d_rank = t_p_rank; t_d_rank <= t_route.size(); ++t_d_rank) {
      // Update state variables along the way before potential early
      // abort.
      if (t_p_rank < t_d_rank) {
        modified_with_pd.push_back(t_route[t_d_rank - 1]);
        const auto& new_modified_job = _input.jobs[t_route[t_d_rank - 1]];
        if (new_modified_job.type == JOB_TYPE::SINGLE) {
          modified_delivery += new_modified_job.delivery;
        }
      }

      if (!(bool)valid_delivery_insertions[t_d_rank]) {
        continue;
      }

      Gain target_gain;
      if (t_p_rank == t_d_rank) {
        target_gain = -utils::addition_cost(_input,
                                            s_route[_s_p_rank],
                                            v,
                                            t_route,
                                            t_p_rank,
                                            t_p_rank + 1);
      } else {
        target_gain = t_p_gain + t_d_gains[t_d_rank];
      }

      if (_remove_gain + target_gain > stored_gain) {
        modified_with_pd.push_back(s_route[_s_d_rank]);
        bool valid =
          target
            .is_valid_addition_for_capacity_inclusion(_input,
                                                      modified_delivery,
                                                      modified_with_pd.begin(),
                                                      modified_with_pd.end(),
                                                      t_p_rank,
                                                      t_d_rank);
        valid = valid &&
                _tw_t_route.is_valid_addition_for_tw(_input,
                                                     modified_with_pd.begin(),
                                                     modified_with_pd.end(),
                                                     t_p_rank,
                                                     t_d_rank);

        modified_with_pd.pop_back();

        if (valid) {
          _valid = true;
          stored_gain = _remove_gain + target_gain;
          _best_t_p_rank = t_p_rank;
          _best_t_d_rank = t_d_rank;
        }
      }
    }
  }

  gain_computed = true;
}

void PDShift::apply() {
  std::vector<Index> target_with_pd({s_route[_s_p_rank]});
  std::copy(t_route.begin() + _best_t_p_rank,
            t_route.begin() + _best_t_d_rank,
            std::back_inserter(target_with_pd));
  target_with_pd.push_back(s_route[_s_d_rank]);

  _tw_t_route.replace(_input,
                      target_with_pd.begin(),
                      target_with_pd.end(),
                      _best_t_p_rank,
                      _best_t_d_rank);

  if (_s_d_rank == _s_p_rank + 1) {
    _tw_s_route.remove(_input, _s_p_rank, 2);
  } else {
    _tw_s_route.replace(_input,
                        _source_without_pd.begin(),
                        _source_without_pd.end(),
                        _s_p_rank,
                        _s_d_rank + 1);
  }
}

} // namespace vrptw
} // namespace vroom
<|endoftext|>


<commit_before>
/* tests/test-getentry.C
 * Copyright (C) 2002 Bradford Hovinen
 *
 * Written by Bradford Hovinen <hovinen@cis.udel.edu>
 *
 * --------------------------------------------------------
 *
 *
 * ========LICENCE========
 * This file is part of the library LinBox.
 *
 * LinBox is free software: you can redistribute it and/or modify
 * it under the terms of the  GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 * ========LICENCE========
 *
 */

/*! @file  tests/test-getentry.C
 * @ingroup tests
 * @brief  no doc
 * @test NO DOC
 */

#include "linbox/linbox-config.h"

#include <iostream>
#include <fstream>

#include <cstdio>

#include "test-common.h"

#include "linbox/util/commentator.h"
#include "linbox/field/modular.h"
#include "linbox/solutions/getentry.h"
#include "linbox/blackbox/compose.h"
#include "linbox/blackbox/diagonal.h"
#include "linbox/blackbox/scalar-matrix.h"
#include "linbox/blackbox/sparse.h"
#include "linbox/vector/stream.h"

using namespace LinBox;

/* getEntry of generic blackbox matrix */
template <class Field>
bool testGenericBBgetEntry (const Field &F, size_t n)
{
	bool ret = true;
    typename Field::Element s, x, z;
	ostream &report = commentator().report (Commentator::LEVEL_IMPORTANT, INTERNAL_DESCRIPTION);
	F.init(x, 0);
	F.init(s, 2);
	F.init(z, 0);
	ScalarMatrix<Field> B(F, n, s);
	SolutionTags::Generic t;
	//getEntry(x, B, 0, n-1, t);
	if (n > 1 && !F.isZero(x)) ret = false;
	getEntry(x, B, 0, 0, t);
	if ( !F.areEqual(s, x)) ret = false;
	if (!ret) report << "testGenericBBgetEntry failure" << std::endl;
	return ret;
}
/* getEntry of scalar matrix */
template <class Field>
bool testScalarMatrixgetEntry (const Field &F, size_t n)
{
	bool ret = true;
	commentator().start ("Testing scalar matrix getEntry", "", 1);
	ostream &report = commentator().report (Commentator::LEVEL_IMPORTANT, INTERNAL_DESCRIPTION);
	report << "scalarmatrix getEntry test (using specialization)" << endl;
    typename Field::Element s, t, r, th;
	F.init(r, 0);
	F.init(s, 2);
	F.init(th, 2);
	ScalarMatrix<Field> B(F, n, s);
	getEntry(t, B, 0, n-1); F.assign(r,t);
		report << "0xn-1" << t << endl;
  	getEntry(t, B, n-1, 0); F.addin(r,t);
		report << "n-1 x  0" << t << endl;
  	getEntry(t, B, 0, 0); F.addin(r,t);
		report << "0 x 0" << t << endl;
  	getEntry(t, B, n-1, n-1); F.addin(r,t);
		report << "n-1 x n-1" << t << endl;
	if (!F.areEqual(t, th)) {
		report << "bad scalar matrix getEntry " << t << ", should be " << th << endl;
		ret= false;
	}
	else ret= true;
	commentator().stop (MSG_STATUS (ret), (const char *) 0, "testScalarMatrixgetEntry");
	return ret;
}

/* getEntry of sparse matrix */
template <class Field>
bool testSparseMatrixgetEntry (const Field &F, size_t n)
{
	commentator().start ("Building sparse matrix", "", 1);
	bool ret = true;
	ostream &report = commentator().report (Commentator::LEVEL_IMPORTANT, INTERNAL_DESCRIPTION);
    	typename Field::Element s, t, th;
	F.init(s, 2);
	size_t m = (n > 10 ? 10 : n);
	F.init(th, 2*m);
	SparseMatrix<Field> B(F, n, n);
	for (size_t i = 0; i <  m; ++i)
		for (size_t j = 0; j < m; ++j)
			B.setEntry(i,j,s);
	commentator().stop ("", "done");
	commentator().start ("Testing sparse matrix getEntry", "", 1);
	report << "sparse matrix getEntry test (using specialization)" << endl;
        ret = true;
	getEntry(t, B, 0, 0);
	if (!F.areEqual(t, s)) {
	report << "bad sparse matrix getEntry 1,1 " << t << ", should be " << s << endl;

		ret = false;
	}
	getEntry(t, B, 0, n-1);
	if (!F.areEqual(t, s)) {
	report << "bad sparse matrix getEntry 1,n" << t << ", should be " << s << endl;

		ret = false;
	}
	getEntry(t, B, n-1, 0);
	if (!F.areEqual(t, s)) {
	report << "bad sparse matrix getEntry n,1" << t << ", should be " << s << endl;

		ret = false;
	}
	getEntry(t, B, n-1, n-1);
	if (!F.areEqual(t, s)) {
	report << "bad sparse matrix getEntry n,n" << t << ", should be " << s << endl;

		ret = false;
	}
	commentator().stop (MSG_STATUS (ret), (const char *) 0, "testSparseMatrixgetEntry");
	return ret;
}

/* getEntry of dense matrix */
template <class Field>
static bool testDenseMatrixgetEntry (const Field &F, size_t n)
{
	bool ret = true;
    	typename Field::Element s, t, th;
	F.init(s, 2);
	size_t m = (n > 10 ? 10 : n);
	F.init(th, 2*m);
	BlasMatrix<Field> B(F, n, n);
	for (size_t i = 0; i <  m; ++i)
		for (size_t j = 0; j < n; ++j)
			B.setEntry(i, j, s);
	commentator().start ("Testing dense matrix getEntry", "", 1);
	ostream &report = commentator().report (Commentator::LEVEL_IMPORTANT, INTERNAL_DESCRIPTION);
	report << "dense matrix getEntry test (using specialization)" << endl;
        ret = true;
        getEntry(t, B, 0, 0);
	if (!F.areEqual(t, s)) {
		report << "bad dense matrix getEntry 1,1 " << t << ", should be " << s << endl;

		ret = false;
	}
        getEntry(t, B, 0, n-1);
	if (!F.areEqual(t, s)) {
		report << "bad dense matrix getEntry 1,n " << t << ", should be " << s << endl;

		ret = false;
	}
        getEntry(t, B, n-1, 0);
	if (!F.areEqual(t, s)) {
		report << "bad dense matrix getEntry n,1 " << t << ", should be " << s << endl;

		ret = false;
	}
        getEntry(t, B, n-1, n-1);
	if (!F.areEqual(t, s)) {
		report << "bad dense matrix getEntry n,n " << t << ", should be " << s << endl;

		ret = false;
	}
	commentator().stop (MSG_STATUS (ret), (const char *) 0, "testDenseMatrixgetEntry");
	return ret;
}

/* getEntry of diagonal matrix */
template <class Field>
static bool testDiagonalgetEntry (const Field &F, VectorStream<vector<typename Field::Element> > &stream)
{
	typedef vector <typename Field::Element> Vector;
	typedef Diagonal <Field> Blackbox;

	commentator().start ("Testing diagonal getEntry", "testDiagonalgetEntry", stream.m ());
	ostream &report = commentator().report (Commentator::LEVEL_IMPORTANT, INTERNAL_DESCRIPTION);

	VectorDomain<Field> VD (F);

	bool ret = true;
	size_t i;

	Vector d;
	typename Field::Element sigma, res, ge;

	VectorWrapper::ensureDim (d, stream.dim ());

	while (stream) {
		commentator().startIteration ((unsigned)stream.j ());

		stream.next (d);

		report << "Input vector:  ";
		VD.write (report, d);
		report << endl;

		F.init (sigma, 0);
		for (i = 0; i < stream.n (); i++)
			F.addin (sigma, VectorWrapper::constRef<Field, Vector> (d, i));

		report << "True getEntry: ";
		F.write (report, sigma);
		report << endl;

		Blackbox D (F, d);

		F.init (res, 0);
		for (i = 0; i < stream.n (); i++)
			F.addin (res, getEntry (ge, D, i, i));
                F.addin(res, getEntry (ge, D, 0,stream.n ()-1));
                F.addin(res, getEntry (ge, D, stream.n ()-1, 0));

		report << "Computed getEntry: ";
		F.write (report, res);
		report << endl;

		if (!F.areEqual (sigma, res)) {
			ret = false;
			report << "ERROR: Computed getEntry is incorrect" << endl;
		}

		commentator().stop ("done");
		commentator().progress ();
	}

	commentator().stop (MSG_STATUS (ret), (const char *) 0, "testDiagonalgetEntry");

	return ret;
}

/* getEntry of composed blackbox with diagonal component*/
template <class Field>
bool testSpecialCDgetEntry (const Field &F, size_t n)
{
	bool ret = true;
	typedef typename Field::Element Elt;
	typedef ScalarMatrix<Field> BB;
	typedef Diagonal<Field> DD;
    Elt s, x, t, u;
	ostream &report = commentator().report (Commentator::LEVEL_IMPORTANT, INTERNAL_DESCRIPTION);
	F.init(x, 0);
	F.init(s, 2);
	F.init(t, 0);
	F.init(u, 0);
	F.mul(u, s, t);
	BB B(F, n, s);
	vector<Elt> d(n, t);
	DD D(F, d);
	Compose<DD, BB> CDB (D, B);
	Compose<BB, DD> CBD (B, D);
	Compose<DD, DD> CDD (D, D);
	getEntry(x, CDB, 0, n-1);
	if (n > 1 && !F.isZero(x)) ret = false;
	getEntry(x, CDB, 0, 0);
	if ( !F.areEqual(u, x)) ret = false;
	getEntry(x, CBD, 0, n-1);
	if (n > 1 && !F.isZero(x)) ret = false;
	getEntry(x, CBD, 0, 0);
	if ( !F.areEqual(u, x)) ret = false;
	getEntry(x, CDD, 0, n-1);
	if (n > 1 && !F.isZero(x)) ret = false;
	getEntry(x, CDD, 0, 0);
	if ( !F.areEqual(F.mul(u,t,t), x)) ret = false;
	if (!ret) report << "testSpecialCDgetEntry failure" << std::endl;
	return ret;
}
int main (int argc, char **argv)
{
	bool pass = true;

	//static size_t n = 256;
	static size_t n = 10;
	static integer q = 101;
	static int iterations = 10;

	static Argument args[] = {
		{ 'n', "-n N", "Set dimension of test matrices to NxN.", TYPE_INT,     &n },
		{ 'q', "-q Q", "Operate over the \"field\" GF(Q) [1].",  TYPE_INTEGER, &q },
		{ 'i', "-i I", "Perform each test for I iterations.",     TYPE_INT,     &iterations },
		END_OF_ARGUMENTS
	};

	typedef Modular<int32_t> Field;
	typedef vector<Field::Element> Vector;

	parseArguments (argc, argv, args);
	Field F (q);

	commentator().getMessageClass (INTERNAL_DESCRIPTION).setMaxDepth (3);
	commentator().start("getEntry solution test suite", "getEntry");

	RandomDenseStream<Field, Vector> stream (F, n, (unsigned int)iterations);

	if (!testGenericBBgetEntry (F, n)) pass = false;
	if (!testScalarMatrixgetEntry (F, n)) pass = false;
	if (!testSparseMatrixgetEntry (F, n)) pass = false;
	if (!testDenseMatrixgetEntry (F, n)) pass = false;
	if (!testDiagonalgetEntry (F, stream)) pass = false;
	if (!testSpecialCDgetEntry (F, n)) pass = false;

	commentator().stop("getEntry solution test suite");
	return pass ? 0 : -1;
}

// vim:sts=8:sw=8:ts=8:noet:sr:cino=>s,f0,{0,g0,(0,:0,t0,+0,=s
// Local Variables:
// mode: C++
// tab-width: 8
// indent-tabs-mode: nil
// c-basic-offset: 8
// End:

<commit_msg>test-getentry<commit_after>
/* tests/test-getentry.C
 * Copyright (C) 2002 Bradford Hovinen
 *
 * Written by Bradford Hovinen <hovinen@cis.udel.edu>
 *
 * --------------------------------------------------------
 *
 *
 * ========LICENCE========
 * This file is part of the library LinBox.
 *
 * LinBox is free software: you can redistribute it and/or modify
 * it under the terms of the  GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 * ========LICENCE========
 *
 */

/*! @file  tests/test-getentry.C
 * @ingroup tests
 * @brief  no doc
 * @test NO DOC
 */

#include "linbox/linbox-config.h"

#include <iostream>
#include <fstream>

#include <cstdio>

#include "test-common.h"

#include "linbox/util/commentator.h"
#include "linbox/field/modular.h"
#include "linbox/solutions/getentry.h"
#include "linbox/blackbox/compose.h"
#include "linbox/blackbox/diagonal.h"
#include "linbox/blackbox/scalar-matrix.h"
#include "linbox/blackbox/sparse.h"
#include "linbox/vector/stream.h"

using namespace LinBox;

/* getEntry of generic blackbox matrix */
template <class Field>
bool testGenericBBgetEntry (const Field &F, size_t n)
{
	bool ret = true;
    typename Field::Element s, x, z;
	ostream &report = commentator().report (Commentator::LEVEL_IMPORTANT, INTERNAL_DESCRIPTION);
	F.init(x, 0);
	F.init(s, 2);
	F.init(z, 0);
	ScalarMatrix<Field> B(F, n, s);
	SolutionTags::Generic t;
	//getEntry(x, B, 0, n-1, t);
	if (n > 1 && !F.isZero(x)) ret = false;
	getEntry(x, B, 0, 0, t);
	if ( !F.areEqual(s, x)) ret = false;
	if (!ret) report << "testGenericBBgetEntry failure" << std::endl;
	return ret;
}
/* getEntry of scalar matrix */
template <class Field>
bool testScalarMatrixgetEntry (const Field &F, size_t n)
{
	bool ret = true;
	commentator().start ("Testing scalar matrix getEntry", "", 1);
	ostream &report = commentator().report (Commentator::LEVEL_IMPORTANT, INTERNAL_DESCRIPTION);
	report << "scalarmatrix getEntry test (using specialization)" << endl;
    typename Field::Element s, t, r, th;
	F.init(r, 0);
	F.init(s, 2);
	F.init(th, 2);
	ScalarMatrix<Field> B(F, n, s);
	getEntry(t, B, 0, n-1); F.assign(r,t);
		report << "0xn-1" << t << endl;
  	getEntry(t, B, n-1, 0); F.addin(r,t);
		report << "n-1 x  0" << t << endl;
  	getEntry(t, B, 0, 0); F.addin(r,t);
		report << "0 x 0" << t << endl;
  	getEntry(t, B, n-1, n-1); F.addin(r,t);
		report << "n-1 x n-1" << t << endl;
	if (!F.areEqual(t, th)) {
		report << "bad scalar matrix getEntry " << t << ", should be " << th << endl;
		ret= false;
	}
	else ret= true;
	commentator().stop (MSG_STATUS (ret), (const char *) 0, "testScalarMatrixgetEntry");
	return ret;
}

/* getEntry of sparse matrix */
template <class Field>
bool testSparseMatrixgetEntry (const Field &F, size_t n)
{
	commentator().start ("Building sparse matrix", "", 1);
	bool ret = true;
	ostream &report = commentator().report (Commentator::LEVEL_IMPORTANT, INTERNAL_DESCRIPTION);
    	typename Field::Element s, t, th;
	F.init(s, 2);
	size_t m = (n > 10 ? 10 : n);
	F.init(th, 2*m);
	SparseMatrix<Field> B(F, n, n);
	for (size_t i = 0; i <  m; ++i)
		for (size_t j = 0; j < m; ++j)
			B.setEntry(i,j,s);
	commentator().stop ("", "done");
	commentator().start ("Testing sparse matrix getEntry", "", 1);
	report << "sparse matrix getEntry test (using specialization)" << endl;
        ret = true;
	getEntry(t, B, 0, 0);
	if (!F.areEqual(t, s)) {
	report << "bad sparse matrix getEntry 1,1 " << t << ", should be " << s << endl;

		ret = false;
	}
	getEntry(t, B, 0, n-1);
	if (!F.areEqual(t, s)) {
	report << "bad sparse matrix getEntry 1,n" << t << ", should be " << s << endl;

		ret = false;
	}
	getEntry(t, B, n-1, 0);
	if (!F.areEqual(t, s)) {
	report << "bad sparse matrix getEntry n,1" << t << ", should be " << s << endl;

		ret = false;
	}
	getEntry(t, B, n-1, n-1);
	if (!F.areEqual(t, s)) {
	report << "bad sparse matrix getEntry n,n" << t << ", should be " << s << endl;

		ret = false;
	}
	commentator().stop (MSG_STATUS (ret), (const char *) 0, "testSparseMatrixgetEntry");
	return ret;
}

/* getEntry of dense matrix */
template <class Field>
static bool testDenseMatrixgetEntry (const Field &F, size_t n)
{
	bool ret = true;
    	typename Field::Element s, t, th;
	F.init(s, 2);
	size_t m = (n > 10 ? 10 : n);
	F.init(th, 2*m);
	BlasMatrix<Field> B(F, n, n);
	for (size_t i = 0; i <  m; ++i)
		for (size_t j = 0; j < n; ++j)
			B.setEntry(i, j, s);
	commentator().start ("Testing dense matrix getEntry", "", 1);
	ostream &report = commentator().report (Commentator::LEVEL_IMPORTANT, INTERNAL_DESCRIPTION);
	report << "dense matrix getEntry test (using specialization)" << endl;
        ret = true;
        getEntry(t, B, 0, 0);
	if (!F.areEqual(t, s)) {
		report << "bad dense matrix getEntry 1,1 " << t << ", should be " << s << endl;

		ret = false;
	}
        getEntry(t, B, 0, n-1);
	if (!F.areEqual(t, s)) {
		report << "bad dense matrix getEntry 1,n " << t << ", should be " << s << endl;

		ret = false;
	}
        getEntry(t, B, n-1, 0);
	if (!F.areEqual(t, s)) {
		report << "bad dense matrix getEntry n,1 " << t << ", should be " << s << endl;

		ret = false;
	}
        getEntry(t, B, n-1, n-1);
	if (!F.areEqual(t, s)) {
		report << "bad dense matrix getEntry n,n " << t << ", should be " << s << endl;

		ret = false;
	}
	commentator().stop (MSG_STATUS (ret), (const char *) 0, "testDenseMatrixgetEntry");
	return ret;
}

/* getEntry of diagonal matrix */
template <class Field,class Vector>
static bool testDiagonalgetEntry (const Field &F, VectorStream<Vector > &stream)
{
	typedef Diagonal <Field> Blackbox;

	commentator().start ("Testing diagonal getEntry", "testDiagonalgetEntry", stream.m ());
	ostream &report = commentator().report (Commentator::LEVEL_IMPORTANT, INTERNAL_DESCRIPTION);

	VectorDomain<Field> VD (F);

	bool ret = true;
	size_t i;

	Vector d(F);
	typename Field::Element sigma, res, ge;

	VectorWrapper::ensureDim (d, stream.dim ());

	while (stream) {
		commentator().startIteration ((unsigned)stream.j ());

		stream.next (d);

		report << "Input vector:  ";
		VD.write (report, d);
		report << endl;

		F.init (sigma, 0);
		for (i = 0; i < stream.n (); i++)
			F.addin (sigma, VectorWrapper::constRef<Field, Vector> (d, i));

		report << "True getEntry: ";
		F.write (report, sigma);
		report << endl;

		Blackbox D (d);

		F.init (res, 0);
		for (i = 0; i < stream.n (); i++)
			F.addin (res, getEntry (ge, D, i, i));
                F.addin(res, getEntry (ge, D, 0,stream.n ()-1));
                F.addin(res, getEntry (ge, D, stream.n ()-1, 0));

		report << "Computed getEntry: ";
		F.write (report, res);
		report << endl;

		if (!F.areEqual (sigma, res)) {
			ret = false;
			report << "ERROR: Computed getEntry is incorrect" << endl;
		}

		commentator().stop ("done");
		commentator().progress ();
	}

	commentator().stop (MSG_STATUS (ret), (const char *) 0, "testDiagonalgetEntry");

	return ret;
}

/* getEntry of composed blackbox with diagonal component*/
template <class Field>
bool testSpecialCDgetEntry (const Field &F, size_t n)
{
	bool ret = true;
	typedef typename Field::Element Elt;
	typedef ScalarMatrix<Field> BB;
	typedef Diagonal<Field> DD;
	Elt s, x, t, u;
	ostream &report = commentator().report (Commentator::LEVEL_IMPORTANT, INTERNAL_DESCRIPTION);
	F.init(x, 0);
	F.init(s, 2);
	F.init(t, 0);
	F.init(u, 0);
	F.mul(u, s, t);
	BB B(F, n, s);
	BlasVector<Field> d(F,n, t);
	DD D(d);
	Compose<DD, BB> CDB (D, B);
	Compose<BB, DD> CBD (B, D);
	Compose<DD, DD> CDD (D, D);
	getEntry(x, CDB, 0, n-1);
	if (n > 1 && !F.isZero(x)) ret = false;
	getEntry(x, CDB, 0, 0);
	if ( !F.areEqual(u, x)) ret = false;
	getEntry(x, CBD, 0, n-1);
	if (n > 1 && !F.isZero(x)) ret = false;
	getEntry(x, CBD, 0, 0);
	if ( !F.areEqual(u, x)) ret = false;
	getEntry(x, CDD, 0, n-1);
	if (n > 1 && !F.isZero(x)) ret = false;
	getEntry(x, CDD, 0, 0);
	if ( !F.areEqual(F.mul(u,t,t), x)) ret = false;
	if (!ret) report << "testSpecialCDgetEntry failure" << std::endl;
	return ret;
}
int main (int argc, char **argv)
{
	bool pass = true;

	//static size_t n = 256;
	static size_t n = 10;
	static integer q = 101;
	static int iterations = 10;

	static Argument args[] = {
		{ 'n', "-n N", "Set dimension of test matrices to NxN.", TYPE_INT,     &n },
		{ 'q', "-q Q", "Operate over the \"field\" GF(Q) [1].",  TYPE_INTEGER, &q },
		{ 'i', "-i I", "Perform each test for I iterations.",     TYPE_INT,     &iterations },
		END_OF_ARGUMENTS
	};

	typedef Modular<int32_t> Field;
	typedef BlasVector<Field> Vector;

	parseArguments (argc, argv, args);
	Field F (q);

	commentator().getMessageClass (INTERNAL_DESCRIPTION).setMaxDepth (3);
	commentator().start("getEntry solution test suite", "getEntry");

	RandomDenseStream<Field, Vector> stream (F, n, (unsigned int)iterations);

	if (!testGenericBBgetEntry (F, n)) pass = false;
	if (!testScalarMatrixgetEntry (F, n)) pass = false;
	if (!testSparseMatrixgetEntry (F, n)) pass = false;
	if (!testDenseMatrixgetEntry (F, n)) pass = false;
	if (!testDiagonalgetEntry (F, stream)) pass = false;
	if (!testSpecialCDgetEntry (F, n)) pass = false;

	commentator().stop("getEntry solution test suite");
	return pass ? 0 : -1;
}

// Local Variables:
// mode: C++
// tab-width: 8
// indent-tabs-mode: nil
// c-basic-offset: 8
// End:
// vim:sts=8:sw=8:ts=8:noet:sr:cino=>s,f0,{0,g0,(0,\:0,t0,+0,=s
<|endoftext|>


<commit_before>// Copyright (c) 2019 Matthew J. Smith and Overkit contributors
// License: MIT (http://opensource.org/licenses/MIT)

#include "ovk/core/OverlapAccel.hpp"

#include "ovk/core/Array.hpp"
#include "ovk/core/ArrayView.hpp"
#include "ovk/core/Box.hpp"
#include "ovk/core/Field.hpp"
#include "ovk/core/FieldOps.hpp"
#include "ovk/core/GeometryManipulator.hpp"
#include "ovk/core/Global.hpp"
#include "ovk/core/Optional.hpp"
#include "ovk/core/Range.hpp"
#include "ovk/core/Tuple.hpp"

#include <limits>
#include <memory>
#include <utility>

namespace ovk {
namespace core {

namespace {
struct compute_cell_bounds {
  template <typename T> void operator()(const T &Manipulator, int NumDims, const range &CellRange,
    const array<field_view<const double>> &Coords, field_view<const bool> CellMask, double
    MaxTolerance, field_view<box> CellBounds) const {
    tuple<double> ScaleFactor = MakeUniformTuple<double>(NumDims, 1.+2.*MaxTolerance, 1.);
    for (int k = CellRange.Begin(2); k < CellRange.End(2); ++k) {
      for (int j = CellRange.Begin(1); j < CellRange.End(1); ++j) {
        for (int i = CellRange.Begin(0); i < CellRange.End(0); ++i) {
          tuple<int> Cell = {i,j,k};
          if (CellMask(Cell)) {
            CellBounds(Cell) = ScaleBox(Manipulator.CellBounds(Coords, Cell), ScaleFactor);
          } else {
            CellBounds(Cell) = MakeEmptyBox(NumDims);
          }
        }
      }
    }
  }
};

struct compute_cell_volumes {
  template <typename T> void operator()(const T &Manipulator, int NumDims, const range &CellRange,
    const array<field_view<const double>> &Coords, field_view<const bool> CellMask,
    field_view<double> CellVolumes) const {
    for (int k = CellRange.Begin(2); k < CellRange.End(2); ++k) {
      for (int j = CellRange.Begin(1); j < CellRange.End(1); ++j) {
        for (int i = CellRange.Begin(0); i < CellRange.End(0); ++i) {
          tuple<int> Cell = {i,j,k};
          if (CellMask(Cell)) {
            CellVolumes(Cell) = Manipulator.CellVolume(Coords, Cell);
          } else {
            CellVolumes(Cell) = 0.;
          }
        }
      }
    }
  }
};
}

overlap_accel::overlap_accel(geometry_type GeometryType, int NumDims, const range &CellRange,
  array_view<const field_view<const double>> Coords, field_view<const bool> CellMask, double
  MaxTolerance, long long NumCellsLeaf, double MaxNodeUnoccupiedVolume, double
  MaxNodeCellVolumeVariation, double BinScale):
  GeometryType_(GeometryType),
  NumDims_(NumDims),
  GeometryManipulator_(GeometryType, NumDims),
  CellRange_(CellRange),
  CellIndexer_(CellRange),
  Coords_({MAX_DIMS})
{

  for (int iDim = 0; iDim < MAX_DIMS; ++iDim) {
    Coords_(iDim) = Coords(iDim);
  }

  field<box> CellBounds(CellRange);

  GeometryManipulator_.Apply(compute_cell_bounds(), NumDims, CellRange, Coords_, CellMask,
    MaxTolerance, CellBounds);

  long long NumCells = CellRange.Count();

  Bounds_ = MakeEmptyBox(NumDims);
  for (long long iCell = 0; iCell < NumCells; ++iCell) {
    Bounds_ = UnionBoxes(Bounds_, CellBounds[iCell]);
  }

  if (!Bounds_.Empty()) {

    field<double> CellVolumes(CellRange);

    GeometryManipulator_.Apply(compute_cell_volumes(), NumDims, CellRange, Coords_, CellMask,
      CellVolumes);

    long long NumContainedCells = 0;
    for (int k = CellRange.Begin(2); k < CellRange.End(2); ++k) {
      for (int j = CellRange.Begin(1); j < CellRange.End(1); ++j) {
        for (int i = CellRange.Begin(0); i < CellRange.End(0); ++i) {
          if (CellMask(i,j,k)) ++NumContainedCells;
        }
      }
    }

    array<long long> CellIndices({NumContainedCells});

    long long iContainedCell = 0;
    for (int k = CellRange.Begin(2); k < CellRange.End(2); ++k) {
      for (int j = CellRange.Begin(1); j < CellRange.End(1); ++j) {
        for (int i = CellRange.Begin(0); i < CellRange.End(0); ++i) {
          tuple<int> Cell = {i,j,k};
          if (CellMask(Cell)) {
            CellIndices(iContainedCell) = CellIndexer_.ToIndex(Cell);
            ++iContainedCell;
          }
        }
      }
    }

    int MaxDepth = 0;
    while ((NumContainedCells/NumCellsLeaf >> MaxDepth) != 0) {
      MaxDepth += 1;
    }

    Root_ = CreateNode_(Bounds_, CellBounds, CellVolumes, CellIndices, 0, MaxDepth, NumCellsLeaf,
      MaxNodeUnoccupiedVolume, MaxNodeCellVolumeVariation, BinScale);

  }

}

overlap_accel::node overlap_accel::CreateNode_(const box &AccelBounds, const field<box> &CellBounds,
  const field<double> &CellVolumes, const array<long long> &ContainedCellIndices, int Depth, int
  MaxDepth, long long NumCellsLeaf, double MaxUnoccupiedVolume, double MaxCellVolumeVariation,
  double BinScale) const {

  constexpr long long MAX_HASH_SIZE = 1L << 26;

  long long NumContainedCells = ContainedCellIndices.Count();

  box NodeBounds = MakeEmptyBox(NumDims_);
  for (long long iCell : ContainedCellIndices) {
    NodeBounds = UnionBoxes(NodeBounds, CellBounds[iCell]);
  }

  bool LeafNode;

  if (Depth == MaxDepth || NumContainedCells <= NumCellsLeaf) {

    LeafNode = true;

  } else {

    double TotalCellVolume = 0.;
    for (long long iCell : ContainedCellIndices) {
      TotalCellVolume += CellVolumes[iCell];
    }
    double MeanCellVolume = TotalCellVolume/double(NumContainedCells);

    double CellVolumeVariation = 0.;
    for (long long iCell : ContainedCellIndices) {
      double Deviation = CellVolumes[iCell] - MeanCellVolume;
      CellVolumeVariation += Deviation*Deviation;
    }
    CellVolumeVariation = std::sqrt(CellVolumeVariation/double(NumContainedCells-1))/MeanCellVolume;

    double UnoccupiedVolume = Max(NodeBounds.Volume()-TotalCellVolume, 0.);

    bool OccupiedEnough = UnoccupiedVolume < MaxUnoccupiedVolume*AccelBounds.Volume();
    bool UniformEnough = CellVolumeVariation <= MaxCellVolumeVariation;
    bool NotTooBig = NumContainedCells <= MAX_HASH_SIZE;

    LeafNode = OccupiedEnough and UniformEnough and NotTooBig;

  }

  node Node;

  if (!LeafNode) {

    Node.SplitDim = 1;
    for (int iDim = 0; iDim < NumDims_; ++iDim) {
      if (NodeBounds.Size(iDim) > NodeBounds.Size(Node.SplitDim)) {
        Node.SplitDim = iDim;
      }
    }

    Node.Split = 0.;
    for (long long iCell : ContainedCellIndices) {
      const box &Bounds = CellBounds[iCell];
      Node.Split += 0.5*(Bounds.Begin(Node.SplitDim) + Bounds.End(Node.SplitDim));
    }
    Node.Split /= Max(double(NumContainedCells), 1.);

    long long NumLeftChildCells = 0;
    long long NumRightChildCells = 0;

    for (long long iCell : ContainedCellIndices) {
      const box &Bounds = CellBounds[iCell];
      if (Bounds.Begin(Node.SplitDim) <= Node.Split) ++NumLeftChildCells;
      if (Bounds.End(Node.SplitDim) >= Node.Split) ++NumRightChildCells;
    }

    array<long long> LeftChildIndices, RightChildIndices;
    LeftChildIndices.Reserve(NumLeftChildCells);
    RightChildIndices.Reserve(NumRightChildCells);

    for (long long iCell : ContainedCellIndices) {
      const box &Bounds = CellBounds[iCell];
      if (Bounds.Begin(Node.SplitDim) <= Node.Split) LeftChildIndices.Append(iCell);
      if (Bounds.End(Node.SplitDim) >= Node.Split) RightChildIndices.Append(iCell);
    }

    Node.LeftChild.reset(new node());
    Node.RightChild.reset(new node());

    *Node.LeftChild = CreateNode_(AccelBounds, CellBounds, CellVolumes, LeftChildIndices,
      Depth+1, MaxDepth, NumCellsLeaf, MaxUnoccupiedVolume, MaxCellVolumeVariation, BinScale);
    *Node.RightChild = CreateNode_(AccelBounds, CellBounds, CellVolumes, RightChildIndices,
      Depth+1, MaxDepth, NumCellsLeaf, MaxUnoccupiedVolume, MaxCellVolumeVariation, BinScale);

  } else {

    tuple<double> MeanCellBoundsSize = {0.,0.,0.};
    for (long long iCell : ContainedCellIndices) {
      for (int iDim = 0; iDim < NumDims_; ++iDim) {
        MeanCellBoundsSize(iDim) += CellBounds[iCell].Size(iDim);
      }
    }
    for (int iDim = 0; iDim < NumDims_; ++iDim) {
      MeanCellBoundsSize(iDim) /= Max(double(NumContainedCells), 1.);
    }

    tuple<double> DesiredBinSize;
    for (int iDim = 0; iDim < MAX_DIMS; ++iDim) {
      DesiredBinSize(iDim) = BinScale * MeanCellBoundsSize(iDim);
    }

    tuple<int> NumBins = {1,1,1};
    if (NumContainedCells > 1) {
      for (int iDim = 0; iDim < NumDims_; ++iDim) {
        NumBins(iDim) = Max(int(std::ceil(NodeBounds.Size(iDim)/DesiredBinSize(iDim))), 1);
      }
    }

    array<box> ContainedCellBounds({NumContainedCells});

    for (long long iContainedCell = 0; iContainedCell < NumContainedCells; ++iContainedCell) {
      long long iCell = ContainedCellIndices(iContainedCell);
      ContainedCellBounds(iContainedCell) = CellBounds[iCell];
    }

    Node.CellIndices = ContainedCellIndices;
    Node.Hash.reset(new bounding_box_hash(NumDims_, NumBins, ContainedCellBounds));

  }

  return Node;

}

optional<tuple<int>> overlap_accel::FindCell(const tuple<double> &PointCoords, double Tolerance)
  const {

  optional<tuple<int>> MaybeCell;

  if (Bounds_.Contains(PointCoords)) {
    MaybeCell = FindCellInNode_(*Root_, PointCoords, Tolerance);
  }

  return MaybeCell;

}

namespace {
struct find_cell_in_bin {
  template <typename T> void operator()(const T &Manipulator, int NumDims, const array<field_view<
    const double>> &Coords, const array_view<const long long> &BinCells, const array<long long>
    &NodeContainedCells, const field_indexer &CellIndexer, const tuple<double> &PointCoords, double
    Tolerance, optional<tuple<int>> &MaybeCell) const {

    // Try to find overlap without tolerance first
    for (long long iContainedCell : BinCells) {
      long long iCell = NodeContainedCells(iContainedCell);
      tuple<int> Cell = CellIndexer.ToTuple(iCell);
      if (Manipulator.OverlapsCell(Coords, 0., Cell, PointCoords)) {
        MaybeCell = Cell;
        break;
      }
    }

    // If that fails, try to project onto edge of nearest cell
    if (!MaybeCell) {
      double BestDisplacementSq = std::numeric_limits<double>::max();
      for (long long iContainedCell : BinCells) {
        long long iCell = NodeContainedCells(iContainedCell);
        tuple<int> Cell = CellIndexer.ToTuple(iCell);
        if (!Manipulator.OverlapsCell(Coords, Tolerance, Cell, PointCoords)) continue;
        auto MaybeCellCoords = Manipulator.CoordsInCell(Coords, Cell, PointCoords);
        if (!MaybeCellCoords) continue;
        const tuple<double> &CellCoords = *MaybeCellCoords;
        double DisplacementSq = 0.;
        for (int iDim = 0; iDim < NumDims; ++iDim) {
          double ClampOffset = 0.;
          if (CellCoords(iDim) > 1.) {
            ClampOffset = 1.-CellCoords(iDim);
          } else if (CellCoords(iDim) < 0.) {
            ClampOffset = -CellCoords(iDim);
          }
          DisplacementSq += ClampOffset*ClampOffset;
        }
        if (DisplacementSq < BestDisplacementSq) {
          MaybeCell = Cell;
          BestDisplacementSq = DisplacementSq;
        }
      }
    }

  }
};
}

optional<tuple<int>> overlap_accel::FindCellInNode_(const node &Node, const tuple<double>
  &PointCoords, double Tolerance) const {

  optional<tuple<int>> MaybeCell;

  bool LeafNode = Node.Hash != nullptr;

  if (!LeafNode) {

    if (PointCoords(Node.SplitDim) <= Node.Split) {
      MaybeCell = FindCellInNode_(*Node.LeftChild, PointCoords, Tolerance);
    } else {
      MaybeCell = FindCellInNode_(*Node.RightChild, PointCoords, Tolerance);
    }

  } else {

    long long iBin = Node.Hash->MapToBin(PointCoords);

    if (iBin >= 0) {
      array_view<const long long> BinCells = Node.Hash->RetrieveBin(iBin);
      GeometryManipulator_.Apply(find_cell_in_bin(), NumDims_, Coords_, BinCells, Node.CellIndices,
        CellIndexer_, PointCoords, Tolerance, MaybeCell);
    }

  }

  return MaybeCell;

}

}}
<commit_msg>box::Volume doesn't work<commit_after>// Copyright (c) 2019 Matthew J. Smith and Overkit contributors
// License: MIT (http://opensource.org/licenses/MIT)

#include "ovk/core/OverlapAccel.hpp"

#include "ovk/core/Array.hpp"
#include "ovk/core/ArrayView.hpp"
#include "ovk/core/Box.hpp"
#include "ovk/core/Field.hpp"
#include "ovk/core/FieldOps.hpp"
#include "ovk/core/GeometryManipulator.hpp"
#include "ovk/core/Global.hpp"
#include "ovk/core/Optional.hpp"
#include "ovk/core/Range.hpp"
#include "ovk/core/Tuple.hpp"

#include <limits>
#include <memory>
#include <utility>

namespace ovk {
namespace core {

namespace {
struct compute_cell_bounds {
  template <typename T> void operator()(const T &Manipulator, int NumDims, const range &CellRange,
    const array<field_view<const double>> &Coords, field_view<const bool> CellMask, double
    MaxTolerance, field_view<box> CellBounds) const {
    tuple<double> ScaleFactor = MakeUniformTuple<double>(NumDims, 1.+2.*MaxTolerance, 1.);
    for (int k = CellRange.Begin(2); k < CellRange.End(2); ++k) {
      for (int j = CellRange.Begin(1); j < CellRange.End(1); ++j) {
        for (int i = CellRange.Begin(0); i < CellRange.End(0); ++i) {
          tuple<int> Cell = {i,j,k};
          if (CellMask(Cell)) {
            CellBounds(Cell) = ScaleBox(Manipulator.CellBounds(Coords, Cell), ScaleFactor);
          } else {
            CellBounds(Cell) = MakeEmptyBox(NumDims);
          }
        }
      }
    }
  }
};

struct compute_cell_volumes {
  template <typename T> void operator()(const T &Manipulator, int NumDims, const range &CellRange,
    const array<field_view<const double>> &Coords, field_view<const bool> CellMask,
    field_view<double> CellVolumes) const {
    for (int k = CellRange.Begin(2); k < CellRange.End(2); ++k) {
      for (int j = CellRange.Begin(1); j < CellRange.End(1); ++j) {
        for (int i = CellRange.Begin(0); i < CellRange.End(0); ++i) {
          tuple<int> Cell = {i,j,k};
          if (CellMask(Cell)) {
            CellVolumes(Cell) = Manipulator.CellVolume(Coords, Cell);
          } else {
            CellVolumes(Cell) = 0.;
          }
        }
      }
    }
  }
};
}

overlap_accel::overlap_accel(geometry_type GeometryType, int NumDims, const range &CellRange,
  array_view<const field_view<const double>> Coords, field_view<const bool> CellMask, double
  MaxTolerance, long long NumCellsLeaf, double MaxNodeUnoccupiedVolume, double
  MaxNodeCellVolumeVariation, double BinScale):
  GeometryType_(GeometryType),
  NumDims_(NumDims),
  GeometryManipulator_(GeometryType, NumDims),
  CellRange_(CellRange),
  CellIndexer_(CellRange),
  Coords_({MAX_DIMS})
{

  for (int iDim = 0; iDim < MAX_DIMS; ++iDim) {
    Coords_(iDim) = Coords(iDim);
  }

  field<box> CellBounds(CellRange);

  GeometryManipulator_.Apply(compute_cell_bounds(), NumDims, CellRange, Coords_, CellMask,
    MaxTolerance, CellBounds);

  long long NumCells = CellRange.Count();

  Bounds_ = MakeEmptyBox(NumDims);
  for (long long iCell = 0; iCell < NumCells; ++iCell) {
    Bounds_ = UnionBoxes(Bounds_, CellBounds[iCell]);
  }

  if (!Bounds_.Empty()) {

    field<double> CellVolumes(CellRange);

    GeometryManipulator_.Apply(compute_cell_volumes(), NumDims, CellRange, Coords_, CellMask,
      CellVolumes);

    long long NumContainedCells = 0;
    for (int k = CellRange.Begin(2); k < CellRange.End(2); ++k) {
      for (int j = CellRange.Begin(1); j < CellRange.End(1); ++j) {
        for (int i = CellRange.Begin(0); i < CellRange.End(0); ++i) {
          if (CellMask(i,j,k)) ++NumContainedCells;
        }
      }
    }

    array<long long> CellIndices({NumContainedCells});

    long long iContainedCell = 0;
    for (int k = CellRange.Begin(2); k < CellRange.End(2); ++k) {
      for (int j = CellRange.Begin(1); j < CellRange.End(1); ++j) {
        for (int i = CellRange.Begin(0); i < CellRange.End(0); ++i) {
          tuple<int> Cell = {i,j,k};
          if (CellMask(Cell)) {
            CellIndices(iContainedCell) = CellIndexer_.ToIndex(Cell);
            ++iContainedCell;
          }
        }
      }
    }

    int MaxDepth = 0;
    while ((NumContainedCells/NumCellsLeaf >> MaxDepth) != 0) {
      MaxDepth += 1;
    }

    Root_ = CreateNode_(Bounds_, CellBounds, CellVolumes, CellIndices, 0, MaxDepth, NumCellsLeaf,
      MaxNodeUnoccupiedVolume, MaxNodeCellVolumeVariation, BinScale);

  }

}

overlap_accel::node overlap_accel::CreateNode_(const box &AccelBounds, const field<box> &CellBounds,
  const field<double> &CellVolumes, const array<long long> &ContainedCellIndices, int Depth, int
  MaxDepth, long long NumCellsLeaf, double MaxUnoccupiedVolume, double MaxCellVolumeVariation,
  double BinScale) const {

  constexpr long long MAX_HASH_SIZE = 1L << 26;

  long long NumContainedCells = ContainedCellIndices.Count();

  box NodeBounds = MakeEmptyBox(NumDims_);
  for (long long iCell : ContainedCellIndices) {
    NodeBounds = UnionBoxes(NodeBounds, CellBounds[iCell]);
  }

  bool LeafNode;

  if (Depth == MaxDepth || NumContainedCells <= NumCellsLeaf) {

    LeafNode = true;

  } else {

    double TotalCellVolume = 0.;
    for (long long iCell : ContainedCellIndices) {
      TotalCellVolume += CellVolumes[iCell];
    }
    double MeanCellVolume = TotalCellVolume/double(NumContainedCells);

    double CellVolumeVariation = 0.;
    for (long long iCell : ContainedCellIndices) {
      double Deviation = CellVolumes[iCell] - MeanCellVolume;
      CellVolumeVariation += Deviation*Deviation;
    }
    CellVolumeVariation = std::sqrt(CellVolumeVariation/double(NumContainedCells-1))/MeanCellVolume;

    auto BoxVolume = [&](const box &Box) -> double {
      double Volume = 1.;
      for (int iDim = 0; iDim < NumDims_; ++iDim) {
        Volume *= Box.Size(iDim);
      }
      return Volume;
    };

    double UnoccupiedVolume = Max(BoxVolume(NodeBounds)-TotalCellVolume, 0.);

    bool OccupiedEnough = UnoccupiedVolume <= MaxUnoccupiedVolume*BoxVolume(AccelBounds);
    bool UniformEnough = CellVolumeVariation <= MaxCellVolumeVariation;
    bool NotTooBig = NumContainedCells <= MAX_HASH_SIZE;

    LeafNode = OccupiedEnough and UniformEnough and NotTooBig;

  }

  node Node;

  if (!LeafNode) {

    Node.SplitDim = 1;
    for (int iDim = 0; iDim < NumDims_; ++iDim) {
      if (NodeBounds.Size(iDim) > NodeBounds.Size(Node.SplitDim)) {
        Node.SplitDim = iDim;
      }
    }

    Node.Split = 0.;
    for (long long iCell : ContainedCellIndices) {
      const box &Bounds = CellBounds[iCell];
      Node.Split += 0.5*(Bounds.Begin(Node.SplitDim) + Bounds.End(Node.SplitDim));
    }
    Node.Split /= Max(double(NumContainedCells), 1.);

    long long NumLeftChildCells = 0;
    long long NumRightChildCells = 0;

    for (long long iCell : ContainedCellIndices) {
      const box &Bounds = CellBounds[iCell];
      if (Bounds.Begin(Node.SplitDim) <= Node.Split) ++NumLeftChildCells;
      if (Bounds.End(Node.SplitDim) >= Node.Split) ++NumRightChildCells;
    }

    array<long long> LeftChildIndices, RightChildIndices;
    LeftChildIndices.Reserve(NumLeftChildCells);
    RightChildIndices.Reserve(NumRightChildCells);

    for (long long iCell : ContainedCellIndices) {
      const box &Bounds = CellBounds[iCell];
      if (Bounds.Begin(Node.SplitDim) <= Node.Split) LeftChildIndices.Append(iCell);
      if (Bounds.End(Node.SplitDim) >= Node.Split) RightChildIndices.Append(iCell);
    }

    Node.LeftChild.reset(new node());
    Node.RightChild.reset(new node());

    *Node.LeftChild = CreateNode_(AccelBounds, CellBounds, CellVolumes, LeftChildIndices,
      Depth+1, MaxDepth, NumCellsLeaf, MaxUnoccupiedVolume, MaxCellVolumeVariation, BinScale);
    *Node.RightChild = CreateNode_(AccelBounds, CellBounds, CellVolumes, RightChildIndices,
      Depth+1, MaxDepth, NumCellsLeaf, MaxUnoccupiedVolume, MaxCellVolumeVariation, BinScale);

  } else {

    tuple<double> MeanCellBoundsSize = {0.,0.,0.};
    for (long long iCell : ContainedCellIndices) {
      for (int iDim = 0; iDim < NumDims_; ++iDim) {
        MeanCellBoundsSize(iDim) += CellBounds[iCell].Size(iDim);
      }
    }
    for (int iDim = 0; iDim < NumDims_; ++iDim) {
      MeanCellBoundsSize(iDim) /= Max(double(NumContainedCells), 1.);
    }

    tuple<double> DesiredBinSize;
    for (int iDim = 0; iDim < MAX_DIMS; ++iDim) {
      DesiredBinSize(iDim) = BinScale * MeanCellBoundsSize(iDim);
    }

    tuple<int> NumBins = {1,1,1};
    if (NumContainedCells > 1) {
      for (int iDim = 0; iDim < NumDims_; ++iDim) {
        NumBins(iDim) = Max(int(std::ceil(NodeBounds.Size(iDim)/DesiredBinSize(iDim))), 1);
      }
    }

    array<box> ContainedCellBounds({NumContainedCells});

    for (long long iContainedCell = 0; iContainedCell < NumContainedCells; ++iContainedCell) {
      long long iCell = ContainedCellIndices(iContainedCell);
      ContainedCellBounds(iContainedCell) = CellBounds[iCell];
    }

    Node.CellIndices = ContainedCellIndices;
    Node.Hash.reset(new bounding_box_hash(NumDims_, NumBins, ContainedCellBounds));

  }

  return Node;

}

optional<tuple<int>> overlap_accel::FindCell(const tuple<double> &PointCoords, double Tolerance)
  const {

  optional<tuple<int>> MaybeCell;

  if (Bounds_.Contains(PointCoords)) {
    MaybeCell = FindCellInNode_(*Root_, PointCoords, Tolerance);
  }

  return MaybeCell;

}

namespace {
struct find_cell_in_bin {
  template <typename T> void operator()(const T &Manipulator, int NumDims, const array<field_view<
    const double>> &Coords, const array_view<const long long> &BinCells, const array<long long>
    &NodeContainedCells, const field_indexer &CellIndexer, const tuple<double> &PointCoords, double
    Tolerance, optional<tuple<int>> &MaybeCell) const {

    // Try to find overlap without tolerance first
    for (long long iContainedCell : BinCells) {
      long long iCell = NodeContainedCells(iContainedCell);
      tuple<int> Cell = CellIndexer.ToTuple(iCell);
      if (Manipulator.OverlapsCell(Coords, 0., Cell, PointCoords)) {
        MaybeCell = Cell;
        break;
      }
    }

    // If that fails, try to project onto edge of nearest cell
    if (!MaybeCell) {
      double BestDisplacementSq = std::numeric_limits<double>::max();
      for (long long iContainedCell : BinCells) {
        long long iCell = NodeContainedCells(iContainedCell);
        tuple<int> Cell = CellIndexer.ToTuple(iCell);
        if (!Manipulator.OverlapsCell(Coords, Tolerance, Cell, PointCoords)) continue;
        auto MaybeCellCoords = Manipulator.CoordsInCell(Coords, Cell, PointCoords);
        if (!MaybeCellCoords) continue;
        const tuple<double> &CellCoords = *MaybeCellCoords;
        double DisplacementSq = 0.;
        for (int iDim = 0; iDim < NumDims; ++iDim) {
          double ClampOffset = 0.;
          if (CellCoords(iDim) > 1.) {
            ClampOffset = 1.-CellCoords(iDim);
          } else if (CellCoords(iDim) < 0.) {
            ClampOffset = -CellCoords(iDim);
          }
          DisplacementSq += ClampOffset*ClampOffset;
        }
        if (DisplacementSq < BestDisplacementSq) {
          MaybeCell = Cell;
          BestDisplacementSq = DisplacementSq;
        }
      }
    }

  }
};
}

optional<tuple<int>> overlap_accel::FindCellInNode_(const node &Node, const tuple<double>
  &PointCoords, double Tolerance) const {

  optional<tuple<int>> MaybeCell;

  bool LeafNode = Node.Hash != nullptr;

  if (!LeafNode) {

    if (PointCoords(Node.SplitDim) <= Node.Split) {
      MaybeCell = FindCellInNode_(*Node.LeftChild, PointCoords, Tolerance);
    } else {
      MaybeCell = FindCellInNode_(*Node.RightChild, PointCoords, Tolerance);
    }

  } else {

    long long iBin = Node.Hash->MapToBin(PointCoords);

    if (iBin >= 0) {
      array_view<const long long> BinCells = Node.Hash->RetrieveBin(iBin);
      GeometryManipulator_.Apply(find_cell_in_bin(), NumDims_, Coords_, BinCells, Node.CellIndices,
        CellIndexer_, PointCoords, Tolerance, MaybeCell);
    }

  }

  return MaybeCell;

}

}}
<|endoftext|>


<commit_before>/***
  Copyright (c) 2014 Mirco Tischler

  Permission is hereby granted, free of charge, to any person obtaining a copy
  of this software and associated documentation files (the "Software"), to deal
  in the Software without restriction, including without limitation the rights
  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  copies of the Software, and to permit persons to whom the Software is
  furnished to do so, subject to the following conditions:

  The above copyright notice and this permission notice shall be included in all
  copies or substantial portions of the Software.

  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  SOFTWARE.
***/

#include "range.h"

#include <iostream>
#include <vector>

int main() {
        std::vector<int> v {1, 3, 5, 7, 9};

        auto r = range::make_range(v);

        range::for_each(r, [](const int &i) {
                std::cout << i << std::endl;
        });

        auto s = range::divide(r, 3);

        std::cout << range::has(r, 5) << std::endl;

        return 0;
}
<commit_msg>test: check range based for loops<commit_after>/***
  Copyright (c) 2014 Mirco Tischler

  Permission is hereby granted, free of charge, to any person obtaining a copy
  of this software and associated documentation files (the "Software"), to deal
  in the Software without restriction, including without limitation the rights
  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  copies of the Software, and to permit persons to whom the Software is
  furnished to do so, subject to the following conditions:

  The above copyright notice and this permission notice shall be included in all
  copies or substantial portions of the Software.

  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  SOFTWARE.
***/

#include "range.h"

#include <iostream>
#include <vector>

int main() {
        std::vector<int> v {1, 3, 5, 7, 9};

        auto r = range::make_range(v);

        range::for_each(r, [](const int &i) {
                std::cout << i << std::endl;
        });

        auto s = range::divide(r, 3);

        std::cout << range::has(r, 5) << std::endl;

        for(int i: r)
                std::cout << i << std::endl;

        return 0;
}
<|endoftext|>