<commit_before>#include "VectorTile.h"
#include <string>
#include "vector_tile20/vector_tile.pb.h"
#include <math.h>
#include <iostream>
#include <sstream>
#include <utility>
using namespace std;

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";
}

inline double CheckWinding(LineLoop2D pts)
{
	double total = 0.0;
	for(size_t i=0; i < pts.size(); i++)
	{
		size_t i2 = (i+1)%pts.size();
		double val = (pts[i2].first - pts[i].first)*(pts[i2].second + pts[i].second);
		total += val;
	}
	return total;
}

void DecodeGeometry(const ::vector_tile::Tile_Feature &feature,
	int extent, int tileZoom, int tileColumn, int tileRow,
	vector<Point2D> &pointsOut,
	vector<vector<Point2D> > &linesOut,
	vector<Polygon2D> &polygonsOut)

{
	long unsigned int numTiles = pow(2,tileZoom);
	double lonMin = tilex2long(tileColumn, tileZoom);
	double latMax = tiley2lat(numTiles-tileRow-1, tileZoom);//Why is latitude no where near expected?
	double lonMax = tilex2long(tileColumn+1, tileZoom);
	double latMin = tiley2lat(numTiles-tileRow, tileZoom);
	double dLat = latMax - latMin;
	double dLon = lonMax - lonMin;
	vector<Point2D> points;
	Polygon2D currentPolygon;
	bool currentPolygonSet = false;
	unsigned prevCmdId = 0;

	int cursorx = 0, cursory = 0;
	double prevx = 0.0, prevy = 0.0;// prevWinding = -1.0;
	pointsOut.clear();
	linesOut.clear();
	polygonsOut.clear();

	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(unsigned 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;

				if (feature.type() == vector_tile::Tile_GeomType_POINT)
					pointsOut.push_back(Point2D(px, py));
				if (feature.type() == vector_tile::Tile_GeomType_LINESTRING && points.size() > 0)
				{
					linesOut.push_back(points);
					points.clear();
				}
				prevx = px;
				prevy = py;
				i += 2;
				prevCmdId = cmdId;
			}
		}
		if(cmdId == 2)//LineTo
		{
			for(unsigned j=0; j < cmdCount; j++)
			{
				if(prevCmdId != 2)
					points.push_back(Point2D(prevx, prevy));
				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;

				points.push_back(Point2D(px, py));
				i += 2;
				prevCmdId = cmdId;
			}
		}
		if(cmdId == 7) //ClosePath
		{
			//Closed path does not move cursor in v1 to v2.1 of spec.
			// https://github.com/mapbox/vector-tile-spec/issues/49
			for(unsigned j=0; j < cmdCount; j++)
			{
				if (feature.type() == vector_tile::Tile_GeomType_POLYGON)
				{
					double winding = CheckWinding(points);
					if(winding >= 0.0)
					{
						if(currentPolygonSet)
						{
							//We are moving on to the next polygon, so store what we have collected so far
							polygonsOut.push_back(currentPolygon);
							currentPolygon.first.clear();
							currentPolygon.second.clear();
						}
						currentPolygon.first = points; //outer shape
						currentPolygonSet = true;
					}
					else
						currentPolygon.second.push_back(points); //inter shape

					//prevWinding = winding;
					points.clear();
					prevCmdId = cmdId;
				}
			}
		}
	}

	if (feature.type() == vector_tile::Tile_GeomType_LINESTRING)
		linesOut.push_back(points);
	if (feature.type() == vector_tile::Tile_GeomType_POLYGON)
		polygonsOut.push_back(currentPolygon);
}

DecodeVectorTile::DecodeVectorTile(class DecodeVectorTileResults &output)
{
	this->output = &output;
}

DecodeVectorTile::~DecodeVectorTile()
{

}

void DecodeVectorTile::DecodeTileData(const std::string &tileData, int tileZoom, int tileColumn, int tileRow)
{
	vector_tile::Tile tile;
	bool parsed = tile.ParseFromString(tileData);
	if(!parsed)
		throw runtime_error("Failed to parse tile data");

	this->output->NumLayers(tile.layers_size());

	for(int layerNum = 0; layerNum < tile.layers_size(); layerNum++)
	{
		const ::vector_tile::Tile_Layer &layer = tile.layers(layerNum);
		this->output->LayerStart(layer.name().c_str(), layer.version());

		//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);

			map<string, string> tagMap;
			for(int tagNum = 0; tagNum < feature.tags_size(); tagNum+=2)
			{
				const ::vector_tile::Tile_Value &value = layer.values(feature.tags(tagNum+1));
				tagMap[layer.keys(feature.tags(tagNum))] = ValueToStr(value);
			}

			vector<Point2D> points;
			vector<vector<Point2D> > lines;
			vector<Polygon2D> polygons;
			DecodeGeometry(feature, layer.extent(), tileZoom, tileColumn, tileRow,
				points, lines, polygons);

			this->output->Feature(feature.type(), feature.has_id(), feature.id(), tagMap,
				points, lines, polygons);
		}

		this->output->LayerEnd();
	}
}

// *********************************************

// https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames#C.2FC.2B.2B
int long2tilex(double lon, int z)
{
	return (int)(floor((lon + 180.0) / 360.0 * pow(2.0, z)));
}

int lat2tiley(double lat, int z)
{
	return (int)(floor((1.0 - log( tan(lat * M_PI/180.0) + 1.0 / cos(lat * M_PI/180.0)) / M_PI) / 2.0 * pow(2.0, z)));
}

double tilex2long(int x, int z)
{
	return x / pow(2.0, z) * 360.0 - 180;
}

double tiley2lat(int y, int z)
{
	double n = M_PI - 2.0 * M_PI * y / pow(2.0, z);
	return 180.0 / M_PI * atan(0.5 * (exp(n) - exp(-n)));
}

// ***********************************************

DecodeVectorTileResults::DecodeVectorTileResults()
{

}

DecodeVectorTileResults::~DecodeVectorTileResults()
{

}

void DecodeVectorTileResults::NumLayers(int numLayers)
{
	cout << "Num layers: " << numLayers << endl;
}

void DecodeVectorTileResults::LayerStart(const char *name, int version)
{
	cout << "layer name: " << name << endl;
	cout << "layer version: " << version << endl;
}

void DecodeVectorTileResults::LayerEnd()
{
	cout << "layer end" << endl;
}

void DecodeVectorTileResults::Feature(int typeEnum, bool hasId,
	unsigned long long id, const map<string, string> &tagMap,
	vector<Point2D> &points,
	vector<vector<Point2D> > &lines,
	vector<Polygon2D> &polygons)
{
	cout << typeEnum << "," << FeatureTypeToStr((::vector_tile::Tile_GeomType)typeEnum);
	if(hasId)
		cout << ",id=" << id;
	cout << endl;

	for(map<string, string>::const_iterator it = tagMap.begin(); it != tagMap.end(); it++)
	{
		cout << it->first << "=" << it->second << endl;
	}

	for(size_t i =0; i < points.size(); i++)
		cout << "POINT("<<points[i].first<<","<<points[i].second<<") ";
	for(size_t i =0; i < lines.size(); i++)
	{
		cout << "LINESTRING(";
		vector<Point2D> &linePts = lines[i];
		for(size_t j =0; j < linePts.size(); j++)
			cout << "("<<linePts[i].first<<","<<linePts[i].second<<") ";
		cout << ") ";
	}
	for(size_t i =0; i < polygons.size(); i++)
	{
		Polygon2D &polygon = polygons[i];
		cout << "POLYGON((";
		LineLoop2D &linePts = polygon.first; //Outer shape
		for(size_t j =0; j < linePts.size(); j++)
			cout << "("<<linePts[j].first<<","<<linePts[j].second<<") ";
		cout << ")";
		if(polygon.second.size() > 0)
		{
			//Inner shape
			cout << ",(";
			for(size_t k =0; k < polygon.second.size(); k++)
			{
				cout << "(";
				LineLoop2D &linePts2 = polygon.second[i];
				for(size_t j =0; j < linePts2.size(); j++)
					cout << "("<<linePts2[i].first<<","<<linePts2[i].second<<") ";
				cout << ") ";
			}
			cout << ")";
		}

		cout << ") ";
	}
	cout << endl;
}

<commit_msg>Fix print of inner polygon<commit_after>#include "VectorTile.h"
#include <string>
#include "vector_tile20/vector_tile.pb.h"
#include <math.h>
#include <iostream>
#include <sstream>
#include <utility>
using namespace std;

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";
}

inline double CheckWinding(LineLoop2D pts)
{
	double total = 0.0;
	for(size_t i=0; i < pts.size(); i++)
	{
		size_t i2 = (i+1)%pts.size();
		double val = (pts[i2].first - pts[i].first)*(pts[i2].second + pts[i].second);
		total += val;
	}
	return total;
}

void DecodeGeometry(const ::vector_tile::Tile_Feature &feature,
	int extent, int tileZoom, int tileColumn, int tileRow,
	vector<Point2D> &pointsOut,
	vector<vector<Point2D> > &linesOut,
	vector<Polygon2D> &polygonsOut)

{
	long unsigned int numTiles = pow(2,tileZoom);
	double lonMin = tilex2long(tileColumn, tileZoom);
	double latMax = tiley2lat(numTiles-tileRow-1, tileZoom);//Why is latitude no where near expected?
	double lonMax = tilex2long(tileColumn+1, tileZoom);
	double latMin = tiley2lat(numTiles-tileRow, tileZoom);
	double dLat = latMax - latMin;
	double dLon = lonMax - lonMin;
	vector<Point2D> points;
	Polygon2D currentPolygon;
	bool currentPolygonSet = false;
	unsigned prevCmdId = 0;

	int cursorx = 0, cursory = 0;
	double prevx = 0.0, prevy = 0.0;// prevWinding = -1.0;
	pointsOut.clear();
	linesOut.clear();
	polygonsOut.clear();

	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(unsigned 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;

				if (feature.type() == vector_tile::Tile_GeomType_POINT)
					pointsOut.push_back(Point2D(px, py));
				if (feature.type() == vector_tile::Tile_GeomType_LINESTRING && points.size() > 0)
				{
					linesOut.push_back(points);
					points.clear();
				}
				prevx = px;
				prevy = py;
				i += 2;
				prevCmdId = cmdId;
			}
		}
		if(cmdId == 2)//LineTo
		{
			for(unsigned j=0; j < cmdCount; j++)
			{
				if(prevCmdId != 2)
					points.push_back(Point2D(prevx, prevy));
				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;

				points.push_back(Point2D(px, py));
				i += 2;
				prevCmdId = cmdId;
			}
		}
		if(cmdId == 7) //ClosePath
		{
			//Closed path does not move cursor in v1 to v2.1 of spec.
			// https://github.com/mapbox/vector-tile-spec/issues/49
			for(unsigned j=0; j < cmdCount; j++)
			{
				if (feature.type() == vector_tile::Tile_GeomType_POLYGON)
				{
					double winding = CheckWinding(points);
					if(winding >= 0.0)
					{
						if(currentPolygonSet)
						{
							//We are moving on to the next polygon, so store what we have collected so far
							polygonsOut.push_back(currentPolygon);
							currentPolygon.first.clear();
							currentPolygon.second.clear();
						}
						currentPolygon.first = points; //outer shape
						currentPolygonSet = true;
					}
					else
						currentPolygon.second.push_back(points); //inter shape

					//prevWinding = winding;
					points.clear();
					prevCmdId = cmdId;
				}
			}
		}
	}

	if (feature.type() == vector_tile::Tile_GeomType_LINESTRING)
		linesOut.push_back(points);
	if (feature.type() == vector_tile::Tile_GeomType_POLYGON)
		polygonsOut.push_back(currentPolygon);
}

DecodeVectorTile::DecodeVectorTile(class DecodeVectorTileResults &output)
{
	this->output = &output;
}

DecodeVectorTile::~DecodeVectorTile()
{

}

void DecodeVectorTile::DecodeTileData(const std::string &tileData, int tileZoom, int tileColumn, int tileRow)
{
	vector_tile::Tile tile;
	bool parsed = tile.ParseFromString(tileData);
	if(!parsed)
		throw runtime_error("Failed to parse tile data");

	this->output->NumLayers(tile.layers_size());

	for(int layerNum = 0; layerNum < tile.layers_size(); layerNum++)
	{
		const ::vector_tile::Tile_Layer &layer = tile.layers(layerNum);
		this->output->LayerStart(layer.name().c_str(), layer.version());

		//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);

			map<string, string> tagMap;
			for(int tagNum = 0; tagNum < feature.tags_size(); tagNum+=2)
			{
				const ::vector_tile::Tile_Value &value = layer.values(feature.tags(tagNum+1));
				tagMap[layer.keys(feature.tags(tagNum))] = ValueToStr(value);
			}

			vector<Point2D> points;
			vector<vector<Point2D> > lines;
			vector<Polygon2D> polygons;
			DecodeGeometry(feature, layer.extent(), tileZoom, tileColumn, tileRow,
				points, lines, polygons);

			this->output->Feature(feature.type(), feature.has_id(), feature.id(), tagMap,
				points, lines, polygons);
		}

		this->output->LayerEnd();
	}
}

// *********************************************

// https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames#C.2FC.2B.2B
int long2tilex(double lon, int z)
{
	return (int)(floor((lon + 180.0) / 360.0 * pow(2.0, z)));
}

int lat2tiley(double lat, int z)
{
	return (int)(floor((1.0 - log( tan(lat * M_PI/180.0) + 1.0 / cos(lat * M_PI/180.0)) / M_PI) / 2.0 * pow(2.0, z)));
}

double tilex2long(int x, int z)
{
	return x / pow(2.0, z) * 360.0 - 180;
}

double tiley2lat(int y, int z)
{
	double n = M_PI - 2.0 * M_PI * y / pow(2.0, z);
	return 180.0 / M_PI * atan(0.5 * (exp(n) - exp(-n)));
}

// ***********************************************

DecodeVectorTileResults::DecodeVectorTileResults()
{

}

DecodeVectorTileResults::~DecodeVectorTileResults()
{

}

void DecodeVectorTileResults::NumLayers(int numLayers)
{
	cout << "Num layers: " << numLayers << endl;
}

void DecodeVectorTileResults::LayerStart(const char *name, int version)
{
	cout << "layer name: " << name << endl;
	cout << "layer version: " << version << endl;
}

void DecodeVectorTileResults::LayerEnd()
{
	cout << "layer end" << endl;
}

void DecodeVectorTileResults::Feature(int typeEnum, bool hasId,
	unsigned long long id, const map<string, string> &tagMap,
	vector<Point2D> &points,
	vector<vector<Point2D> > &lines,
	vector<Polygon2D> &polygons)
{
	cout << typeEnum << "," << FeatureTypeToStr((::vector_tile::Tile_GeomType)typeEnum);
	if(hasId)
		cout << ",id=" << id;
	cout << endl;

	for(map<string, string>::const_iterator it = tagMap.begin(); it != tagMap.end(); it++)
	{
		cout << it->first << "=" << it->second << endl;
	}

	for(size_t i =0; i < points.size(); i++)
		cout << "POINT("<<points[i].first<<","<<points[i].second<<") ";
	for(size_t i =0; i < lines.size(); i++)
	{
		cout << "LINESTRING(";
		vector<Point2D> &linePts = lines[i];
		for(size_t j =0; j < linePts.size(); j++)
			cout << "("<<linePts[i].first<<","<<linePts[i].second<<") ";
		cout << ") ";
	}
	for(size_t i =0; i < polygons.size(); i++)
	{
		Polygon2D &polygon = polygons[i];
		cout << "POLYGON((";
		LineLoop2D &linePts = polygon.first; //Outer shape
		for(size_t j =0; j < linePts.size(); j++)
			cout << "("<<linePts[j].first<<","<<linePts[j].second<<") ";
		cout << ")";
		if(polygon.second.size() > 0)
		{
			//Inner shape
			cout << ",(";
			for(size_t k =0; k < polygon.second.size(); k++)
			{
				cout << "(";
				LineLoop2D &linePts2 = polygon.second[k];
				for(size_t j =0; j < linePts2.size(); j++)
					cout << "("<<linePts2[j].first<<","<<linePts2[j].second<<") ";
				cout << ") ";
			}
			cout << ")";
		}

		cout << ") ";
	}
	cout << endl;
}

<|endoftext|>


<commit_before><commit_msg>Improve strncmp tests<commit_after><|endoftext|>


<commit_before><commit_msg>Simulator: Removed spurious assembly time output.<commit_after><|endoftext|>


<commit_before>/*-------------------------------------------------------------------------
 * drawElements Quality Program OpenGL ES 3.1 Module
 * -------------------------------------------------
 *
 * Copyright 2017 The Android Open Source Project
 *
 * 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.
 *
 *//*!
 * \file
 * \brief Negative Sample Variables Tests
 *//*--------------------------------------------------------------------*/

#include "es31fNegativeSampleVariablesTests.hpp"
#include "gluShaderProgram.hpp"

namespace deqp
{
namespace gles31
{
namespace Functional
{
namespace NegativeTestShared
{
namespace
{

enum ExpectResult
{
	EXPECT_RESULT_PASS = 0,
	EXPECT_RESULT_FAIL,
	EXPECT_RESULT_LAST
};

void verifyShader (NegativeTestContext& ctx, glu::ShaderType shaderType, std::string shaderSource, ExpectResult expect)
{
	DE_ASSERT(expect >= EXPECT_RESULT_PASS && expect < EXPECT_RESULT_LAST);

	tcu::TestLog&		log			= ctx.getLog();
	bool				testFailed	= false;
	const char* const	source		= shaderSource.c_str();
	const int			length		= (int) shaderSource.size();
	glu::Shader			shader		(ctx.getRenderContext(), shaderType);
	std::string			message;

	shader.setSources(1, &source, &length);
	shader.compile();

	log << shader;

	if (expect == EXPECT_RESULT_PASS)
	{
		testFailed = !shader.getCompileStatus();
		message = "Shader did not compile.";
	}
	else
	{
		testFailed = shader.getCompileStatus();
		message = "Shader was not expected to compile.";
	}

	if (testFailed)
	{
		log << tcu::TestLog::Message << message << tcu::TestLog::EndMessage;
		ctx.fail(message);
	}
}

std::string getVersionAndExtension (NegativeTestContext& ctx)
{
	const bool				isES32	= contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2));
	const glu::GLSLVersion	version	= isES32 ? glu::GLSL_VERSION_320_ES : glu::GLSL_VERSION_310_ES;

	std::string versionAndExtension = glu::getGLSLVersionDeclaration(version);
	versionAndExtension += " \n";

	if (!isES32)
		versionAndExtension += "#extension GL_OES_sample_variables : require \n";

	return versionAndExtension;
}

void checkSupported (NegativeTestContext& ctx)
{
	const bool isES32 = contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2));

	if (!isES32 && !ctx.isExtensionSupported("GL_OES_sample_variables"))
		TCU_THROW(NotSupportedError, "GL_OES_sample_variables is not supported.");
}

void write_to_read_only_types (NegativeTestContext& ctx)
{
	checkSupported(ctx);

	std::ostringstream	shader;

	struct testConfig
	{
		std::string builtInType;
		std::string varyingCheck;
	} testConfigs[] =
	{
		{"gl_SampleID",			"	lowp int writeValue = 1; \n	gl_SampleID = writeValue; \n"},
		{"gl_SamplePosition",	"	mediump vec2 writeValue = vec2(1.0f, 1.0f); \n	gl_SamplePosition = writeValue; \n"},
		{"gl_SampleMaskIn",		"	lowp int writeValue = 1; \n	gl_SampleMaskIn[0] = writeValue; \n"}
	};

	for (int idx = 0; idx < DE_LENGTH_OF_ARRAY(testConfigs); idx++)
	{
		shader.str("");
		shader
			<< getVersionAndExtension(ctx)
			<< "layout (location = 0) out mediump vec4 fs_color; \n"
			<< "void main() \n"
			<< "{ \n"
			<<		testConfigs[idx].varyingCheck
			<< "	fs_color = vec4(1.0f, 0.0f, 0.0f, 1.0f); \n"
			<< "} \n";

		ctx.beginSection("OES_sample_variables: trying to write to built-in read-only variable" + testConfigs[idx].builtInType);
		verifyShader(ctx, glu::SHADERTYPE_FRAGMENT, shader.str(), EXPECT_RESULT_FAIL);
		ctx.endSection();
	}
}

void access_built_in_types_inside_other_shaders (NegativeTestContext& ctx)
{
	checkSupported(ctx);

	std::ostringstream	shader;

	struct testConfig
	{
		std::string builtInType;
		std::string varyingCheck;
	} testConfigs[] =
	{
		{"gl_SampleID",			"	lowp int writeValue = 1; \n	gl_SampleID = writeValue; \n"},
		{"gl_SamplePosition",	"	mediump vec2 writeValue = vec2(1.0f, 1.0f); \n	gl_SamplePosition = writeValue; \n"},
		{"gl_SampleMaskIn",		"	lowp int writeValue = 1; \n	gl_SampleMaskIn[0] = writeValue; \n"},
		{"gl_SampleMask",		"	highp int readValue = gl_SampleMask[0]; \n"},
	};

	for (int idx = 0; idx < DE_LENGTH_OF_ARRAY(testConfigs); idx++)
	{
		shader.str("");
		shader
			<< getVersionAndExtension(ctx)
			<< "void main () \n"
			<< "{ \n"
			<<		testConfigs[idx].varyingCheck
			<< "	gl_Position = vec4(1.0f, 0.0f, 0.0f , 1.0f); \n"
			<< "} \n";

		ctx.beginSection("OES_sample_variables: trying to use fragment shader built-in sampler variable " + testConfigs[idx].builtInType + " inside vertex shader");
		verifyShader(ctx, glu::SHADERTYPE_VERTEX, shader.str(), EXPECT_RESULT_FAIL);
		ctx.endSection();
	}

	for (int idx = 0; idx < DE_LENGTH_OF_ARRAY(testConfigs); idx++)
	{
		shader.str("");
		shader
			<< getVersionAndExtension(ctx)
			<< "layout (vertices = 3) out; \n"
			<< "void main () \n"
			<< "{ \n"
			<<		testConfigs[idx].varyingCheck
			<< "} \n";

		ctx.beginSection("OES_sample_variables: trying to use fragment shader built-in sampler variable " + testConfigs[idx].builtInType + " inside tessellation control shader");
		verifyShader(ctx, glu::SHADERTYPE_TESSELLATION_CONTROL, shader.str(), EXPECT_RESULT_FAIL);
		ctx.endSection();
	}

	for (int idx = 0; idx < DE_LENGTH_OF_ARRAY(testConfigs); idx++)
	{
		shader.str("");
		shader
			<< getVersionAndExtension(ctx)
			<< "layout (triangles, equal_spacing, ccw) in; \n"
			<< "void main () \n"
			<< "{ \n"
			<<		testConfigs[idx].varyingCheck
			<< "} \n";

		ctx.beginSection("OES_sample_variables: trying to use fragment shader built-in sampler variable " + testConfigs[idx].builtInType + " inside tessellation evaluation shader");
		verifyShader(ctx, glu::SHADERTYPE_TESSELLATION_EVALUATION, shader.str(), EXPECT_RESULT_FAIL);
		ctx.endSection();
	}

	for (int idx = 0; idx < DE_LENGTH_OF_ARRAY(testConfigs); idx++)
	{
		shader.str("");
		shader
			<< getVersionAndExtension(ctx)
			<< "layout (triangles) in; \n"
			<< "layout (triangle_strip, max_vertices = 32) out; \n"
			<< "void main () \n"
			<< "{ \n"
			<<		testConfigs[idx].varyingCheck
			<< "} \n";

		ctx.beginSection("OES_sample_variables: trying to use fragment shader built-in sampler variable " + testConfigs[idx].builtInType + " inside geometry shader");
		verifyShader(ctx, glu::SHADERTYPE_GEOMETRY, shader.str(), EXPECT_RESULT_FAIL);
		ctx.endSection();
	}
}

void index_outside_sample_mask_range (NegativeTestContext& ctx)
{
	checkSupported(ctx);

	std::ostringstream	shader;
	const int			MAX_TYPES	= 2;
	const int			MAX_INDEXES = 2;

	struct testConfig
	{
		std::string builtInType[MAX_TYPES];
		std::string invalidIndex[MAX_INDEXES];
	} testConfigs =
	{
		{
			"gl_SampleMask",
			"gl_SampleMaskIn"
		},
		{
			"	const highp int invalidIndex = (gl_MaxSamples + 31) / 32; \n",
			"	const highp int invalidIndex = -1; \n"
		}
	};

	for (int typeIdx = 0; typeIdx < MAX_TYPES; typeIdx++)
	{
		for (int invalidIdx = 0; invalidIdx < MAX_INDEXES; invalidIdx++)
		{
			shader.str("");
			shader
				<< getVersionAndExtension(ctx)
				<< "layout (location = 0) out mediump vec4 fs_color; \n"
				<< "void main() \n"
				<< "{ \n"
				<<		testConfigs.invalidIndex[invalidIdx]
				<< "	highp int invalidValue = " << testConfigs.builtInType[typeIdx] << "[invalidIndex]; \n"
				<< "	fs_color = vec4(1.0f, 0.0f, 0.0f, 1.0f); \n"
				<< "} \n";

			ctx.beginSection("OES_sample_variables: using constant integral expression outside of " + testConfigs.builtInType[typeIdx] + " bounds");
			verifyShader(ctx, glu::SHADERTYPE_FRAGMENT, shader.str(), EXPECT_RESULT_FAIL);
			ctx.endSection();
		}
	}
}

void access_built_in_types_without_extension (NegativeTestContext& ctx)
{
	checkSupported(ctx);

	std::ostringstream	shader;

	struct testConfig
	{
		std::string builtInType;
		std::string varyingCheck;
	} testConfigs[] =
	{
		{"gl_SampleID",			"	lowp int writeValue = 1; \n	gl_SampleID = writeValue; \n"},
		{"gl_SamplePosition",	"	mediump vec2 writeValue = vec2(1.0f, 1.0f); \n	gl_SamplePosition = writeValue; \n"},
		{"gl_SampleMaskIn",		"	lowp int writeValue = 1; \n	gl_SampleMaskIn[0] = writeValue; \n"},
		{"gl_SampleMask",		"	highp int readValue = gl_SampleMask[0]; \n"},
	};

	for (int idx = 0; idx < DE_LENGTH_OF_ARRAY(testConfigs); idx++)
	{
		shader.str("");
		shader
			<< "#version 310 es \n"
			<< "layout (location = 0) out mediump vec4 fs_color; \n"
			<< "void main() \n"
			<< "{ \n"
			<<		testConfigs[idx].varyingCheck
			<< "	fs_color = vec4(1.0f, 0.0f, 0.0f, 1.0f); \n"
			<< "} \n";

		ctx.beginSection("OES_sample_variables: accessing built-in type " + testConfigs[idx].builtInType + " in shader version 310 ES without required extension");
		verifyShader(ctx, glu::SHADERTYPE_FRAGMENT, shader.str(), EXPECT_RESULT_FAIL);
		ctx.endSection();
	}
}

void redeclare_built_in_types (NegativeTestContext& ctx)
{
	checkSupported(ctx);

	std::ostringstream	shader;
	std::ostringstream	testName;

	const char* const testConfigs[] =
	{
		"gl_SampleID",
		"gl_SamplePosition",
		"gl_SampleMaskIn",
		"gl_SampleMask",
	};

	for (int idx = 0; idx < DE_LENGTH_OF_ARRAY(testConfigs); idx++)
	{
		shader.str("");
		shader
			<< getVersionAndExtension(ctx)
			<< "layout (location = 0) out mediump vec4 fs_color; \n"
			<< "uniform lowp int " << testConfigs[idx] << "; \n"
			<< "void main() \n"
			<< "{ \n"
			<< "	if (" << testConfigs[idx] << " == 0) \n"
			<< "		fs_color = vec4(1.0f, 0.0f, 0.0f, 1.0f); \n"
			<< "	else \n"
			<< "		fs_color = vec4(0.0f, 1.0f, 0.0f, 1.0f); \n"
			<< "} \n";

		testName.str("");
		testName << "OES_sample_variables: redeclare built-in type " << testConfigs[idx];
		ctx.beginSection(testName.str());
		verifyShader(ctx, glu::SHADERTYPE_FRAGMENT, shader.str(), EXPECT_RESULT_FAIL);
		ctx.endSection();
	}
}

} // anonymous

std::vector<FunctionContainer> getNegativeSampleVariablesTestFunctions (void)
{
	const FunctionContainer funcs[] =
	{
		{write_to_read_only_types,						"write_to_read_only_types",						"tests trying writing to read-only built-in sample variables"},
		{access_built_in_types_inside_other_shaders,	"access_built_in_types_inside_other_shaders",	"Tests try to access fragment shader sample variables in other shaders"},
		{index_outside_sample_mask_range,				"index_outside_sample_mask_range",				"tests try to index into built-in sample array types out of bounds"},
		{access_built_in_types_without_extension,		"access_built_in_types_without_extension",		"tests try to access built-in sample types without the correct extension using version 310 es"},
		{redeclare_built_in_types,						"redeclare_built_in_types",						"Tests try to redeclare built-in sample types"},
	};

	return std::vector<FunctionContainer>(DE_ARRAY_BEGIN(funcs), DE_ARRAY_END(funcs));
}

} // NegativeTestShared
} // Functional
} // gles31
} // deqp<commit_msg>release-request-c38dc7a9-f664-4c91-8e15-307b4f336902-for-git_pi-release-4277421 snap-temp-L88300000093613514<commit_after>/*-------------------------------------------------------------------------
 * drawElements Quality Program OpenGL ES 3.1 Module
 * -------------------------------------------------
 *
 * Copyright 2017 The Android Open Source Project
 *
 * 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.
 *
 *//*!
 * \file
 * \brief Negative Sample Variables Tests
 *//*--------------------------------------------------------------------*/

#include "es31fNegativeSampleVariablesTests.hpp"
#include "gluShaderProgram.hpp"

namespace deqp
{
namespace gles31
{
namespace Functional
{
namespace NegativeTestShared
{
namespace
{

enum ExpectResult
{
	EXPECT_RESULT_PASS = 0,
	EXPECT_RESULT_FAIL,
	EXPECT_RESULT_LAST
};

void verifyShader (NegativeTestContext& ctx, glu::ShaderType shaderType, std::string shaderSource, ExpectResult expect)
{
	DE_ASSERT(expect >= EXPECT_RESULT_PASS && expect < EXPECT_RESULT_LAST);

	tcu::TestLog&		log			= ctx.getLog();
	bool				testFailed	= false;
	const char* const	source		= shaderSource.c_str();
	const int			length		= (int) shaderSource.size();
	glu::Shader			shader		(ctx.getRenderContext(), shaderType);
	std::string			message;

	shader.setSources(1, &source, &length);
	shader.compile();

	log << shader;

	if (expect == EXPECT_RESULT_PASS)
	{
		testFailed = !shader.getCompileStatus();
		message = "Shader did not compile.";
	}
	else
	{
		testFailed = shader.getCompileStatus();
		message = "Shader was not expected to compile.";
	}

	if (testFailed)
	{
		log << tcu::TestLog::Message << message << tcu::TestLog::EndMessage;
		ctx.fail(message);
	}
}

std::string getVersionAndExtension (NegativeTestContext& ctx)
{
	const bool				isES32	= contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2));
	const glu::GLSLVersion	version	= isES32 ? glu::GLSL_VERSION_320_ES : glu::GLSL_VERSION_310_ES;

	std::string versionAndExtension = glu::getGLSLVersionDeclaration(version);
	versionAndExtension += " \n";

	if (!isES32)
		versionAndExtension += "#extension GL_OES_sample_variables : require \n";

	return versionAndExtension;
}

void checkSupported (NegativeTestContext& ctx)
{
	const bool isES32 = contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2));

	if (!isES32 && !ctx.isExtensionSupported("GL_OES_sample_variables"))
		TCU_THROW(NotSupportedError, "GL_OES_sample_variables is not supported.");
}

void write_to_read_only_types (NegativeTestContext& ctx)
{
	checkSupported(ctx);

	std::ostringstream	shader;

	struct testConfig
	{
		std::string builtInType;
		std::string varyingCheck;
	} testConfigs[] =
	{
		{"gl_SampleID",			"	lowp int writeValue = 1; \n	gl_SampleID = writeValue; \n"},
		{"gl_SamplePosition",	"	mediump vec2 writeValue = vec2(1.0f, 1.0f); \n	gl_SamplePosition = writeValue; \n"},
		{"gl_SampleMaskIn",		"	lowp int writeValue = 1; \n	gl_SampleMaskIn[0] = writeValue; \n"}
	};

	for (int idx = 0; idx < DE_LENGTH_OF_ARRAY(testConfigs); idx++)
	{
		shader.str("");
		shader
			<< getVersionAndExtension(ctx)
			<< "layout (location = 0) out mediump vec4 fs_color; \n"
			<< "void main() \n"
			<< "{ \n"
			<<		testConfigs[idx].varyingCheck
			<< "	fs_color = vec4(1.0f, 0.0f, 0.0f, 1.0f); \n"
			<< "} \n";

		ctx.beginSection("OES_sample_variables: trying to write to built-in read-only variable" + testConfigs[idx].builtInType);
		verifyShader(ctx, glu::SHADERTYPE_FRAGMENT, shader.str(), EXPECT_RESULT_FAIL);
		ctx.endSection();
	}
}

void access_built_in_types_inside_other_shaders (NegativeTestContext& ctx)
{
	checkSupported(ctx);

	if ((!ctx.isExtensionSupported("GL_EXT_tessellation_shader") && !ctx.isExtensionSupported("GL_OES_tessellation_shader")) ||
		(!ctx.isExtensionSupported("GL_EXT_geometry_shader") && !ctx.isExtensionSupported("GL_OES_geometry_shader")))
	{
		TCU_THROW(NotSupportedError, "tessellation and geometry shader extensions not supported");
	}

	std::ostringstream	shader;

	struct testConfig
	{
		std::string builtInType;
		std::string varyingCheck;
	} testConfigs[] =
	{
		{"gl_SampleID",			"	lowp int writeValue = 1; \n	gl_SampleID = writeValue; \n"},
		{"gl_SamplePosition",	"	mediump vec2 writeValue = vec2(1.0f, 1.0f); \n	gl_SamplePosition = writeValue; \n"},
		{"gl_SampleMaskIn",		"	lowp int writeValue = 1; \n	gl_SampleMaskIn[0] = writeValue; \n"},
		{"gl_SampleMask",		"	highp int readValue = gl_SampleMask[0]; \n"},
	};

	for (int idx = 0; idx < DE_LENGTH_OF_ARRAY(testConfigs); idx++)
	{
		shader.str("");
		shader
			<< getVersionAndExtension(ctx)
			<< "void main () \n"
			<< "{ \n"
			<<		testConfigs[idx].varyingCheck
			<< "	gl_Position = vec4(1.0f, 0.0f, 0.0f , 1.0f); \n"
			<< "} \n";

		ctx.beginSection("OES_sample_variables: trying to use fragment shader built-in sampler variable " + testConfigs[idx].builtInType + " inside vertex shader");
		verifyShader(ctx, glu::SHADERTYPE_VERTEX, shader.str(), EXPECT_RESULT_FAIL);
		ctx.endSection();
	}

	for (int idx = 0; idx < DE_LENGTH_OF_ARRAY(testConfigs); idx++)
	{
		shader.str("");
		shader
			<< getVersionAndExtension(ctx)
			<< "layout (vertices = 3) out; \n"
			<< "void main () \n"
			<< "{ \n"
			<<		testConfigs[idx].varyingCheck
			<< "} \n";

		ctx.beginSection("OES_sample_variables: trying to use fragment shader built-in sampler variable " + testConfigs[idx].builtInType + " inside tessellation control shader");
		verifyShader(ctx, glu::SHADERTYPE_TESSELLATION_CONTROL, shader.str(), EXPECT_RESULT_FAIL);
		ctx.endSection();
	}

	for (int idx = 0; idx < DE_LENGTH_OF_ARRAY(testConfigs); idx++)
	{
		shader.str("");
		shader
			<< getVersionAndExtension(ctx)
			<< "layout (triangles, equal_spacing, ccw) in; \n"
			<< "void main () \n"
			<< "{ \n"
			<<		testConfigs[idx].varyingCheck
			<< "} \n";

		ctx.beginSection("OES_sample_variables: trying to use fragment shader built-in sampler variable " + testConfigs[idx].builtInType + " inside tessellation evaluation shader");
		verifyShader(ctx, glu::SHADERTYPE_TESSELLATION_EVALUATION, shader.str(), EXPECT_RESULT_FAIL);
		ctx.endSection();
	}

	for (int idx = 0; idx < DE_LENGTH_OF_ARRAY(testConfigs); idx++)
	{
		shader.str("");
		shader
			<< getVersionAndExtension(ctx)
			<< "layout (triangles) in; \n"
			<< "layout (triangle_strip, max_vertices = 32) out; \n"
			<< "void main () \n"
			<< "{ \n"
			<<		testConfigs[idx].varyingCheck
			<< "} \n";

		ctx.beginSection("OES_sample_variables: trying to use fragment shader built-in sampler variable " + testConfigs[idx].builtInType + " inside geometry shader");
		verifyShader(ctx, glu::SHADERTYPE_GEOMETRY, shader.str(), EXPECT_RESULT_FAIL);
		ctx.endSection();
	}
}

void index_outside_sample_mask_range (NegativeTestContext& ctx)
{
	checkSupported(ctx);

	std::ostringstream	shader;
	const int			MAX_TYPES	= 2;
	const int			MAX_INDEXES = 2;

	struct testConfig
	{
		std::string builtInType[MAX_TYPES];
		std::string invalidIndex[MAX_INDEXES];
	} testConfigs =
	{
		{
			"gl_SampleMask",
			"gl_SampleMaskIn"
		},
		{
			"	const highp int invalidIndex = (gl_MaxSamples + 31) / 32; \n",
			"	const highp int invalidIndex = -1; \n"
		}
	};

	for (int typeIdx = 0; typeIdx < MAX_TYPES; typeIdx++)
	{
		for (int invalidIdx = 0; invalidIdx < MAX_INDEXES; invalidIdx++)
		{
			shader.str("");
			shader
				<< getVersionAndExtension(ctx)
				<< "layout (location = 0) out mediump vec4 fs_color; \n"
				<< "void main() \n"
				<< "{ \n"
				<<		testConfigs.invalidIndex[invalidIdx]
				<< "	highp int invalidValue = " << testConfigs.builtInType[typeIdx] << "[invalidIndex]; \n"
				<< "	fs_color = vec4(1.0f, 0.0f, 0.0f, 1.0f); \n"
				<< "} \n";

			ctx.beginSection("OES_sample_variables: using constant integral expression outside of " + testConfigs.builtInType[typeIdx] + " bounds");
			verifyShader(ctx, glu::SHADERTYPE_FRAGMENT, shader.str(), EXPECT_RESULT_FAIL);
			ctx.endSection();
		}
	}
}

void access_built_in_types_without_extension (NegativeTestContext& ctx)
{
	checkSupported(ctx);

	std::ostringstream	shader;

	struct testConfig
	{
		std::string builtInType;
		std::string varyingCheck;
	} testConfigs[] =
	{
		{"gl_SampleID",			"	lowp int writeValue = 1; \n	gl_SampleID = writeValue; \n"},
		{"gl_SamplePosition",	"	mediump vec2 writeValue = vec2(1.0f, 1.0f); \n	gl_SamplePosition = writeValue; \n"},
		{"gl_SampleMaskIn",		"	lowp int writeValue = 1; \n	gl_SampleMaskIn[0] = writeValue; \n"},
		{"gl_SampleMask",		"	highp int readValue = gl_SampleMask[0]; \n"},
	};

	for (int idx = 0; idx < DE_LENGTH_OF_ARRAY(testConfigs); idx++)
	{
		shader.str("");
		shader
			<< "#version 310 es \n"
			<< "layout (location = 0) out mediump vec4 fs_color; \n"
			<< "void main() \n"
			<< "{ \n"
			<<		testConfigs[idx].varyingCheck
			<< "	fs_color = vec4(1.0f, 0.0f, 0.0f, 1.0f); \n"
			<< "} \n";

		ctx.beginSection("OES_sample_variables: accessing built-in type " + testConfigs[idx].builtInType + " in shader version 310 ES without required extension");
		verifyShader(ctx, glu::SHADERTYPE_FRAGMENT, shader.str(), EXPECT_RESULT_FAIL);
		ctx.endSection();
	}
}

void redeclare_built_in_types (NegativeTestContext& ctx)
{
	checkSupported(ctx);

	std::ostringstream	shader;
	std::ostringstream	testName;

	const char* const testConfigs[] =
	{
		"gl_SampleID",
		"gl_SamplePosition",
		"gl_SampleMaskIn",
		"gl_SampleMask",
	};

	for (int idx = 0; idx < DE_LENGTH_OF_ARRAY(testConfigs); idx++)
	{
		shader.str("");
		shader
			<< getVersionAndExtension(ctx)
			<< "layout (location = 0) out mediump vec4 fs_color; \n"
			<< "uniform lowp int " << testConfigs[idx] << "; \n"
			<< "void main() \n"
			<< "{ \n"
			<< "	if (" << testConfigs[idx] << " == 0) \n"
			<< "		fs_color = vec4(1.0f, 0.0f, 0.0f, 1.0f); \n"
			<< "	else \n"
			<< "		fs_color = vec4(0.0f, 1.0f, 0.0f, 1.0f); \n"
			<< "} \n";

		testName.str("");
		testName << "OES_sample_variables: redeclare built-in type " << testConfigs[idx];
		ctx.beginSection(testName.str());
		verifyShader(ctx, glu::SHADERTYPE_FRAGMENT, shader.str(), EXPECT_RESULT_FAIL);
		ctx.endSection();
	}
}

} // anonymous

std::vector<FunctionContainer> getNegativeSampleVariablesTestFunctions (void)
{
	const FunctionContainer funcs[] =
	{
		{write_to_read_only_types,						"write_to_read_only_types",						"tests trying writing to read-only built-in sample variables"},
		{access_built_in_types_inside_other_shaders,	"access_built_in_types_inside_other_shaders",	"Tests try to access fragment shader sample variables in other shaders"},
		{index_outside_sample_mask_range,				"index_outside_sample_mask_range",				"tests try to index into built-in sample array types out of bounds"},
		{access_built_in_types_without_extension,		"access_built_in_types_without_extension",		"tests try to access built-in sample types without the correct extension using version 310 es"},
		{redeclare_built_in_types,						"redeclare_built_in_types",						"Tests try to redeclare built-in sample types"},
	};

	return std::vector<FunctionContainer>(DE_ARRAY_BEGIN(funcs), DE_ARRAY_END(funcs));
}

} // NegativeTestShared
} // Functional
} // gles31
} // deqp
<|endoftext|>


<commit_before>/*
 Moses - factored phrase-based language decoder
 Copyright (C) 2010 University of Edinburgh

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

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

 You should have received a copy of the GNU General Public License along
 with this program; if not, write to the Free Software Foundation, Inc.,
 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

 */

#include <algorithm>
#include <cassert>
#include <cmath>
#include <fstream>
#include <sstream>
#include <stdexcept>
#include "StaticData.h"

#include "FeatureVector.h"

using namespace std;

namespace Moses {

  const string FName::SEP = "_";
  FName::Name2Id FName::name2id;
  vector<string> FName::id2name;

  void FName::init(const string& name)  {
    Name2Id::iterator i = name2id.find(name);
    if (i != name2id.end()) {
      m_id = i->second;
    } else {
      m_id = name2id.size();
      name2id[name] = m_id;
      id2name.push_back(name);
    }
  }

  std::ostream& operator<<( std::ostream& out, const FName& name) {
    out << name.name();
    return out;
  }

  size_t FName::hash() const {
    /*std::size_t seed = 0;
		 boost::hash_combine(seed, m_root);
		 boost::hash_combine(seed, m_name);
		 return seed;*/
    return boost::hash_value(m_id);
  }

  const std::string& FName::name() const {
    return id2name[m_id];
  }

  bool FName::operator==(const FName& rhs) const {
    return m_id == rhs.m_id;
  }

  bool FName::operator!=(const FName& rhs) const {
    return ! (*this == rhs);
  }

	FVector::FVector(FValue defaultValue)  {
    m_features[DEFAULT_NAME] = defaultValue;
	}

	void FVector::clear() {
    m_features.clear();
    m_features[DEFAULT_NAME] = DEFAULT;
	}

	void FVector::load(const std::string& filename) {
		ifstream in (filename.c_str());
		if (!in) {
			ostringstream msg;
			msg << "Unable to open " << filename;
			throw runtime_error(msg.str());
		}
		string line;
		while(getline(in,line)) {
			if (line[0] == '#') continue;
			istringstream linestream(line);
			string namestring;
			FValue value;
			linestream >> namestring;
			linestream >> value;
			FName fname(namestring);
			set(fname,value);
		}
  }

  void FVector::save(const string& filename) const {
    ofstream out(filename.c_str());
    if (!out) {
      ostringstream msg;
      msg << "Unable to open " << filename;
      throw runtime_error(msg.str());
    }
    write(out);
    out.close();
  }

  void FVector::write(ostream& out) const {
    for (const_iterator i = begin(); i != end(); ++i) {
      out << i->first << " " << i->second << endl;
    }
  }

  FName FVector::DEFAULT_NAME("DEFAULT","");
  const FValue FVector::DEFAULT = 0;

  static bool equalsTolerance(FValue lhs, FValue rhs) {
    if (lhs == rhs) return true;
    static const FValue TOLERANCE = 1e-4;
    FValue diff = abs(lhs-rhs);
    FValue mean = (abs(lhs)+abs(rhs))/2;
    //cerr << "ET " << lhs << " " << rhs << " " << diff << " " << mean << " " << endl;
    return diff/mean < TOLERANCE ;
  }

  bool FVector::operator== (const FVector& rhs) const {
    if (this == &rhs) {
      return true;
    }
    if (get(DEFAULT_NAME) != rhs.get(DEFAULT_NAME)) return false;
    for (const_iterator i  = begin(); i != end(); ++i) {
      if (!equalsTolerance(i->second,rhs.get(i->first))) return false;
    }
    for (const_iterator i = rhs.begin(); i != rhs.end(); ++i) {
      if (!equalsTolerance(i->second, get(i->first))) return false;
    }
    return true;
  }

  bool FVector::operator!= (const FVector& rhs) const {
    return ! (*this == rhs);
  }

	ProxyFVector FVector::operator[](const FName& name) {
		// At this point, we don't know whether operator[] was called, so we return
		// a proxy object and defer the decision until later
		return ProxyFVector(this, name);

	}

	FValue &FVector::operator[](const FName& name) const {
		return get(name) + get(DEFAULT_NAME);
	}

  ostream& FVector::print(ostream& out) const {
    out << "{";
    for (const_iterator i = begin(); i != end(); ++i) {
      FValue value = i->second;
      if (i->first != DEFAULT_NAME) {
        value += get(DEFAULT_NAME);
      }
      if (i->first != DEFAULT_NAME && i->second != 0.0) {
        out << i->first << "=" << value << ", ";
      }
    }
    out << "}";
    return out;
  }

  ostream& operator<<(ostream& out, const FVector& fv) {
    return fv.print(out);
  }

  const FValue& FVector::get(const FName& name) const {
    const_iterator fi = m_features.find(name);
    if (fi == m_features.end()) {
      return DEFAULT;
    } else {
      return fi->second;
    }
  }

  void FVector::set(const FName& name, const FValue& value) {
    m_features[name] = value;
  }

  FVector& FVector::operator+= (const FVector& rhs) {
    //default value will take care of itself here.
    for (iterator i = begin(); i != end(); ++i) {
      set(i->first,i->second + rhs.get(i->first));
    }
    for (const_iterator i = rhs.begin(); i != rhs.end(); ++i) {
      if (!hasNonDefaultValue(i->first)) {
        set(i->first,i->second);
      }
    }
    return *this;
  }

  FVector& FVector::operator-= (const FVector& rhs) {
    for (iterator i = begin(); i != end(); ++i) {
      set(i->first,i->second - rhs.get(i->first));
    }
    for (const_iterator i = rhs.begin(); i != rhs.end(); ++i) {
      if (!hasNonDefaultValue(i->first)) {
        set(i->first,-(i->second));
      }
    }
    return *this;
  }

  FVector& FVector::operator*= (const FVector& rhs) {
    FValue lhsDefault = get(DEFAULT_NAME);
    FValue rhsDefault = rhs.get(DEFAULT_NAME);
    for (iterator i = begin(); i != end(); ++i) {
      if (i->first == DEFAULT_NAME) {
        set(i->first,lhsDefault*rhsDefault);
      } else {
        FValue lhsValue = i->second;
        FValue rhsValue = rhs.get(i->first);
        set(i->first, lhsValue*rhsDefault + rhsValue*lhsDefault + lhsValue*rhsValue);
      }
    }
    if (lhsDefault) {
      //Features that have the default value in the lhs
      for (const_iterator i = rhs.begin(); i != rhs.end(); ++i) {
        if (!hasNonDefaultValue(i->first)) {
          set(i->first, lhsDefault*i->second);
        }
      }
    }
    return *this;
  }

  FVector& FVector::operator/= (const FVector& rhs) {
    FValue lhsDefault = get(DEFAULT_NAME);
    FValue rhsDefault = rhs.get(DEFAULT_NAME);
    if (lhsDefault && !rhsDefault) {
      throw runtime_error("Attempt to divide feature vectors where lhs has default and rhs does not");
    }
    FValue quotientDefault = 0;
    if (rhsDefault) {
      quotientDefault = lhsDefault / rhsDefault;
    }
    for (iterator i = begin(); i != end(); ++i) {
      if (i->first == DEFAULT_NAME) {
        set(i->first, quotientDefault);
      } else {
        FValue lhsValue = i->second;
        FValue rhsValue = rhs.get(i->first);
        set(i->first, (lhsValue + lhsDefault) / (rhsValue + rhsDefault) - quotientDefault);
      }
    }
    if (lhsDefault) {
      //Features that have the default value in the lhs
      for (const_iterator i = rhs.begin(); i != rhs.end(); ++i) {
        if (!hasNonDefaultValue(i->first)) {
          set(i->first, lhsDefault / (i->second + rhsDefault) - quotientDefault);
        }
      }
    }
    return *this;
  }

	FVector& FVector::max_equals(const FVector& rhs) {
		FValue lhsDefault = get(DEFAULT_NAME);
		FValue rhsDefault = rhs.get(DEFAULT_NAME);
		FValue maxDefault = max(lhsDefault,rhsDefault);
		for (iterator i = begin(); i != end(); ++i) {
			if (i->first == DEFAULT_NAME) {
				set(i->first, maxDefault);
			} else {
				set(i->first, max(i->second + lhsDefault, rhs.get(i->first) + rhsDefault) - maxDefault);
			}
		}
		for (const_iterator i = rhs.begin(); i != rhs.end(); ++i) {
			if (!hasNonDefaultValue(i->first)) {
				set(i->first, max(lhsDefault, (i->second + rhsDefault)) - maxDefault);
			}
		}

		return *this;
	}

  FVector& FVector::operator+= (const FValue& rhs) {
    set(DEFAULT_NAME, get(DEFAULT_NAME) + rhs);
    return *this;
  }

  FVector& FVector::operator-= (const FValue& rhs) {
    set(DEFAULT_NAME, get(DEFAULT_NAME) - rhs);
    return *this;
  }

  FVector& FVector::operator*= (const FValue& rhs) {
    //NB Could do this with boost::bind ?
    //This multiplies the default value, which is what we want
    for (iterator i = begin(); i != end(); ++i) {
      i->second *= rhs;
    }
    return *this;
  }

  FVector& FVector::operator/= (const FValue& rhs) {
		//This dividess the default value, which is what we want
    for (iterator i = begin(); i != end(); ++i) {
      i->second /= rhs;
    }
    return *this;
  }

  FValue FVector::l1norm() const {
    FValue norm = 0;
    for (const_iterator i = begin(); i != end(); ++i) {
      if (!(i->second) && i->first == DEFAULT_NAME) {
        throw runtime_error("Cannot take l1norm with non-zero default values");
      }
      norm += abs(i->second);
    }
    return norm;
  }

  FValue FVector::sum() const {
    FValue sum = 0;
    for (const_iterator i = begin(); i != end(); ++i) {
      if (!(i->second) && i->first == DEFAULT_NAME) {
        throw runtime_error("Cannot take sum with non-zero default values");
      }
      sum += i->second;
    }
    return sum;
  }

  FValue FVector::l2norm() const {
    return sqrt(inner_product(*this));
  }

  FValue FVector::inner_product(const FVector& rhs) const {
    FValue lhsDefault = get(DEFAULT_NAME);
    FValue rhsDefault = rhs.get(DEFAULT_NAME);
    if (lhsDefault && rhsDefault) {
      throw runtime_error("Cannot take inner product if both lhs and rhs have non-zero default values");
    }
    FValue product = 0.0;
    for (const_iterator i = begin(); i != end(); ++i) {
      if (i->first != DEFAULT_NAME) {
        product += ((i->second + lhsDefault)*(rhs.get(i->first) + rhsDefault));
      }
    }

    if (lhsDefault) {
      //Features that have the default value in the rhs
      for (const_iterator i = rhs.begin(); i != rhs.end(); ++i) {
        if (!hasNonDefaultValue(i->first)) {
          product += (i->second + rhsDefault)*lhsDefault;
        }
      }
    }
    return product;
  }

  FValue FVector::inner_product(const std::vector<FValue>& rhs) const {
      assert(size() == rhs.size());
      const ScoreIndexManager &sim = StaticData::Instance().GetScoreIndexManager;
      FValue product = 0;
      if (get(DEFAULT_NAME) == 0) {
	  for (const_iterator i = cbegin(); i != cend(); i++)
	      FValue rv = rhs[ sim.GetFeatureIndex(i->first) ];
	      product += *i * rv;
      } else {
	  for (size_t i = 0; i < rhs.size(); i++) {
	      product += rhs[i] * get(sim.GetFeatureName(i));
	  }
      }
      return product;
  }

  const FVector operator+(const FVector& lhs, const FVector& rhs) {
    return FVector(lhs) += rhs;
  }

  const FVector operator-(const FVector& lhs, const FVector& rhs) {
    return FVector(lhs) -= rhs;
  }

	const FVector operator*(const FVector& lhs, const FVector& rhs) {
    return FVector(lhs) *= rhs;
  }

  const FVector operator/(const FVector& lhs, const FVector& rhs) {
    return FVector(lhs) /= rhs;
  }

  const FVector operator+(const FVector& lhs, const FValue& rhs) {
    return FVector(lhs) += rhs;
  }

  const FVector operator-(const FVector& lhs, const FValue& rhs) {
    return FVector(lhs) -= rhs;
  }

  const FVector operator*(const FVector& lhs, const FValue& rhs) {
    return FVector(lhs) *= rhs;
  }

  const FVector operator/(const FVector& lhs, const FValue& rhs) {
    return FVector(lhs) /= rhs;
  }

  const FVector fvmax(const FVector& lhs, const FVector& rhs) {
    return FVector(lhs).max_equals(rhs);
  }

  FValue inner_product(const FVector& lhs, const FVector& rhs) {
    if (lhs.size() >= rhs.size()) {
      return rhs.inner_product(lhs);
    } else {
      return lhs.inner_product(rhs);
    }
  }

}
<commit_msg>Got rid of 'discards qualifiers' errors in FeatureVector.cpp.<commit_after>/*
 Moses - factored phrase-based language decoder
 Copyright (C) 2010 University of Edinburgh

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

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

 You should have received a copy of the GNU General Public License along
 with this program; if not, write to the Free Software Foundation, Inc.,
 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

 */

#include <algorithm>
#include <cassert>
#include <cmath>
#include <fstream>
#include <sstream>
#include <stdexcept>
#include "StaticData.h"

#include "FeatureVector.h"

using namespace std;

namespace Moses {

  const string FName::SEP = "_";
  FName::Name2Id FName::name2id;
  vector<string> FName::id2name;

  void FName::init(const string& name)  {
    Name2Id::iterator i = name2id.find(name);
    if (i != name2id.end()) {
      m_id = i->second;
    } else {
      m_id = name2id.size();
      name2id[name] = m_id;
      id2name.push_back(name);
    }
  }

  std::ostream& operator<<( std::ostream& out, const FName& name) {
    out << name.name();
    return out;
  }

  size_t FName::hash() const {
    /*std::size_t seed = 0;
		 boost::hash_combine(seed, m_root);
		 boost::hash_combine(seed, m_name);
		 return seed;*/
    return boost::hash_value(m_id);
  }

  const std::string& FName::name() const {
    return id2name[m_id];
  }

  bool FName::operator==(const FName& rhs) const {
    return m_id == rhs.m_id;
  }

  bool FName::operator!=(const FName& rhs) const {
    return ! (*this == rhs);
  }

	FVector::FVector(FValue defaultValue)  {
    m_features[DEFAULT_NAME] = defaultValue;
	}

	void FVector::clear() {
    m_features.clear();
    m_features[DEFAULT_NAME] = DEFAULT;
	}

	void FVector::load(const std::string& filename) {
		ifstream in (filename.c_str());
		if (!in) {
			ostringstream msg;
			msg << "Unable to open " << filename;
			throw runtime_error(msg.str());
		}
		string line;
		while(getline(in,line)) {
			if (line[0] == '#') continue;
			istringstream linestream(line);
			string namestring;
			FValue value;
			linestream >> namestring;
			linestream >> value;
			FName fname(namestring);
			set(fname,value);
		}
  }

  void FVector::save(const string& filename) const {
    ofstream out(filename.c_str());
    if (!out) {
      ostringstream msg;
      msg << "Unable to open " << filename;
      throw runtime_error(msg.str());
    }
    write(out);
    out.close();
  }

  void FVector::write(ostream& out) const {
    for (const_iterator i = cbegin(); i != cend(); ++i) {
      out << i->first << " " << i->second << endl;
    }
  }

  FName FVector::DEFAULT_NAME("DEFAULT","");
  const FValue FVector::DEFAULT = 0;

  static bool equalsTolerance(FValue lhs, FValue rhs) {
    if (lhs == rhs) return true;
    static const FValue TOLERANCE = 1e-4;
    FValue diff = abs(lhs-rhs);
    FValue mean = (abs(lhs)+abs(rhs))/2;
    //cerr << "ET " << lhs << " " << rhs << " " << diff << " " << mean << " " << endl;
    return diff/mean < TOLERANCE ;
  }

  bool FVector::operator== (const FVector& rhs) const {
    if (this == &rhs) {
      return true;
    }
    if (get(DEFAULT_NAME) != rhs.get(DEFAULT_NAME)) return false;
    for (const_iterator i  = cbegin(); i != cend(); ++i) {
      if (!equalsTolerance(i->second,rhs.get(i->first))) return false;
    }
    for (const_iterator i = rhs.cbegin(); i != rhs.cend(); ++i) {
      if (!equalsTolerance(i->second, get(i->first))) return false;
    }
    return true;
  }

  bool FVector::operator!= (const FVector& rhs) const {
    return ! (*this == rhs);
  }

	ProxyFVector FVector::operator[](const FName& name) {
		// At this point, we don't know whether operator[] was called, so we return
		// a proxy object and defer the decision until later
		return ProxyFVector(this, name);

	}

	FValue &FVector::operator[](const FName& name) const {
		return get(name) + get(DEFAULT_NAME);
	}

  ostream& FVector::print(ostream& out) const {
    out << "{";
    for (const_iterator i = cbegin(); i != cend(); ++i) {
      FValue value = i->second;
      if (i->first != DEFAULT_NAME) {
        value += get(DEFAULT_NAME);
      }
      if (i->first != DEFAULT_NAME && i->second != 0.0) {
        out << i->first << "=" << value << ", ";
      }
    }
    out << "}";
    return out;
  }

  ostream& operator<<(ostream& out, const FVector& fv) {
    return fv.print(out);
  }

  const FValue& FVector::get(const FName& name) const {
    const_iterator fi = m_features.find(name);
    if (fi == m_features.end()) {
      return DEFAULT;
    } else {
      return fi->second;
    }
  }

  void FVector::set(const FName& name, const FValue& value) {
    m_features[name] = value;
  }

  FVector& FVector::operator+= (const FVector& rhs) {
    //default value will take care of itself here.
    for (iterator i = begin(); i != end(); ++i) {
      set(i->first,i->second + rhs.get(i->first));
    }
    for (const_iterator i = rhs.cbegin(); i != rhs.cend(); ++i) {
      if (!hasNonDefaultValue(i->first)) {
        set(i->first,i->second);
      }
    }
    return *this;
  }

  FVector& FVector::operator-= (const FVector& rhs) {
    for (iterator i = begin(); i != end(); ++i) {
      set(i->first,i->second - rhs.get(i->first));
    }
    for (const_iterator i = rhs.cbegin(); i != rhs.cend(); ++i) {
      if (!hasNonDefaultValue(i->first)) {
        set(i->first,-(i->second));
      }
    }
    return *this;
  }

  FVector& FVector::operator*= (const FVector& rhs) {
    FValue lhsDefault = get(DEFAULT_NAME);
    FValue rhsDefault = rhs.get(DEFAULT_NAME);
    for (iterator i = begin(); i != end(); ++i) {
      if (i->first == DEFAULT_NAME) {
        set(i->first,lhsDefault*rhsDefault);
      } else {
        FValue lhsValue = i->second;
        FValue rhsValue = rhs.get(i->first);
        set(i->first, lhsValue*rhsDefault + rhsValue*lhsDefault + lhsValue*rhsValue);
      }
    }
    if (lhsDefault) {
      //Features that have the default value in the lhs
      for (const_iterator i = rhs.cbegin(); i != rhs.cend(); ++i) {
        if (!hasNonDefaultValue(i->first)) {
          set(i->first, lhsDefault*i->second);
        }
      }
    }
    return *this;
  }

  FVector& FVector::operator/= (const FVector& rhs) {
    FValue lhsDefault = get(DEFAULT_NAME);
    FValue rhsDefault = rhs.get(DEFAULT_NAME);
    if (lhsDefault && !rhsDefault) {
      throw runtime_error("Attempt to divide feature vectors where lhs has default and rhs does not");
    }
    FValue quotientDefault = 0;
    if (rhsDefault) {
      quotientDefault = lhsDefault / rhsDefault;
    }
    for (iterator i = begin(); i != end(); ++i) {
      if (i->first == DEFAULT_NAME) {
        set(i->first, quotientDefault);
      } else {
        FValue lhsValue = i->second;
        FValue rhsValue = rhs.get(i->first);
        set(i->first, (lhsValue + lhsDefault) / (rhsValue + rhsDefault) - quotientDefault);
      }
    }
    if (lhsDefault) {
      //Features that have the default value in the lhs
      for (const_iterator i = rhs.cbegin(); i != rhs.cend(); ++i) {
        if (!hasNonDefaultValue(i->first)) {
          set(i->first, lhsDefault / (i->second + rhsDefault) - quotientDefault);
        }
      }
    }
    return *this;
  }

	FVector& FVector::max_equals(const FVector& rhs) {
		FValue lhsDefault = get(DEFAULT_NAME);
		FValue rhsDefault = rhs.get(DEFAULT_NAME);
		FValue maxDefault = max(lhsDefault,rhsDefault);
		for (iterator i = begin(); i != end(); ++i) {
			if (i->first == DEFAULT_NAME) {
				set(i->first, maxDefault);
			} else {
				set(i->first, max(i->second + lhsDefault, rhs.get(i->first) + rhsDefault) - maxDefault);
			}
		}
		for (const_iterator i = rhs.cbegin(); i != rhs.cend(); ++i) {
			if (!hasNonDefaultValue(i->first)) {
				set(i->first, max(lhsDefault, (i->second + rhsDefault)) - maxDefault);
			}
		}

		return *this;
	}

  FVector& FVector::operator+= (const FValue& rhs) {
    set(DEFAULT_NAME, get(DEFAULT_NAME) + rhs);
    return *this;
  }

  FVector& FVector::operator-= (const FValue& rhs) {
    set(DEFAULT_NAME, get(DEFAULT_NAME) - rhs);
    return *this;
  }

  FVector& FVector::operator*= (const FValue& rhs) {
    //NB Could do this with boost::bind ?
    //This multiplies the default value, which is what we want
    for (iterator i = begin(); i != end(); ++i) {
      i->second *= rhs;
    }
    return *this;
  }

  FVector& FVector::operator/= (const FValue& rhs) {
		//This dividess the default value, which is what we want
    for (iterator i = begin(); i != end(); ++i) {
      i->second /= rhs;
    }
    return *this;
  }

  FValue FVector::l1norm() const {
    FValue norm = 0;
    for (const_iterator i = cbegin(); i != cend(); ++i) {
      if (!(i->second) && i->first == DEFAULT_NAME) {
        throw runtime_error("Cannot take l1norm with non-zero default values");
      }
      norm += abs(i->second);
    }
    return norm;
  }

  FValue FVector::sum() const {
    FValue sum = 0;
    for (const_iterator i = cbegin(); i != cend(); ++i) {
      if (!(i->second) && i->first == DEFAULT_NAME) {
        throw runtime_error("Cannot take sum with non-zero default values");
      }
      sum += i->second;
    }
    return sum;
  }

  FValue FVector::l2norm() const {
    return sqrt(inner_product(*this));
  }

  FValue FVector::inner_product(const FVector& rhs) const {
    FValue lhsDefault = get(DEFAULT_NAME);
    FValue rhsDefault = rhs.get(DEFAULT_NAME);
    if (lhsDefault && rhsDefault) {
      throw runtime_error("Cannot take inner product if both lhs and rhs have non-zero default values");
    }
    FValue product = 0.0;
    for (const_iterator i = cbegin(); i != cend(); ++i) {
      if (i->first != DEFAULT_NAME) {
        product += ((i->second + lhsDefault)*(rhs.get(i->first) + rhsDefault));
      }
    }

    if (lhsDefault) {
      //Features that have the default value in the rhs
      for (const_iterator i = rhs.cbegin(); i != rhs.cend(); ++i) {
        if (!hasNonDefaultValue(i->first)) {
          product += (i->second + rhsDefault)*lhsDefault;
        }
      }
    }
    return product;
  }

  FValue FVector::inner_product(const std::vector<FValue>& rhs) const {
      assert(size() == rhs.size());
      const ScoreIndexManager &sim = StaticData::Instance().GetScoreIndexManager;
      FValue product = 0;
      if (get(DEFAULT_NAME) == 0) {
	  for (const_iterator i = cbegin(); i != cend(); i++)
	      FValue rv = rhs[ sim.GetFeatureIndex(i->first) ];
	      product += *i * rv;
      } else {
	  for (size_t i = 0; i < rhs.size(); i++) {
	      product += rhs[i] * get(sim.GetFeatureName(i));
	  }
      }
      return product;
  }

  const FVector operator+(const FVector& lhs, const FVector& rhs) {
    return FVector(lhs) += rhs;
  }

  const FVector operator-(const FVector& lhs, const FVector& rhs) {
    return FVector(lhs) -= rhs;
  }

	const FVector operator*(const FVector& lhs, const FVector& rhs) {
    return FVector(lhs) *= rhs;
  }

  const FVector operator/(const FVector& lhs, const FVector& rhs) {
    return FVector(lhs) /= rhs;
  }

  const FVector operator+(const FVector& lhs, const FValue& rhs) {
    return FVector(lhs) += rhs;
  }

  const FVector operator-(const FVector& lhs, const FValue& rhs) {
    return FVector(lhs) -= rhs;
  }

  const FVector operator*(const FVector& lhs, const FValue& rhs) {
    return FVector(lhs) *= rhs;
  }

  const FVector operator/(const FVector& lhs, const FValue& rhs) {
    return FVector(lhs) /= rhs;
  }

  const FVector fvmax(const FVector& lhs, const FVector& rhs) {
    return FVector(lhs).max_equals(rhs);
  }

  FValue inner_product(const FVector& lhs, const FVector& rhs) {
    if (lhs.size() >= rhs.size()) {
      return rhs.inner_product(lhs);
    } else {
      return lhs.inner_product(rhs);
    }
  }

}
<|endoftext|>


<commit_before>#include "graphics/dgl.h"
#include "2d/sceneobject/Path.h"

#include "2d/sceneobject/Path_ScriptBinding.h"

IMPLEMENT_CONOBJECT(Path);

PathObject::PathObject():
   mObj(NULL),
   mPath(NULL)
{
   mCurrNode = 0;
   mPrevNode = 0;
   mLoop = true;
   mOrient = false;
   mSnapToNode = false;
   mLoopCount = 0;
   mMaxLoop = -1;
   mMaxSpeed = 1.0f;
   mAngOff = 0.0f;
}

void PathObject::setCurrNode(S32 node)
{
}

void PathObject::setNextNode(S32 node)
{
}

void PathObject::setPrevNode(S32 node)
{
}

Path::Path()
{

   // Use a static body by default.
   mBodyDefinition.type = b2_staticBody;

   VECTOR_SET_ASSOCIATION(mObjs);
   VECTOR_SET_ASSOCIATION(mNodes);
}

Path::~Path()
{

}

void Path::initPersistFields()
{
   Parent::initPersistFields();
}

void Path::preIntegrate(const F32 totalTime, const F32 elapsedTime, DebugStats * pDebugStats)
{
   Parent::preIntegrate(totalTime, elapsedTime, pDebugStats);

   Vector<PathObject*>::iterator i;
   for (i = mObjs.begin(); i != mObjs.end(); i++)
   {
      bool stop = false;
      PathObject &pObj = *(*i);

      Vector2 cPos = pObj.mObj->getPosition();
      Node &cNode = mNodes[pObj.mCurrNode];
      Vector2 cDst = mNodes[pObj.mCurrNode].position;
      F32 distance = (cDst - cPos).Length();

      if (distance < (pObj.mMaxSpeed * elapsedTime) || distance <= cNode.distance)
      {
         S32 nCount = mNodes.size();
         S32 end = nCount - 1;
         if (pObj.mCurrNode == end)
         {
            if (pObj.mLoop)
            {
               pObj.mLoopCount++;
               if ((pObj.mMaxLoop > 0) && (pObj.mLoopCount >= pObj.mMaxLoop))
               {
                  Con::printf("why we stopping?");
                  stop = true;
               }
               else
               {
                  Con::printf("back to 0");
                  pObj.mPrevNode = pObj.mCurrNode;
                  pObj.mCurrNode = 0;
                  pObj.mNextNode = pObj.mCurrNode;
               }
            }
            else
            {
               stop = true;
            }
         }
         else
         {
            pObj.mPrevNode = pObj.mCurrNode;
            pObj.mCurrNode = pObj.mCurrNode + 1;
            pObj.mNextNode = pObj.mCurrNode;
         }

         if (pObj.mCurrNode >= nCount)
         {
            pObj.mCurrNode = 0;
            pObj.mNextNode = pObj.mCurrNode;
         }
         else if (pObj.mCurrNode < 0)
         {
            pObj.mCurrNode = 0;
            pObj.mNextNode = pObj.mCurrNode;
         }

      }

      if (!stop)
      {
         moveObject(pObj);
      }

      else
      {
         pObj.mObj->setLinearVelocity(Vector2(0.0f, 0.0f));
      }

   }

}

void Path::integrateObject(const F32 totalTime, const F32 elapsedTime, DebugStats * pDebugStats)
{
   Parent::integrateObject(totalTime, elapsedTime, pDebugStats);
}

S32 Path::addNode(Vector2 pos, F32 distance, F32 weight)
{
   S32 nodeCount = mNodes.size();

   mNodes.push_back(Node(pos, distance, weight));

   return nodeCount;
}

void Path::attachObject(SceneObject * object, F32 speed, bool orientToPath, F32 angleOff, bool snapToNode, S32 startNode, bool loop, S32 maxLoop)
{
   if (snapToNode)
   {
      if ((startNode >= 0) && (startNode < mNodes.size()))
         object->setPosition(mNodes[startNode].position);
   }

   object->setLinearVelocity(Vector2::getZero());

   deleteNotify(object);

   PathObject *pObj  = new PathObject();
   pObj->mPath       = this;
   pObj->mObj        = object;
   pObj->mObjId      = object->getId();
   pObj->mOrient     = orientToPath;
   pObj->mAngOff     = angleOff;
   pObj->mLoop       = loop;
   pObj->mMaxLoop    = maxLoop;
   pObj->mMaxSpeed   = speed;
   pObj->mCurrNode   = startNode;
   pObj->mNextNode   = startNode;

   mObjs.push_back(pObj);
}

void Path::detachObject(SceneObject * object)
{
   if (!object)
      return;

   Vector<PathObject*>::iterator i;

   for (i = mObjs.begin(); i != mObjs.end(); i++)
   {
      PathObject *pObj = (*i);
      if(object == pObj->mObj)
      {
         if (!pObj->mObj.isNull())
         {
            pObj->mObj->setLinearVelocity(Vector2(0, 0));
            clearNotify(pObj->mObj);
         }

         delete pObj;

         mObjs.erase_fast(i);

         break;
      }
   }
}

void Path::moveObject(PathObject& obj)
{
   Vector2 cDest = mNodes[obj.mNextNode].position;
   Vector2 oPos = obj.mObj->getPosition();
   Vector2 dir = cDest - oPos;
   dir.Normalize();

   obj.mObj->setLinearVelocity(dir * obj.mMaxSpeed);

   if (obj.mOrient)
   {
      F32 rot = mRadToDeg(mAtan(dir.x, dir.y));
      rot = rot - obj.mAngOff;
      F32 ang = mDegToRad(rot);
      F32 speed = obj.mMaxSpeed;
      obj.mObj->rotateTo(ang, speed);
   }

}

void Path::onDeleteNotify(SimObject* object)
{
   Vector<PathObject*>::iterator i;

   SimObjectId objId = object->getId();

   for (i = mObjs.begin(); i != mObjs.end(); i++)
   {
      if ((*i)->mObjId == objId)
      {
         delete (*i);

         mObjs.erase_fast(i);

         break;
      }
   }
}
<commit_msg>Cleanup<commit_after>#include "graphics/dgl.h"
#include "2d/sceneobject/Path.h"

#include "2d/sceneobject/Path_ScriptBinding.h"

IMPLEMENT_CONOBJECT(Path);

PathObject::PathObject():
   mObj(NULL),
   mPath(NULL)
{
   mCurrNode = 0;
   mPrevNode = 0;
   mLoop = true;
   mOrient = false;
   mSnapToNode = false;
   mLoopCount = 0;
   mMaxLoop = -1;
   mMaxSpeed = 1.0f;
   mAngOff = 0.0f;
}

void PathObject::setCurrNode(S32 node)
{
}

void PathObject::setNextNode(S32 node)
{
}

void PathObject::setPrevNode(S32 node)
{
}

Path::Path()
{

   // Use a static body by default.
   mBodyDefinition.type = b2_staticBody;

   VECTOR_SET_ASSOCIATION(mObjs);
   VECTOR_SET_ASSOCIATION(mNodes);
}

Path::~Path()
{

}

void Path::initPersistFields()
{
   Parent::initPersistFields();
}

void Path::preIntegrate(const F32 totalTime, const F32 elapsedTime, DebugStats * pDebugStats)
{
   Parent::preIntegrate(totalTime, elapsedTime, pDebugStats);

   Vector<PathObject*>::iterator i;
   for (i = mObjs.begin(); i != mObjs.end(); i++)
   {
      bool stop = false;
      PathObject &pObj = *(*i);

      Vector2 cPos = pObj.mObj->getPosition();
      Node &cNode = mNodes[pObj.mCurrNode];
      Vector2 cDst = mNodes[pObj.mCurrNode].position;
      F32 distance = (cDst - cPos).Length();

      if (distance < (pObj.mMaxSpeed * elapsedTime) || distance <= cNode.distance)
      {
         S32 nCount = mNodes.size();
         S32 end = nCount - 1;
         if (pObj.mCurrNode == end)
         {
            if (pObj.mLoop)
            {
               pObj.mLoopCount++;
               if ((pObj.mMaxLoop > 0) && (pObj.mLoopCount >= pObj.mMaxLoop))
               {
                  stop = true;
               }
               else
               {
                  pObj.mPrevNode = pObj.mCurrNode;
                  pObj.mCurrNode = 0;
                  pObj.mNextNode = pObj.mCurrNode;
               }
            }
            else
            {
               stop = true;
            }
         }
         else
         {
            pObj.mPrevNode = pObj.mCurrNode;
            pObj.mCurrNode = pObj.mCurrNode + 1;
            pObj.mNextNode = pObj.mCurrNode;
         }

         if (pObj.mCurrNode >= nCount)
         {
            pObj.mCurrNode = 0;
            pObj.mNextNode = pObj.mCurrNode;
         }
         else if (pObj.mCurrNode < 0)
         {
            pObj.mCurrNode = 0;
            pObj.mNextNode = pObj.mCurrNode;
         }

      }

      if (!stop)
      {
         moveObject(pObj);
      }

      else
      {
         pObj.mObj->setLinearVelocity(Vector2(0.0f, 0.0f));
      }

   }

}

void Path::integrateObject(const F32 totalTime, const F32 elapsedTime, DebugStats * pDebugStats)
{
   Parent::integrateObject(totalTime, elapsedTime, pDebugStats);
}

S32 Path::addNode(Vector2 pos, F32 distance, F32 weight)
{
   S32 nodeCount = mNodes.size();

   mNodes.push_back(Node(pos, distance, weight));

   return nodeCount;
}

void Path::attachObject(SceneObject * object, F32 speed, bool orientToPath, F32 angleOff, bool snapToNode, S32 startNode, bool loop, S32 maxLoop)
{
   if (snapToNode)
   {
      if ((startNode >= 0) && (startNode < mNodes.size()))
         object->setPosition(mNodes[startNode].position);
   }

   object->setLinearVelocity(Vector2::getZero());

   deleteNotify(object);

   PathObject *pObj  = new PathObject();
   pObj->mPath       = this;
   pObj->mObj        = object;
   pObj->mObjId      = object->getId();
   pObj->mOrient     = orientToPath;
   pObj->mAngOff     = angleOff;
   pObj->mLoop       = loop;
   pObj->mMaxLoop    = maxLoop;
   pObj->mMaxSpeed   = speed;
   pObj->mCurrNode   = startNode;
   pObj->mNextNode   = startNode;

   mObjs.push_back(pObj);
}

void Path::detachObject(SceneObject * object)
{
   if (!object)
      return;

   Vector<PathObject*>::iterator i;

   for (i = mObjs.begin(); i != mObjs.end(); i++)
   {
      PathObject *pObj = (*i);
      if(object == pObj->mObj)
      {
         if (!pObj->mObj.isNull())
         {
            pObj->mObj->setLinearVelocity(Vector2(0, 0));
            clearNotify(pObj->mObj);
         }

         delete pObj;

         mObjs.erase_fast(i);

         break;
      }
   }
}

void Path::moveObject(PathObject& obj)
{
   Vector2 cDest = mNodes[obj.mNextNode].position;
   Vector2 oPos = obj.mObj->getPosition();
   Vector2 dir = cDest - oPos;
   dir.Normalize();

   obj.mObj->setLinearVelocity(dir * obj.mMaxSpeed);

   if (obj.mOrient)
   {
      F32 rot = mRadToDeg(mAtan(dir.x, dir.y));
      rot = rot - obj.mAngOff;
      F32 ang = mDegToRad(rot);
      F32 speed = obj.mMaxSpeed;
      obj.mObj->rotateTo(ang, speed);
   }

}

void Path::onDeleteNotify(SimObject* object)
{
   Vector<PathObject*>::iterator i;

   SimObjectId objId = object->getId();

   for (i = mObjs.begin(); i != mObjs.end(); i++)
   {
      if ((*i)->mObjId == objId)
      {
         delete (*i);

         mObjs.erase_fast(i);

         break;
      }
   }
}
<|endoftext|>


<commit_before>/*=========================================================================

  Program:   ORFEO Toolbox
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  See OTBCopyright.txt for details.

  Copyright (c) GET / ENST Bretagne. All rights reserved.
  See GETCopyright.txt for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#ifndef __otbChangeProfileKernelFunctor_txx
#define __otbChangeProfileKernelFunctor_txx

#include "otbChangeProfileKernelFunctor.h"

namespace otb
{

ChangeProfileKernelFunctor
::ChangeProfileKernelFunctor ()
		: GenericKernelFunctorBase ()
{
	m_Coef = 0.0;
	m_Degree = 1.0;
	m_Gamma = 1.0;

	SetValue( "Coef", m_Coef );
	SetValue( "Degree", m_Degree );
	SetValue( "Gamma", m_Gamma );
}

void
ChangeProfileKernelFunctor
::Update ()
{
	m_Coef = GetValue<double>( "Coef" );
	m_Degree = GetValue<double>( "Degree" );
	m_Gamma = GetValue<double>( "Gamma" );
}

double
ChangeProfileKernelFunctor
::operator() ( const svm_node * x, const svm_node * y,
				const svm_parameter & param ) const
{
	double theMax = 0.0;
	double theCur;

	while(x->index != -1 && y->index != -1)
	{
		if(x->index == y->index)
		{
			theCur = fabs( x->value - y->value );
			++x;
			++y;
		}
		else
		{
			if(x->index > y->index)
				++y;
			else
				++x;
		}

		if ( theCur > theMax )
			theMax = theCur;
	}

	return exp( - m_Gamma * pow( theMax, m_Degree ) + m_Coef );
}

} // end of namespace otb

#endif

<commit_msg>COMP: missing include<commit_after>/*=========================================================================

  Program:   ORFEO Toolbox
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  See OTBCopyright.txt for details.

  Copyright (c) GET / ENST Bretagne. All rights reserved.
  See GETCopyright.txt for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#ifndef __otbChangeProfileKernelFunctor_txx
#define __otbChangeProfileKernelFunctor_txx

#include <cmath>
#include "otbChangeProfileKernelFunctor.h"

namespace otb
{

ChangeProfileKernelFunctor
::ChangeProfileKernelFunctor ()
		: GenericKernelFunctorBase ()
{
	m_Coef = 0.0;
	m_Degree = 1.0;
	m_Gamma = 1.0;

	SetValue( "Coef", m_Coef );
	SetValue( "Degree", m_Degree );
	SetValue( "Gamma", m_Gamma );
}

void
ChangeProfileKernelFunctor
::Update ()
{
	m_Coef = GetValue<double>( "Coef" );
	m_Degree = GetValue<double>( "Degree" );
	m_Gamma = GetValue<double>( "Gamma" );
}

double
ChangeProfileKernelFunctor
::operator() ( const svm_node * x, const svm_node * y,
				const svm_parameter & param ) const
{
	double theMax = 0.0;
	double theCur;

	while(x->index != -1 && y->index != -1)
	{
		if(x->index == y->index)
		{
			theCur = fabs( x->value - y->value );
			++x;
			++y;
		}
		else
		{
			if(x->index > y->index)
				++y;
			else
				++x;
		}

		if ( theCur > theMax )
			theMax = theCur;
	}

	return exp( - m_Gamma * pow( theMax, m_Degree ) + m_Coef );
}

} // end of namespace otb

#endif

<|endoftext|>


<commit_before>#include "ChatSession.h"

namespace TelepathyIM
{
	ChatSession::ChatSession(Tp::TextChannelPtr tp_text_channel) : tp_text_channel_(tp_text_channel), state_(STATE_INITIALIZING)
	{
		Tp::Features features;
		features.insert(Tp::TextChannel::FeatureMessageQueue);
		features.insert(Tp::TextChannel::FeatureCore);
		features.insert(Tp::TextChannel::FeatureMessageCapabilities);
		connect(tp_text_channel_->becomeReady(features), SIGNAL( finished(Tp::PendingOperation*) ), SLOT( OnTextChannelReady(Tp::PendingOperation*)) );
	}

	ChatSession::~ChatSession()
	{
		//! @todo IMPLEMENT

		if (state_ == STATE_OPEN)
			Close();
	}

	void ChatSession::SendMessage(const QString &text)
	{
		if (state_ == STATE_CLOSED)
			throw Core::Exception("Channel closed");

		if (state_ == STATE_INITIALIZING)
		{
			send_buffer_.push_back(text);
			return;
		}

		Tp::PendingSendMessage* p = tp_text_channel_->send( text );

		//! @todo Connect this signal to actual message object
		connect(p, SIGNAL( finished(Tp::PendingOperation* operation) ), SLOT( OnMessageSendAck(Tp::PendingOperation*) ));
	}

	Communication::ChatSessionInterface::State ChatSession::GetState() const
	{
		return state_;
	}

	void ChatSession::Close()
	{
		//! @todo IMPLEMENT
	}

	Communication::ChatSessionParticipantVector ChatSession::GetParticipants() const
	{
		Communication::ChatSessionParticipantVector participants;
		for (ChatSessionParticipantVector::const_iterator i = participants_.begin(); i != participants_.end(); ++i)
		{
			participants.push_back( *i );
		}

		return participants;
	}

	Communication::ChatMessageVector ChatSession::GetMessageHistory()
	{
		Communication::ChatMessageVector messages;
		for (ChatMessageVector::iterator i = message_history_.begin(); i != message_history_.end(); ++i)
		{
			messages.push_back( *i );
		}
		return messages;
	}

	void ChatSession::OnTextChannelCreated(Tp::PendingOperation* op)
	{
		//if ( op->isError() )
		//{
		//	LogError("Cannot create TextChannel object");
		//	return;
		//}
		//LogInfo("TextChannel object created");

		//Tp::PendingChannel *pChannel = qobject_cast<Tp::PendingChannel *>(op);
		//Tp::ChannelPtr text_channel = pChannel->channel();

		//tp_text_channel_ = Tp::TextChannelPtr( dynamic_cast<Tp::TextChannel *>(text_channel.data()) );

		//QObject::connect(tp_text_channel_->becomeReady(Tp::TextChannel::FeatureMessageQueue),
		//	     SIGNAL( finished(Tp::PendingOperation*) ),
		//		SLOT( OnChannelReady(Tp::PendingOperation*)) );
	}

	void ChatSession::OnTextChannelReady(Tp::PendingOperation* op)
	{
		for (QStringList::iterator i = send_buffer_.begin(); i != send_buffer_.end(); ++i)
		{
			SendMessage( *i);
		}
	}

	void ChatSession::OnMessageSendAck(Tp::PendingOperation* op)
	{
		//! @todo Move this slot to actual message object
		//! @todo IMPLEMENT
	}

} // end of namespace: TelepathyIM
<commit_msg>added missing function (empty) implementation<commit_after>#include "ChatSession.h"

namespace TelepathyIM
{
	ChatSession::ChatSession(Tp::TextChannelPtr tp_text_channel) : tp_text_channel_(tp_text_channel), state_(STATE_INITIALIZING)
	{
		Tp::Features features;
		features.insert(Tp::TextChannel::FeatureMessageQueue);
		features.insert(Tp::TextChannel::FeatureCore);
		features.insert(Tp::TextChannel::FeatureMessageCapabilities);
		connect(tp_text_channel_->becomeReady(features), SIGNAL( finished(Tp::PendingOperation*) ), SLOT( OnTextChannelReady(Tp::PendingOperation*)) );
	}

	ChatSession::~ChatSession()
	{
		//! @todo IMPLEMENT

		if (state_ == STATE_OPEN)
			Close();
	}

	void ChatSession::SendMessage(const QString &text)
	{
		if (state_ == STATE_CLOSED)
			throw Core::Exception("Channel closed");

		if (state_ == STATE_INITIALIZING)
		{
			send_buffer_.push_back(text);
			return;
		}

		Tp::PendingSendMessage* p = tp_text_channel_->send( text );

		//! @todo Connect this signal to actual message object
		connect(p, SIGNAL( finished(Tp::PendingOperation* operation) ), SLOT( OnMessageSendAck(Tp::PendingOperation*) ));
	}

	Communication::ChatSessionInterface::State ChatSession::GetState() const
	{
		return state_;
	}

	void ChatSession::Close()
	{
		//! @todo IMPLEMENT
	}

	Communication::ChatSessionParticipantVector ChatSession::GetParticipants() const
	{
		Communication::ChatSessionParticipantVector participants;
		for (ChatSessionParticipantVector::const_iterator i = participants_.begin(); i != participants_.end(); ++i)
		{
			participants.push_back( *i );
		}

		return participants;
	}

	Communication::ChatMessageVector ChatSession::GetMessageHistory()
	{
		Communication::ChatMessageVector messages;
		for (ChatMessageVector::iterator i = message_history_.begin(); i != message_history_.end(); ++i)
		{
			messages.push_back( *i );
		}
		return messages;
	}

	void ChatSession::OnTextChannelCreated(Tp::PendingOperation* op)
	{
		//if ( op->isError() )
		//{
		//	LogError("Cannot create TextChannel object");
		//	return;
		//}
		//LogInfo("TextChannel object created");

		//Tp::PendingChannel *pChannel = qobject_cast<Tp::PendingChannel *>(op);
		//Tp::ChannelPtr text_channel = pChannel->channel();

		//tp_text_channel_ = Tp::TextChannelPtr( dynamic_cast<Tp::TextChannel *>(text_channel.data()) );

		//QObject::connect(tp_text_channel_->becomeReady(Tp::TextChannel::FeatureMessageQueue),
		//	     SIGNAL( finished(Tp::PendingOperation*) ),
		//		SLOT( OnChannelReady(Tp::PendingOperation*)) );
	}

	void ChatSession::OnChannelInvalidated(Tp::DBusProxy *p, const QString &me, const QString &er)
	{
		//! @todo IMPLEMENT
	}

	void ChatSession::OnTextChannelReady(Tp::PendingOperation* op)
	{
		for (QStringList::iterator i = send_buffer_.begin(); i != send_buffer_.end(); ++i)
		{
			SendMessage( *i);
		}
	}

	void ChatSession::OnMessageSendAck(Tp::PendingOperation* op)
	{
		//! @todo Move this slot to actual message object
		//! @todo IMPLEMENT
	}

} // end of namespace: TelepathyIM
<|endoftext|>


<commit_before>#include "learning/arow.h"

#include "base/file/scoped_fd.h"

namespace learning {

Arow::Arow(size_t size) :
    size_(size),
    mean_(size + 1),
    cov_(size + 1)
{
    std::fill(cov_.begin(), cov_.end(), 1.0);
}

int Arow::predict(const std::vector<double>& features) const
{
    double m = margin(features);
    return m > 0 ? 1 : -1;
}

double Arow::margin(const std::vector<double>& features) const
{
    DCHECK_EQ(size_, features.size());

    double result = 0.0;
    for (size_t i = 0; i < size_; ++i) {
        result += mean_[i] * features[i];
    }
    result += mean_[size_];
    return result;
}

double Arow::margin(const double features[], size_t size) const
{
    DCHECK_EQ(size_, size);

    double result = 0.0;
    for (size_t i = 0; i < size; ++i) {
        result += mean_[i] * features[i];
    }
    result += mean_[size_];
    return result;
}

double Arow::confidence(const std::vector<double>& features) const
{
    DCHECK_EQ(size_, features.size());

    double result = 0.0;
    for (size_t i = 0; i < size_; ++i) {
        result += cov_[i] * features[i] * features[i];
    }
    result += cov_[size_];
    return result;
}

int Arow::update(const std::vector<double>& features, int label, double learning_rate)
{
    DCHECK_EQ(size_, features.size());

    double m = margin(features);
    int loss = m * label < 0 ? 1 : 0;
    if (m * label >= 1)
        return 0;

    double v = confidence(features);
    double beta = 1.0 / (v + learning_rate);
    double alpha = (1.0 - label * m) * beta;

    // update mean
    for (size_t i = 0; i < size_; ++i) {
        mean_[i] += alpha * label * cov_[i] * features[i];
    }
    mean_[size_] += alpha * label * cov_[size_];

    // update covariance
    for (size_t i = 0; i < size_; ++i) {
        cov_[i] = 1.0 / ((1.0 / cov_[i]) + features[i] * features[i] / learning_rate);
    }
    cov_[size_] = 1.0 / ((1.0 / cov_[size_]) + 1.0 / learning_rate);

    return loss;
}

bool Arow::save(const std::string& filename) const
{
    file::ScopedFd fd(file::ScopedFd::open_for_read(filename.c_str()));
    if (!fd.valid())
        return false;

    if (!fd.write_exactly(mean_.data(), sizeof(double) * (size_ + 1)))
        return false;
    if (!fd.write_exactly(cov_.data(), sizeof(double) * (size_ + 1)));
        return false;
    return true;
}

bool Arow::load(const std::string& filename)
{
    file::ScopedFd fd(file::ScopedFd::open_for_write(filename.c_str()));
    if (!fd.valid())
        return false;

    if (!fd.read_exactly(mean_.data(), sizeof(double) * (size_ + 1)))
        return false;
    if (!fd.read_exactly(cov_.data(), sizeof(double) * (size_ + 1)))
        return false;
    return true;
}

} // namespace learning
<commit_msg>Remove unnecessary semicolon in arow.<commit_after>#include "learning/arow.h"

#include "base/file/scoped_fd.h"

namespace learning {

Arow::Arow(size_t size) :
    size_(size),
    mean_(size + 1),
    cov_(size + 1)
{
    std::fill(cov_.begin(), cov_.end(), 1.0);
}

int Arow::predict(const std::vector<double>& features) const
{
    double m = margin(features);
    return m > 0 ? 1 : -1;
}

double Arow::margin(const std::vector<double>& features) const
{
    DCHECK_EQ(size_, features.size());

    double result = 0.0;
    for (size_t i = 0; i < size_; ++i) {
        result += mean_[i] * features[i];
    }
    result += mean_[size_];
    return result;
}

double Arow::margin(const double features[], size_t size) const
{
    DCHECK_EQ(size_, size);

    double result = 0.0;
    for (size_t i = 0; i < size; ++i) {
        result += mean_[i] * features[i];
    }
    result += mean_[size_];
    return result;
}

double Arow::confidence(const std::vector<double>& features) const
{
    DCHECK_EQ(size_, features.size());

    double result = 0.0;
    for (size_t i = 0; i < size_; ++i) {
        result += cov_[i] * features[i] * features[i];
    }
    result += cov_[size_];
    return result;
}

int Arow::update(const std::vector<double>& features, int label, double learning_rate)
{
    DCHECK_EQ(size_, features.size());

    double m = margin(features);
    int loss = m * label < 0 ? 1 : 0;
    if (m * label >= 1)
        return 0;

    double v = confidence(features);
    double beta = 1.0 / (v + learning_rate);
    double alpha = (1.0 - label * m) * beta;

    // update mean
    for (size_t i = 0; i < size_; ++i) {
        mean_[i] += alpha * label * cov_[i] * features[i];
    }
    mean_[size_] += alpha * label * cov_[size_];

    // update covariance
    for (size_t i = 0; i < size_; ++i) {
        cov_[i] = 1.0 / ((1.0 / cov_[i]) + features[i] * features[i] / learning_rate);
    }
    cov_[size_] = 1.0 / ((1.0 / cov_[size_]) + 1.0 / learning_rate);

    return loss;
}

bool Arow::save(const std::string& filename) const
{
    file::ScopedFd fd(file::ScopedFd::open_for_read(filename.c_str()));
    if (!fd.valid())
        return false;

    if (!fd.write_exactly(mean_.data(), sizeof(double) * (size_ + 1)))
        return false;
    if (!fd.write_exactly(cov_.data(), sizeof(double) * (size_ + 1)))
        return false;
    return true;
}

bool Arow::load(const std::string& filename)
{
    file::ScopedFd fd(file::ScopedFd::open_for_write(filename.c_str()));
    if (!fd.valid())
        return false;

    if (!fd.read_exactly(mean_.data(), sizeof(double) * (size_ + 1)))
        return false;
    if (!fd.read_exactly(cov_.data(), sizeof(double) * (size_ + 1)))
        return false;
    return true;
}

} // namespace learning
<|endoftext|>


<commit_before>#include "util/ComponentTest.h"

class ApiServerComponentTest : public ComponentTest {
protected:
	std::shared_ptr<Susi::Api::ApiServerComponent> apiserver;
	bool called{false};
	std::mutex mutex;
	std::condition_variable cond;

	std::string sessionID{"123"};

	void waitForCondition(int timeout){
		std::unique_lock<std::mutex> lock{mutex};
		cond.wait_for(lock,std::chrono::milliseconds{timeout},[this](){return called;});
		EXPECT_EQ(true,called);
		called = false;
	}

	virtual void SetUp() override {
		componentManager->startComponent("apiserver");
		apiserver = componentManager->getComponent<Susi::Api::ApiServerComponent>("apiserver");
	}

	virtual void TearDown() override {
		componentManager->stopComponent("apiserver");
	}

	virtual void GoodCases() override {
		apiserver->registerSender(sessionID,[this](Susi::Util::Any & packet){
			Susi::Util::Any expect = Susi::Util::Any::Object{
				{"type","status"},
				{"error",false}
			};
			EXPECT_EQ(expect.toJSONString(),packet.toJSONString());
			called = true;
			cond.notify_one();
		});
		apiserver->onConnect(sessionID);

		Susi::Util::Any msg = Susi::Util::Any::Object{
			{"type","registerConsumer"},
			{"data","sample"}
		};
		apiserver->onMessage(sessionID,msg);
		waitForCondition(250);

		msg = Susi::Util::Any::Object{
			{"type","registerProcessor"},
			{"data","sample"}
		};
		apiserver->onMessage(sessionID,msg);
		waitForCondition(250);

		msg = Susi::Util::Any::Object{
			{"type","publish"},
			{"data",Susi::Util::Any::Object{
				{"topic","sample"}
			}}
		};

		Susi::Util::Any procEvent;

		apiserver->registerSender(sessionID,[this,&procEvent](Susi::Util::Any & packet){
			if(packet["type"]=="status"){
				Susi::Util::Any expect = Susi::Util::Any::Object{
					{"type","status"},
					{"error",false}
				};
				EXPECT_EQ(expect.toJSONString(),packet.toJSONString());
				Susi::Logger::debug("in status");
			}else if(packet["type"]=="ack"){
				EXPECT_EQ(Susi::Util::Any{"sample"},packet["data"]["topic"]);
				EXPECT_EQ(Susi::Util::Any{"123"},packet["data"]["sessionid"]);
				EXPECT_EQ(size_t{0},packet["data"]["headers"].size());
				Susi::Logger::debug("in ack");
			}else if(packet["type"]=="consumerEvent"){
				EXPECT_EQ(Susi::Util::Any{"sample"},packet["data"]["topic"]);
				EXPECT_EQ(Susi::Util::Any{"123"},packet["data"]["sessionid"]);
				EXPECT_EQ(size_t{0},packet["data"]["headers"].size());
				Susi::Logger::debug("in consumer");
			}else if(packet["type"]=="processorEvent"){
				EXPECT_EQ(Susi::Util::Any{"sample"},packet["data"]["topic"]);
				EXPECT_EQ(Susi::Util::Any{"123"},packet["data"]["sessionid"]);
				EXPECT_EQ(size_t{0},packet["data"]["headers"].size());
				Susi::Logger::debug("in processor");
				procEvent = packet;
			}
			called = true;
			cond.notify_one();
		});
		apiserver->onMessage(sessionID,msg);
		waitForCondition(250);//status
		waitForCondition(250);//processorEvent
		procEvent["type"] = "ack";
		apiserver->onMessage(sessionID,procEvent);
		waitForCondition(250);//status
		waitForCondition(250);//consumerEvent
		waitForCondition(250);//ack
		apiserver->onClose(sessionID);
	}

	virtual void BadCases() override {

	}

	virtual void EdgeCases() override {

	}

};

TEST_F(ApiServerComponentTest,GoodCases){
	GoodCases();
}

TEST_F(ApiServerComponentTest,BadCases){
	BadCases();
}

TEST_F(ApiServerComponentTest,EdgeCases){
	EdgeCases();
}
<commit_msg>[testing] added bad cases for apiservercomponent;<commit_after>#include "util/ComponentTest.h"

class ApiServerComponentTest : public ComponentTest {
protected:
	std::shared_ptr<Susi::Api::ApiServerComponent> apiserver;
	bool called{false};
	std::mutex mutex;
	std::condition_variable cond;

	std::string sessionID{"123"};

	void waitForCondition(int timeout){
		std::unique_lock<std::mutex> lock{mutex};
		cond.wait_for(lock,std::chrono::milliseconds{timeout},[this](){return called;});
		EXPECT_EQ(true,called);
		called = false;
	}

	virtual void SetUp() override {
		componentManager->startComponent("apiserver");
		apiserver = componentManager->getComponent<Susi::Api::ApiServerComponent>("apiserver");
	}

	virtual void TearDown() override {
		componentManager->stopComponent("apiserver");
	}

	virtual void GoodCases() override {
		apiserver->registerSender(sessionID,[this](Susi::Util::Any & packet){
			Susi::Util::Any expect = Susi::Util::Any::Object{
				{"type","status"},
				{"error",false}
			};
			EXPECT_EQ(expect.toJSONString(),packet.toJSONString());
			called = true;
			cond.notify_one();
		});
		apiserver->onConnect(sessionID);

		Susi::Util::Any msg = Susi::Util::Any::Object{
			{"type","registerConsumer"},
			{"data","sample"}
		};
		apiserver->onMessage(sessionID,msg);
		waitForCondition(250);

		msg = Susi::Util::Any::Object{
			{"type","registerProcessor"},
			{"data","sample"}
		};
		apiserver->onMessage(sessionID,msg);
		waitForCondition(250);

		msg = Susi::Util::Any::Object{
			{"type","publish"},
			{"data",Susi::Util::Any::Object{
				{"topic","sample"}
			}}
		};

		Susi::Util::Any procEvent;

		apiserver->registerSender(sessionID,[this,&procEvent](Susi::Util::Any & packet){
			if(packet["type"]=="status"){
				Susi::Util::Any expect = Susi::Util::Any::Object{
					{"type","status"},
					{"error",false}
				};
				EXPECT_EQ(expect.toJSONString(),packet.toJSONString());
				Susi::Logger::debug("in status");
			}else if(packet["type"]=="ack"){
				EXPECT_EQ(Susi::Util::Any{"sample"},packet["data"]["topic"]);
				EXPECT_EQ(Susi::Util::Any{"123"},packet["data"]["sessionid"]);
				EXPECT_EQ(size_t{0},packet["data"]["headers"].size());
				Susi::Logger::debug("in ack");
			}else if(packet["type"]=="consumerEvent"){
				EXPECT_EQ(Susi::Util::Any{"sample"},packet["data"]["topic"]);
				EXPECT_EQ(Susi::Util::Any{"123"},packet["data"]["sessionid"]);
				EXPECT_EQ(size_t{0},packet["data"]["headers"].size());
				Susi::Logger::debug("in consumer");
			}else if(packet["type"]=="processorEvent"){
				EXPECT_EQ(Susi::Util::Any{"sample"},packet["data"]["topic"]);
				EXPECT_EQ(Susi::Util::Any{"123"},packet["data"]["sessionid"]);
				EXPECT_EQ(size_t{0},packet["data"]["headers"].size());
				Susi::Logger::debug("in processor");
				procEvent = packet;
			}
			called = true;
			cond.notify_one();
		});
		apiserver->onMessage(sessionID,msg);
		waitForCondition(250);//status
		waitForCondition(250);//processorEvent
		procEvent["type"] = "ack";
		apiserver->onMessage(sessionID,procEvent);
		waitForCondition(250);//status
		waitForCondition(250);//consumerEvent
		waitForCondition(250);//ack

		msg = Susi::Util::Any::Object{
			{"type","unregisterConsumer"},
			{"data","sample"}
		};
		apiserver->onMessage(sessionID,msg);
		waitForCondition(250);//status
		msg = Susi::Util::Any::Object{
			{"type","unregisterProcessor"},
			{"data","sample"}
		};
		apiserver->onMessage(sessionID,msg);
		waitForCondition(250);//status

		apiserver->onClose(sessionID);
	}

	virtual void BadCases() override {
		auto statusSuccess = [this](Susi::Util::Any & packet){
			Susi::Util::Any expect = Susi::Util::Any::Object{
				{"type","status"},
				{"error",false}
			};
			EXPECT_EQ(expect.toJSONString(),packet.toJSONString());
			called = true;
			cond.notify_one();
		};
		auto statusError = [this](Susi::Util::Any & packet){
			EXPECT_EQ(Susi::Util::Any{"status"},packet["type"]);
			EXPECT_EQ(Susi::Util::Any{true},packet["error"]);
			EXPECT_EQ(Susi::Util::Any{"you are allready subscribed to sample"},packet["data"]);
			called = true;
			cond.notify_one();
		};

		apiserver->registerSender(sessionID,statusSuccess);
		apiserver->onConnect(sessionID);
		Susi::Util::Any msg = Susi::Util::Any::Object{
			{"type","registerConsumer"},
			{"data","sample"}
		};
		apiserver->onMessage(sessionID,msg);
		waitForCondition(250);
		apiserver->registerSender(sessionID,statusError);
		apiserver->onMessage(sessionID,msg);
		waitForCondition(250);

		apiserver->registerSender(sessionID,statusSuccess);
		apiserver->onConnect(sessionID);
		msg = Susi::Util::Any::Object{
			{"type","registerProcessor"},
			{"data","sample"}
		};
		apiserver->onMessage(sessionID,msg);
		waitForCondition(250);
		apiserver->registerSender(sessionID,statusError);
		apiserver->onMessage(sessionID,msg);
		waitForCondition(250);

	}

	virtual void EdgeCases() override {

	}

};

TEST_F(ApiServerComponentTest,GoodCases){
	GoodCases();
}

TEST_F(ApiServerComponentTest,BadCases){
	BadCases();
}

TEST_F(ApiServerComponentTest,EdgeCases){
	EdgeCases();
}
<|endoftext|>