<commit_before>// Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com>
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.

#include <nvtt/nvtt.h>
#include <nvimage/Image.h>
#include <nvimage/ImageIO.h>
#include <nvimage/BlockDXT.h>
#include <nvimage/ColorBlock.h>
#include <nvcore/Ptr.h>
#include <nvcore/Debug.h>
#include <nvcore/StrLib.h>
#include <nvcore/StdStream.h>
#include <nvcore/TextWriter.h>
#include <nvcore/FileSystem.h>

#include <stdlib.h> // free
#include <string.h> // memcpy
#include <time.h> // clock

using namespace nv;

// Kodak image set
static const char * s_kodakImageSet[] = {
	"kodim01.png",
	"kodim02.png",
	"kodim03.png",
	"kodim04.png",
	"kodim05.png",
	"kodim06.png",
	"kodim07.png",
	"kodim08.png",
	"kodim09.png",
	"kodim10.png",
	"kodim11.png",
	"kodim12.png",
	"kodim13.png",
	"kodim14.png",
	"kodim15.png",
	"kodim16.png",
	"kodim17.png",
	"kodim18.png",
	"kodim19.png",
	"kodim20.png",
	"kodim21.png",
	"kodim22.png",
	"kodim23.png",
	"kodim24.png",
};

// Waterloo image set
static const char * s_waterlooImageSet[] = {
	"clegg.png",
	"frymire.png",
	"lena.png",
	"monarch.png",
	"peppers.png",
	"sail.png",
	"serrano.png",
	"tulips.png",
};

// Epic image set
static const char * s_epicImageSet[] = {
	"Bradley1.png",
	"Gradient.png",
	"MoreRocks.png",
	"Wall.png",
	"Rainbow.png",
	"Text.png",
};

struct ImageSet
{
	const char ** fileNames;
	int fileCount;
};

static ImageSet s_imageSets[] = {
	{s_kodakImageSet, sizeof(s_kodakImageSet)/sizeof(s_kodakImageSet[0])},
	{s_waterlooImageSet, sizeof(s_waterlooImageSet)/sizeof(s_waterlooImageSet[0])},
	{s_epicImageSet, sizeof(s_epicImageSet)/sizeof(s_epicImageSet[0])},
};
const int s_imageSetCount = sizeof(s_imageSets)/sizeof(s_imageSets[0]);

struct MyOutputHandler : public nvtt::OutputHandler
{
	MyOutputHandler() : m_data(NULL), m_ptr(NULL) {}
	~MyOutputHandler()
	{
		free(m_data);
	}

	virtual void beginImage(int size, int width, int height, int depth, int face, int miplevel)
	{
		m_size = size;
		m_width = width;
		m_height = height;
		free(m_data);
		m_data = (unsigned char *)malloc(size);
		m_ptr = m_data;
	}

	virtual bool writeData(const void * data, int size)
	{
		memcpy(m_ptr, data, size);
		m_ptr += size;
		return true;
	}

	Image * decompress(nvtt::Format format)
	{
		int bw = (m_width + 3) / 4;
		int bh = (m_height + 3) / 4;

		AutoPtr<Image> img( new Image() );
		img->allocate(m_width, m_height);

		if (format == nvtt::Format_BC1)
		{
			BlockDXT1 * block = (BlockDXT1 *)m_data;

			for (int y = 0; y < bh; y++)
			{
				for (int x = 0; x < bw; x++)
				{
					ColorBlock colors;
					block->decodeBlock(&colors);

					for (int yy = 0; yy < 4; yy++)
					{
						for (int xx = 0; xx < 4; xx++)
						{
							Color32 c = colors.color(xx, yy);

							if (x * 4 + xx < m_width && y * 4 + yy < m_height)
							{
								img->pixel(x * 4 + xx, y * 4 + yy) = c;
							}
						}
					}

					block++;
				}
			}
		}

		return img.release();
	}

	int m_size;
	int m_width;
	int m_height;
	unsigned char * m_data;
	unsigned char * m_ptr;
};

float rmsError(const Image * a, const Image * b)
{
	nvCheck(a != NULL);
	nvCheck(b != NULL);
	nvCheck(a->width() == b->width());
	nvCheck(a->height() == b->height());

	int mse = 0;

	const uint count = a->width() * a->height();

	for (uint i = 0; i < count; i++)
	{
		Color32 c0 = a->pixel(i);
		Color32 c1 = b->pixel(i);

		int r = c0.r - c1.r;
		int g = c0.g - c1.g;
		int b = c0.b - c1.b;
		//int a = c0.a - c1.a;

		mse += r * r;
		mse += g * g;
		mse += b * b;
	}

	return sqrtf(float(mse) / count);
}

int main(int argc, char *argv[])
{
	const uint version = nvtt::version();
	const uint major = version / 100;
	const uint minor = version % 100;

	printf("NVIDIA Texture Tools %u.%u - Copyright NVIDIA Corporation 2007 - 2008\n\n", major, minor);

	int set = 0;
	bool fast = false;
	bool nocuda = false;
	bool showHelp = false;
	const char * basePath = "";
	const char * outPath = "output";
	const char * regressPath = NULL;

	// Parse arguments.
	for (int i = 1; i < argc; i++)
	{
		if (strcmp("-set", argv[i]) == 0)
		{
			if (i+1 < argc && argv[i+1][0] != '-') {
				set = atoi(argv[i+1]);
				i++;
			}
		}
		else if (strcmp("-fast", argv[i]) == 0)
		{
			fast = true;
		}
		else if (strcmp("-nocuda", argv[i]) == 0)
		{
			nocuda = true;
		}
		else if (strcmp("-help", argv[i]) == 0)
		{
			showHelp = true;
		}
		else if (strcmp("-path", argv[i]) == 0)
		{
			if (i+1 < argc && argv[i+1][0] != '-') {
				basePath = argv[i+1];
				i++;
			}
		}
		else if (strcmp("-out", argv[i]) == 0)
		{
			if (i+1 < argc && argv[i+1][0] != '-') {
				outPath = argv[i+1];
				i++;
			}
		}
		else if (strcmp("-regress", argv[i]) == 0)
		{
			if (i+1 < argc && argv[i+1][0] != '-') {
				regressPath = argv[i+1];
				i++;
			}
		}
	}

	if (showHelp)
	{
		printf("usage: nvtestsuite [options]\n\n");

		printf("Input options:\n");
		printf("  -path <path>\tInput image path.\n");
		printf("  -set [0:2]\tImage set.\n");
		printf("  -regress <path>\tRegression directory.\n");

		printf("Compression options:\n");
		printf("  -fast          \tFast compression.\n");
		printf("  -nocuda        \tDo not use cuda compressor.\n");

		printf("Output options:\n");
		printf("  -out <path>    \tOutput directory.\n");

		return 1;
	}

	nvtt::InputOptions inputOptions;
	inputOptions.setMipmapGeneration(false);

	nvtt::CompressionOptions compressionOptions;
	compressionOptions.setFormat(nvtt::Format_BC1);
	if (fast)
	{
		compressionOptions.setQuality(nvtt::Quality_Fastest);
	}
	else
	{
		compressionOptions.setQuality(nvtt::Quality_Production);
	}

	nvtt::OutputOptions outputOptions;
	outputOptions.setOutputHeader(false);

	MyOutputHandler outputHandler;
	outputOptions.setOutputHandler(&outputHandler);

	nvtt::Context context;
	context.enableCudaAcceleration(!nocuda);

	FileSystem::changeDirectory(basePath);
	FileSystem::createDirectory(outPath);

	Path csvFileName;
	csvFileName.format("%s/result.csv", outPath);
	StdOutputStream csvStream(csvFileName);
	TextWriter csvWriter(&csvStream);

	float totalTime = 0;
	float totalRMSE = 0;
	int failedTests = 0;
	float totalDiff = 0;

	const char ** fileNames = s_imageSets[set].fileNames;
	int fileCount = s_imageSets[set].fileCount;

	for (int i = 0; i < fileCount; i++)
	{
		AutoPtr<Image> img( new Image() );

		if (!img->load(fileNames[i]))
		{
			printf("Input image '%s' not found.\n", fileNames[i]);
			return EXIT_FAILURE;
		}

		inputOptions.setTextureLayout(nvtt::TextureType_2D, img->width(), img->height());
		inputOptions.setMipmapData(img->pixels(), img->width(), img->height());

		printf("Compressing: \t'%s'\n", fileNames[i]);

		clock_t start = clock();

		context.process(inputOptions, compressionOptions, outputOptions);

		clock_t end = clock();
		printf("  Time: \t%.3f sec\n", float(end-start) / CLOCKS_PER_SEC);
		totalTime += float(end-start);

		AutoPtr<Image> img_out( outputHandler.decompress(nvtt::Format_BC1) );

		Path outputFileName;
		outputFileName.format("%s/%s", outPath, fileNames[i]);
		outputFileName.stripExtension();
		outputFileName.append(".png");
		if (!ImageIO::save(outputFileName, img_out.ptr()))
		{
			printf("Error saving file '%s'.\n", outputFileName.str());
		}

		float rmse = rmsError(img.ptr(), img_out.ptr());
		totalRMSE += rmse;

		printf("  RMSE:  \t%.4f\n", rmse);

		// Output csv file
		csvWriter << "\"" << fileNames[i] << "\"," << rmse << "\n";

		if (regressPath != NULL)
		{
			Path regressFileName;
			regressFileName.format("%s/%s", regressPath, fileNames[i]);
			regressFileName.stripExtension();
			regressFileName.append(".png");

			AutoPtr<Image> img_reg( new Image() );
			if (!img_reg->load(regressFileName.str()))
			{
				printf("Regression image '%s' not found.\n", regressFileName.str());
				return EXIT_FAILURE;
			}

			float rmse_reg = rmsError(img.ptr(), img_reg.ptr());

			float diff = rmse_reg - rmse;
			totalDiff += diff;

			const char * text = "PASSED";
			if (equal(diff, 0)) text = "PASSED";
			else if (diff < 0) {
				text = "FAILED";
				failedTests++;
			}

			printf("  Diff: \t%.4f (%s)\n", diff, text);
		}

		fflush(stdout);
	}

	totalRMSE /= fileCount;
	totalDiff /= fileCount;

	printf("Total Results:\n");
	printf("  Total Time: \t%.3f sec\n", totalTime / CLOCKS_PER_SEC);
	printf("  Average RMSE:\t%.4f\n", totalRMSE);

	if (regressPath != NULL)
	{
		printf("Regression Results:\n");
		printf("  Diff: %.4f\n", totalDiff);
		printf("  %d/%d tests failed.\n", failedTests, fileCount);
	}

	return EXIT_SUCCESS;
}

<commit_msg>Add farbrausch images to testsuite.<commit_after>// Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com>
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.

#include <nvtt/nvtt.h>
#include <nvimage/Image.h>
#include <nvimage/ImageIO.h>
#include <nvimage/BlockDXT.h>
#include <nvimage/ColorBlock.h>
#include <nvcore/Ptr.h>
#include <nvcore/Debug.h>
#include <nvcore/StrLib.h>
#include <nvcore/StdStream.h>
#include <nvcore/TextWriter.h>
#include <nvcore/FileSystem.h>

#include <stdlib.h> // free
#include <string.h> // memcpy
#include <time.h> // clock

using namespace nv;

// Kodak image set
static const char * s_kodakImageSet[] = {
	"kodim01.png",
	"kodim02.png",
	"kodim03.png",
	"kodim04.png",
	"kodim05.png",
	"kodim06.png",
	"kodim07.png",
	"kodim08.png",
	"kodim09.png",
	"kodim10.png",
	"kodim11.png",
	"kodim12.png",
	"kodim13.png",
	"kodim14.png",
	"kodim15.png",
	"kodim16.png",
	"kodim17.png",
	"kodim18.png",
	"kodim19.png",
	"kodim20.png",
	"kodim21.png",
	"kodim22.png",
	"kodim23.png",
	"kodim24.png",
};

// Waterloo image set
static const char * s_waterlooImageSet[] = {
	"clegg.png",
	"frymire.png",
	"lena.png",
	"monarch.png",
	"peppers.png",
	"sail.png",
	"serrano.png",
	"tulips.png",
};

// Epic image set
static const char * s_epicImageSet[] = {
	"Bradley1.png",
	"Gradient.png",
	"MoreRocks.png",
	"Wall.png",
	"Rainbow.png",
	"Text.png",
};

// Farbrausch
static const char * s_farbrauschImageSet[] = {
	"t.2d.pn02.bmp",
	"t.aircondition.01.bmp",
	"t.bricks.02.bmp",
	"t.bricks.05.bmp",
	"t.concrete.cracked.01.bmp",
	"t.envi.colored02.bmp",
	"t.envi.colored03.bmp",
	"t.font.01.bmp",
	"t.sewers.01.bmp",
	"t.train.03.bmp",
	"t.yello.01.bmp",
};

struct ImageSet
{
	const char ** fileNames;
	int fileCount;
};

static ImageSet s_imageSets[] = {
	{s_kodakImageSet, sizeof(s_kodakImageSet)/sizeof(s_kodakImageSet[0])},
	{s_waterlooImageSet, sizeof(s_waterlooImageSet)/sizeof(s_waterlooImageSet[0])},
	{s_epicImageSet, sizeof(s_epicImageSet)/sizeof(s_epicImageSet[0])},
	{s_farbrauschImageSet, sizeof(s_farbrauschImageSet)/sizeof(s_farbrauschImageSet[0])},
};
const int s_imageSetCount = sizeof(s_imageSets)/sizeof(s_imageSets[0]);

struct MyOutputHandler : public nvtt::OutputHandler
{
	MyOutputHandler() : m_data(NULL), m_ptr(NULL) {}
	~MyOutputHandler()
	{
		free(m_data);
	}

	virtual void beginImage(int size, int width, int height, int depth, int face, int miplevel)
	{
		m_size = size;
		m_width = width;
		m_height = height;
		free(m_data);
		m_data = (unsigned char *)malloc(size);
		m_ptr = m_data;
	}

	virtual bool writeData(const void * data, int size)
	{
		memcpy(m_ptr, data, size);
		m_ptr += size;
		return true;
	}

	Image * decompress(nvtt::Format format)
	{
		int bw = (m_width + 3) / 4;
		int bh = (m_height + 3) / 4;

		AutoPtr<Image> img( new Image() );
		img->allocate(m_width, m_height);

		if (format == nvtt::Format_BC1)
		{
			BlockDXT1 * block = (BlockDXT1 *)m_data;

			for (int y = 0; y < bh; y++)
			{
				for (int x = 0; x < bw; x++)
				{
					ColorBlock colors;
					block->decodeBlock(&colors);

					for (int yy = 0; yy < 4; yy++)
					{
						for (int xx = 0; xx < 4; xx++)
						{
							Color32 c = colors.color(xx, yy);

							if (x * 4 + xx < m_width && y * 4 + yy < m_height)
							{
								img->pixel(x * 4 + xx, y * 4 + yy) = c;
							}
						}
					}

					block++;
				}
			}
		}

		return img.release();
	}

	int m_size;
	int m_width;
	int m_height;
	unsigned char * m_data;
	unsigned char * m_ptr;
};

float rmsError(const Image * a, const Image * b)
{
	nvCheck(a != NULL);
	nvCheck(b != NULL);
	nvCheck(a->width() == b->width());
	nvCheck(a->height() == b->height());

	int mse = 0;

	const uint count = a->width() * a->height();

	for (uint i = 0; i < count; i++)
	{
		Color32 c0 = a->pixel(i);
		Color32 c1 = b->pixel(i);

		int r = c0.r - c1.r;
		int g = c0.g - c1.g;
		int b = c0.b - c1.b;
		//int a = c0.a - c1.a;

		mse += r * r;
		mse += g * g;
		mse += b * b;
	}

	return sqrtf(float(mse) / count);
}

int main(int argc, char *argv[])
{
	const uint version = nvtt::version();
	const uint major = version / 100;
	const uint minor = version % 100;

	printf("NVIDIA Texture Tools %u.%u - Copyright NVIDIA Corporation 2007 - 2008\n\n", major, minor);

	int set = 0;
	bool fast = false;
	bool nocuda = false;
	bool showHelp = false;
	const char * basePath = "";
	const char * outPath = "output";
	const char * regressPath = NULL;

	// Parse arguments.
	for (int i = 1; i < argc; i++)
	{
		if (strcmp("-set", argv[i]) == 0)
		{
			if (i+1 < argc && argv[i+1][0] != '-') {
				set = atoi(argv[i+1]);
				i++;
			}
		}
		else if (strcmp("-fast", argv[i]) == 0)
		{
			fast = true;
		}
		else if (strcmp("-nocuda", argv[i]) == 0)
		{
			nocuda = true;
		}
		else if (strcmp("-help", argv[i]) == 0)
		{
			showHelp = true;
		}
		else if (strcmp("-path", argv[i]) == 0)
		{
			if (i+1 < argc && argv[i+1][0] != '-') {
				basePath = argv[i+1];
				i++;
			}
		}
		else if (strcmp("-out", argv[i]) == 0)
		{
			if (i+1 < argc && argv[i+1][0] != '-') {
				outPath = argv[i+1];
				i++;
			}
		}
		else if (strcmp("-regress", argv[i]) == 0)
		{
			if (i+1 < argc && argv[i+1][0] != '-') {
				regressPath = argv[i+1];
				i++;
			}
		}
	}

	if (showHelp)
	{
		printf("usage: nvtestsuite [options]\n\n");

		printf("Input options:\n");
		printf("  -path <path>\tInput image path.\n");
		printf("  -set [0:2]\tImage set.\n");
		printf("  -regress <path>\tRegression directory.\n");

		printf("Compression options:\n");
		printf("  -fast          \tFast compression.\n");
		printf("  -nocuda        \tDo not use cuda compressor.\n");

		printf("Output options:\n");
		printf("  -out <path>    \tOutput directory.\n");

		return 1;
	}

	nvtt::InputOptions inputOptions;
	inputOptions.setMipmapGeneration(false);

	nvtt::CompressionOptions compressionOptions;
	compressionOptions.setFormat(nvtt::Format_BC1);
	if (fast)
	{
		compressionOptions.setQuality(nvtt::Quality_Fastest);
	}
	else
	{
		compressionOptions.setQuality(nvtt::Quality_Production);
	}

	nvtt::OutputOptions outputOptions;
	outputOptions.setOutputHeader(false);

	MyOutputHandler outputHandler;
	outputOptions.setOutputHandler(&outputHandler);

	nvtt::Context context;
	context.enableCudaAcceleration(!nocuda);

	FileSystem::changeDirectory(basePath);
	FileSystem::createDirectory(outPath);

	Path csvFileName;
	csvFileName.format("%s/result.csv", outPath);
	StdOutputStream csvStream(csvFileName);
	TextWriter csvWriter(&csvStream);

	float totalTime = 0;
	float totalRMSE = 0;
	int failedTests = 0;
	float totalDiff = 0;

	const char ** fileNames = s_imageSets[set].fileNames;
	int fileCount = s_imageSets[set].fileCount;

	for (int i = 0; i < fileCount; i++)
	{
		AutoPtr<Image> img( new Image() );

		if (!img->load(fileNames[i]))
		{
			printf("Input image '%s' not found.\n", fileNames[i]);
			return EXIT_FAILURE;
		}

		inputOptions.setTextureLayout(nvtt::TextureType_2D, img->width(), img->height());
		inputOptions.setMipmapData(img->pixels(), img->width(), img->height());

		printf("Compressing: \t'%s'\n", fileNames[i]);

		clock_t start = clock();

		context.process(inputOptions, compressionOptions, outputOptions);

		clock_t end = clock();
		printf("  Time: \t%.3f sec\n", float(end-start) / CLOCKS_PER_SEC);
		totalTime += float(end-start);

		AutoPtr<Image> img_out( outputHandler.decompress(nvtt::Format_BC1) );

		Path outputFileName;
		outputFileName.format("%s/%s", outPath, fileNames[i]);
		outputFileName.stripExtension();
		outputFileName.append(".png");
		if (!ImageIO::save(outputFileName, img_out.ptr()))
		{
			printf("Error saving file '%s'.\n", outputFileName.str());
		}

		float rmse = rmsError(img.ptr(), img_out.ptr());
		totalRMSE += rmse;

		printf("  RMSE:  \t%.4f\n", rmse);

		// Output csv file
		csvWriter << "\"" << fileNames[i] << "\"," << rmse << "\n";

		if (regressPath != NULL)
		{
			Path regressFileName;
			regressFileName.format("%s/%s", regressPath, fileNames[i]);
			regressFileName.stripExtension();
			regressFileName.append(".png");

			AutoPtr<Image> img_reg( new Image() );
			if (!img_reg->load(regressFileName.str()))
			{
				printf("Regression image '%s' not found.\n", regressFileName.str());
				return EXIT_FAILURE;
			}

			float rmse_reg = rmsError(img.ptr(), img_reg.ptr());

			float diff = rmse_reg - rmse;
			totalDiff += diff;

			const char * text = "PASSED";
			if (equal(diff, 0)) text = "PASSED";
			else if (diff < 0) {
				text = "FAILED";
				failedTests++;
			}

			printf("  Diff: \t%.4f (%s)\n", diff, text);
		}

		fflush(stdout);
	}

	totalRMSE /= fileCount;
	totalDiff /= fileCount;

	printf("Total Results:\n");
	printf("  Total Time: \t%.3f sec\n", totalTime / CLOCKS_PER_SEC);
	printf("  Average RMSE:\t%.4f\n", totalRMSE);

	if (regressPath != NULL)
	{
		printf("Regression Results:\n");
		printf("  Diff: %.4f\n", totalDiff);
		printf("  %d/%d tests failed.\n", failedTests, fileCount);
	}

	return EXIT_SUCCESS;
}

<|endoftext|>


<commit_before>/**
 * Copyright 2015 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "identifier_evaluator.h"
#include "i_dbg_stack_frame.h"
#include "i_eval_coordinator.h"
#include "dbg_object.h"
#include "dbg_class_property.h"

namespace google_cloud_debugger {

IdentifierEvaluator::IdentifierEvaluator(std::string identifier_name)
    : identifier_name_(identifier_name) {
}

HRESULT IdentifierEvaluator::Compile(
    IDbgStackFrame *stack_frame,
    ICorDebugILFrame *debug_frame,
    std::ostream *err_stream) {
  // Only needs to check null for stack frame because we don't
  // invoke the other arguments.
  if (!stack_frame) {
    return E_INVALIDARG;
  }

  // Case 1: this is a local variable.
  HRESULT hr = stack_frame->GetLocalVariable(identifier_name_,
    &identifier_object_, err_stream);
  if (FAILED(hr)) {
    return hr;
  }

  // S_FALSE means there is no match.
  if (SUCCEEDED(hr) && hr != S_FALSE) {
    return identifier_object_->GetTypeSignature(&result_type_);
  }

  // Case 2: static and non-static fields and auto-implemented properties.
  hr = stack_frame->GetFieldAndAutoPropFromFrame(identifier_name_,
    &identifier_object_, debug_frame, err_stream);
  if (FAILED(hr)) {
    return hr;
  }

  // S_FALSE means there is no match.
  if (SUCCEEDED(hr) && hr != S_FALSE) {
    return identifier_object_->GetTypeSignature(&result_type_);
  }

  // Case 3: static and non-static properties with getter.
  hr = stack_frame->GetPropertyFromFrame(identifier_name_,
    &class_property_, err_stream);
  if (hr == S_FALSE) {
    hr = E_FAIL;
  }

  if (FAILED(hr)) {
    return hr;
  }

  hr = class_property_->GetTypeSignature(&result_type_);
  if (FAILED(hr)) {
    return hr;
  }

  // Generic type parameters for the class that the method is in.
  return stack_frame->GetClassGenericTypeParameters(debug_frame,
                                                    &generic_class_types_);
}

HRESULT IdentifierEvaluator::Evaluate(
    std::shared_ptr<DbgObject> *dbg_object,
    IEvalCoordinator *eval_coordinator,
    IDbgObjectFactory *obj_factory,
    std::ostream * err_stream) const {
  if (class_property_ == nullptr) {
    *dbg_object = identifier_object_;
    return S_OK;
  }

  CComPtr<ICorDebugValue> invoking_object;

  HRESULT hr;
  // If this is a non-static property, we have to get the invoking object.
  if (!class_property_->IsStatic()) {
    CComPtr<ICorDebugILFrame> debug_frame;
    hr = eval_coordinator->GetActiveDebugFrame(&debug_frame);
    if (FAILED(hr)) {
      *err_stream << "Failed to get the active debug frame.";
      return hr;
    }

    // Returns this object.
    hr = debug_frame->GetArgument(0, &invoking_object);
    if (FAILED(hr)) {
      *err_stream << "Failed to get the invoking object.";
      return hr;
    }
  }

  hr = class_property_->Evaluate(invoking_object, eval_coordinator,
    const_cast<std::vector<CComPtr<ICorDebugType>> *>(&generic_class_types_));
  if (FAILED(hr)) {
    *err_stream << "Failed to evaluate property.";
    return hr;
  }

  *dbg_object = class_property_->GetMemberValue();
  return S_OK;
}

}  // namespace google_cloud_debugger
<commit_msg>Add clarifying comments in identifier evaluator<commit_after>/**
 * Copyright 2015 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "identifier_evaluator.h"
#include "i_dbg_stack_frame.h"
#include "i_eval_coordinator.h"
#include "dbg_object.h"
#include "dbg_class_property.h"

namespace google_cloud_debugger {

IdentifierEvaluator::IdentifierEvaluator(std::string identifier_name)
    : identifier_name_(identifier_name) {
}

HRESULT IdentifierEvaluator::Compile(
    IDbgStackFrame *stack_frame,
    ICorDebugILFrame *debug_frame,
    std::ostream *err_stream) {
  // Only needs to check null for stack frame because we don't
  // invoke the other arguments.
  if (!stack_frame) {
    return E_INVALIDARG;
  }

  // Case 1: this is a local variable.
  HRESULT hr = stack_frame->GetLocalVariable(identifier_name_,
    &identifier_object_, err_stream);
  if (FAILED(hr)) {
    return hr;
  }

  // S_FALSE means there is no match.
  if (SUCCEEDED(hr) && hr != S_FALSE) {
    return identifier_object_->GetTypeSignature(&result_type_);
  }

  // Case 2: static and non-static fields and auto-implemented properties.
  hr = stack_frame->GetFieldAndAutoPropFromFrame(identifier_name_,
    &identifier_object_, debug_frame, err_stream);
  if (FAILED(hr)) {
    return hr;
  }

  // S_FALSE means there is no match.
  if (SUCCEEDED(hr) && hr != S_FALSE) {
    return identifier_object_->GetTypeSignature(&result_type_);
  }

  // Case 3: static and non-static properties with getter.
  hr = stack_frame->GetPropertyFromFrame(identifier_name_,
    &class_property_, err_stream);
  if (hr == S_FALSE) {
    hr = E_FAIL;
  }

  if (FAILED(hr)) {
    return hr;
  }

  hr = class_property_->GetTypeSignature(&result_type_);
  if (FAILED(hr)) {
    return hr;
  }

  // Generic type parameters for the class that the method is in.
  return stack_frame->GetClassGenericTypeParameters(debug_frame,
                                                    &generic_class_types_);
}

HRESULT IdentifierEvaluator::Evaluate(
    std::shared_ptr<DbgObject> *dbg_object,
    IEvalCoordinator *eval_coordinator,
    IDbgObjectFactory *obj_factory,
    std::ostream * err_stream) const {
  if (class_property_ == nullptr) {
    *dbg_object = identifier_object_;
    return S_OK;
  }

  CComPtr<ICorDebugValue> invoking_object;

  HRESULT hr;
  // If this is a non-static property, we have to get the invoking object.
  if (!class_property_->IsStatic()) {
    CComPtr<ICorDebugILFrame> debug_frame;
    hr = eval_coordinator->GetActiveDebugFrame(&debug_frame);
    if (FAILED(hr)) {
      *err_stream << "Failed to get the active debug frame.";
      return hr;
    }

    // Returns 'this' object.
    hr = debug_frame->GetArgument(0, &invoking_object);
    if (FAILED(hr)) {
      *err_stream << "Failed to get the invoking object.";
      return hr;
    }
  }

  hr = class_property_->Evaluate(invoking_object, eval_coordinator,
    const_cast<std::vector<CComPtr<ICorDebugType>> *>(&generic_class_types_));
  if (FAILED(hr)) {
    *err_stream << "Failed to evaluate property.";
    return hr;
  }

  *dbg_object = class_property_->GetMemberValue();
  return S_OK;
}

}  // namespace google_cloud_debugger
<|endoftext|>


<commit_before>#include "stock/Stock.hxx"
#include "stock/Class.hxx"
#include "stock/GetHandler.hxx"
#include "stock/Item.hxx"
#include "event/Base.hxx"
#include "async.hxx"
#include "pool.hxx"

#include <glib.h>

#include <assert.h>

static unsigned num_create, num_fail, num_borrow, num_release, num_destroy;
static bool next_fail;
static bool got_item;
static StockItem *last_item;

struct MyStockItem final : PoolStockItem {
    void *info;

    explicit MyStockItem(struct pool &_pool, CreateStockItem c)
        :PoolStockItem(_pool, c) {}

    ~MyStockItem() override {
        ++num_destroy;
    }

    /* virtual methods from class StockItem */
    bool Borrow(gcc_unused void *ctx) override {
        ++num_borrow;
        return true;
    }

    bool Release(gcc_unused void *ctx) override {
        ++num_release;
        return true;
    }
};

static inline GQuark
test_quark(void)
{
    return g_quark_from_static_string("test");
}

/*
 * stock class
 *
 */

static void
my_stock_create(void *ctx gcc_unused,
                struct pool &parent_pool, CreateStockItem c,
                gcc_unused const char *uri, void *info,
                gcc_unused struct pool &caller_pool,
                gcc_unused struct async_operation_ref &async_ref)
{
    auto &pool = *pool_new_linear(&parent_pool, "my_stock", 512);
    auto *item = NewFromPool<MyStockItem>(pool, pool, c);

    item->info = info;

    if (next_fail) {
        ++num_fail;

        GError *error = g_error_new_literal(test_quark(), 0, "next_fail");
        item->InvokeCreateError(error);
    } else {
        ++num_create;
        item->InvokeCreateSuccess();
    }
}

static constexpr StockClass my_stock_class = {
    .create = my_stock_create,
};

class MyStockGetHandler final : public StockGetHandler {
public:
    /* virtual methods from class StockGetHandler */
    void OnStockItemReady(StockItem &item) override {
        assert(!got_item);

        got_item = true;
        last_item = &item;
    }

    void OnStockItemError(GError *error) override {
        g_printerr("%s\n", error->message);
        g_error_free(error);

        got_item = true;
        last_item = nullptr;
    }
};

int main(gcc_unused int argc, gcc_unused char **argv)
{
    struct pool *pool;
    Stock *stock;
    struct async_operation_ref async_ref;
    StockItem *item, *second, *third;

    EventBase event_base;
    pool = pool_new_libc(nullptr, "root");

    stock = new Stock(*pool, my_stock_class, nullptr, nullptr, 3, 8);

    MyStockGetHandler handler;

    /* create first item */

    stock->Get(*pool, nullptr, handler, async_ref);
    assert(got_item);
    assert(last_item != nullptr);
    assert(num_create == 1 && num_fail == 0);
    assert(num_borrow == 0 && num_release == 0 && num_destroy == 0);
    item = last_item;

    /* release first item */

    stock->Put(*item, false);
    event_loop(EVLOOP_NONBLOCK);
    assert(num_create == 1 && num_fail == 0);
    assert(num_borrow == 0 && num_release == 1 && num_destroy == 0);

    /* reuse first item */

    got_item = false;
    last_item = nullptr;
    stock->Get(*pool, nullptr, handler, async_ref);
    assert(got_item);
    assert(last_item == item);
    assert(num_create == 1 && num_fail == 0);
    assert(num_borrow == 1 && num_release == 1 && num_destroy == 0);

    /* create second item */

    got_item = false;
    last_item = nullptr;
    stock->Get(*pool, nullptr, handler, async_ref);
    assert(got_item);
    assert(last_item != nullptr);
    assert(last_item != item);
    assert(num_create == 2 && num_fail == 0);
    assert(num_borrow == 1 && num_release == 1 && num_destroy == 0);
    second = last_item;

    /* fail to create third item */

    next_fail = true;
    got_item = false;
    last_item = nullptr;
    stock->Get(*pool, nullptr, handler, async_ref);
    assert(got_item);
    assert(last_item == nullptr);
    assert(num_create == 2 && num_fail == 1);
    assert(num_borrow == 1 && num_release == 1 && num_destroy == 1);

    /* create third item */

    next_fail = false;
    got_item = false;
    last_item = nullptr;
    stock->Get(*pool, nullptr, handler, async_ref);
    assert(got_item);
    assert(last_item != nullptr);
    assert(num_create == 3 && num_fail == 1);
    assert(num_borrow == 1 && num_release == 1 && num_destroy == 1);
    third = last_item;

    /* fourth item waiting */

    got_item = false;
    last_item = nullptr;
    stock->Get(*pool, nullptr, handler, async_ref);
    assert(!got_item);
    assert(num_create == 3 && num_fail == 1);
    assert(num_borrow == 1 && num_release == 1 && num_destroy == 1);

    /* fifth item waiting */

    stock->Get(*pool, nullptr, handler, async_ref);
    assert(!got_item);
    assert(num_create == 3 && num_fail == 1);
    assert(num_borrow == 1 && num_release == 1 && num_destroy == 1);

    /* return third item */

    stock->Put(*third, false);
    event_loop(EVLOOP_NONBLOCK);
    assert(num_create == 3 && num_fail == 1);
    assert(num_borrow == 2 && num_release == 2 && num_destroy == 1);
    assert(got_item);
    assert(last_item == third);

    /* destroy second item */

    got_item = false;
    last_item = nullptr;
    stock->Put(*second, true);
    event_loop(EVLOOP_NONBLOCK);
    assert(num_create == 4 && num_fail == 1);
    assert(num_borrow == 2 && num_release == 2 && num_destroy == 2);
    assert(got_item);
    assert(last_item != nullptr);
    second = last_item;

    /* destroy first item */

    stock->Put(*item, true);
    assert(num_create == 4 && num_fail == 1);
    assert(num_borrow == 2 && num_release == 2 && num_destroy == 3);

    /* destroy second item */

    stock->Put(*second, true);
    assert(num_create == 4 && num_fail == 1);
    assert(num_borrow == 2 && num_release == 2 && num_destroy == 4);

    /* destroy third item */

    stock->Put(*third, true);
    assert(num_create == 4 && num_fail == 1);
    assert(num_borrow == 2 && num_release == 2 && num_destroy == 5);

    /* cleanup */

    delete stock;

    pool_unref(pool);
    pool_commit();
    pool_recycler_clear();
}
<commit_msg>test/t_stock: use HeapStockItem<commit_after>#include "stock/Stock.hxx"
#include "stock/Class.hxx"
#include "stock/GetHandler.hxx"
#include "stock/Item.hxx"
#include "event/Base.hxx"
#include "async.hxx"
#include "pool.hxx"

#include <glib.h>

#include <assert.h>

static unsigned num_create, num_fail, num_borrow, num_release, num_destroy;
static bool next_fail;
static bool got_item;
static StockItem *last_item;

struct MyStockItem final : HeapStockItem {
    void *info;

    explicit MyStockItem(CreateStockItem c)
        :HeapStockItem(c) {}

    ~MyStockItem() override {
        ++num_destroy;
    }

    /* virtual methods from class StockItem */
    bool Borrow(gcc_unused void *ctx) override {
        ++num_borrow;
        return true;
    }

    bool Release(gcc_unused void *ctx) override {
        ++num_release;
        return true;
    }
};

static inline GQuark
test_quark(void)
{
    return g_quark_from_static_string("test");
}

/*
 * stock class
 *
 */

static void
my_stock_create(gcc_unused void *ctx,
                gcc_unused struct pool &parent_pool, CreateStockItem c,
                gcc_unused const char *uri, void *info,
                gcc_unused struct pool &caller_pool,
                gcc_unused struct async_operation_ref &async_ref)
{
    auto *item = new MyStockItem(c);

    item->info = info;

    if (next_fail) {
        ++num_fail;

        GError *error = g_error_new_literal(test_quark(), 0, "next_fail");
        item->InvokeCreateError(error);
    } else {
        ++num_create;
        item->InvokeCreateSuccess();
    }
}

static constexpr StockClass my_stock_class = {
    .create = my_stock_create,
};

class MyStockGetHandler final : public StockGetHandler {
public:
    /* virtual methods from class StockGetHandler */
    void OnStockItemReady(StockItem &item) override {
        assert(!got_item);

        got_item = true;
        last_item = &item;
    }

    void OnStockItemError(GError *error) override {
        g_printerr("%s\n", error->message);
        g_error_free(error);

        got_item = true;
        last_item = nullptr;
    }
};

int main(gcc_unused int argc, gcc_unused char **argv)
{
    struct pool *pool;
    Stock *stock;
    struct async_operation_ref async_ref;
    StockItem *item, *second, *third;

    EventBase event_base;
    pool = pool_new_libc(nullptr, "root");

    stock = new Stock(*pool, my_stock_class, nullptr, nullptr, 3, 8);

    MyStockGetHandler handler;

    /* create first item */

    stock->Get(*pool, nullptr, handler, async_ref);
    assert(got_item);
    assert(last_item != nullptr);
    assert(num_create == 1 && num_fail == 0);
    assert(num_borrow == 0 && num_release == 0 && num_destroy == 0);
    item = last_item;

    /* release first item */

    stock->Put(*item, false);
    event_loop(EVLOOP_NONBLOCK);
    assert(num_create == 1 && num_fail == 0);
    assert(num_borrow == 0 && num_release == 1 && num_destroy == 0);

    /* reuse first item */

    got_item = false;
    last_item = nullptr;
    stock->Get(*pool, nullptr, handler, async_ref);
    assert(got_item);
    assert(last_item == item);
    assert(num_create == 1 && num_fail == 0);
    assert(num_borrow == 1 && num_release == 1 && num_destroy == 0);

    /* create second item */

    got_item = false;
    last_item = nullptr;
    stock->Get(*pool, nullptr, handler, async_ref);
    assert(got_item);
    assert(last_item != nullptr);
    assert(last_item != item);
    assert(num_create == 2 && num_fail == 0);
    assert(num_borrow == 1 && num_release == 1 && num_destroy == 0);
    second = last_item;

    /* fail to create third item */

    next_fail = true;
    got_item = false;
    last_item = nullptr;
    stock->Get(*pool, nullptr, handler, async_ref);
    assert(got_item);
    assert(last_item == nullptr);
    assert(num_create == 2 && num_fail == 1);
    assert(num_borrow == 1 && num_release == 1 && num_destroy == 1);

    /* create third item */

    next_fail = false;
    got_item = false;
    last_item = nullptr;
    stock->Get(*pool, nullptr, handler, async_ref);
    assert(got_item);
    assert(last_item != nullptr);
    assert(num_create == 3 && num_fail == 1);
    assert(num_borrow == 1 && num_release == 1 && num_destroy == 1);
    third = last_item;

    /* fourth item waiting */

    got_item = false;
    last_item = nullptr;
    stock->Get(*pool, nullptr, handler, async_ref);
    assert(!got_item);
    assert(num_create == 3 && num_fail == 1);
    assert(num_borrow == 1 && num_release == 1 && num_destroy == 1);

    /* fifth item waiting */

    stock->Get(*pool, nullptr, handler, async_ref);
    assert(!got_item);
    assert(num_create == 3 && num_fail == 1);
    assert(num_borrow == 1 && num_release == 1 && num_destroy == 1);

    /* return third item */

    stock->Put(*third, false);
    event_loop(EVLOOP_NONBLOCK);
    assert(num_create == 3 && num_fail == 1);
    assert(num_borrow == 2 && num_release == 2 && num_destroy == 1);
    assert(got_item);
    assert(last_item == third);

    /* destroy second item */

    got_item = false;
    last_item = nullptr;
    stock->Put(*second, true);
    event_loop(EVLOOP_NONBLOCK);
    assert(num_create == 4 && num_fail == 1);
    assert(num_borrow == 2 && num_release == 2 && num_destroy == 2);
    assert(got_item);
    assert(last_item != nullptr);
    second = last_item;

    /* destroy first item */

    stock->Put(*item, true);
    assert(num_create == 4 && num_fail == 1);
    assert(num_borrow == 2 && num_release == 2 && num_destroy == 3);

    /* destroy second item */

    stock->Put(*second, true);
    assert(num_create == 4 && num_fail == 1);
    assert(num_borrow == 2 && num_release == 2 && num_destroy == 4);

    /* destroy third item */

    stock->Put(*third, true);
    assert(num_create == 4 && num_fail == 1);
    assert(num_borrow == 2 && num_release == 2 && num_destroy == 5);

    /* cleanup */

    delete stock;

    pool_unref(pool);
    pool_commit();
    pool_recycler_clear();
}
<|endoftext|>


<commit_before>// async_queue.cpp (Oclgrind)
// Copyright (c) 2013-2014, James Price and Simon McIntosh-Smith,
// University of Bristol. All rights reserved.
//
// This program is provided under a three-clause BSD license. For full
// license terms please see the LICENSE file distributed with this
// source code.

#include "async_queue.h"

#include <cassert>
#include <iostream>
#include <list>
#include <map>

#include <spirsim/Kernel.h>
#include <spirsim/Queue.h>

using namespace oclgrind;
using namespace std;

// Maps to keep track of retained objects
static map< Queue::Command*, list<cl_mem> > memObjectMap;
static map< Queue::Command*, cl_kernel > kernelMap;
static map< Queue::Command*, cl_event > eventMap;
static map< Queue::Command*, list<cl_event> > waitListMap;

void asyncEnqueue(cl_command_queue queue,
                  cl_command_type type,
                  Queue::Command *cmd,
                  cl_uint numEvents,
                  const cl_event *waitList,
                  cl_event *eventOut)
{
  // Add event wait list to command
  for (int i = 0; i < numEvents; i++)
  {
    cmd->waitList.push_back(waitList[i]->event);
    waitListMap[cmd].push_back(waitList[i]);
    clRetainEvent(waitList[i]);
  }

  // Enqueue command
  Event *event = queue->queue->enqueue(cmd);

  // Create event objects
  cl_event _event = new _cl_event;
  _event->dispatch = m_dispatchTable;
  _event->context = queue->context;
  _event->queue = queue;
  _event->type = type;
  _event->event = event;
  _event->refCount = 1;

  // Add event to map
  eventMap[cmd] = _event;

  // Pass event as output and retain (if required)
  if (eventOut)
  {
    clRetainEvent(_event);
    *eventOut = _event;
  }
}

void asyncQueueRetain(Queue::Command *cmd, cl_mem mem)
{
  // Retain object and add to map
  clRetainMemObject(mem);
  memObjectMap[cmd].push_back(mem);
}

void asyncQueueRetain(Queue::Command *cmd, cl_kernel kernel)
{
  assert(kernelMap.find(cmd) == kernelMap.end());

  // Retain kernel and add to map
  clRetainKernel(kernel);
  kernelMap[cmd] = kernel;

  // Retain memory objects arguments
  map<cl_uint,cl_mem>::const_iterator itr;
  for (itr = kernel->memArgs.begin(); itr != kernel->memArgs.end(); itr++)
  {
    asyncQueueRetain(cmd, itr->second);
  }
}

void asyncQueueRelease(Queue::Command *cmd)
{
  // Release memory objects
  if (memObjectMap.find(cmd) != memObjectMap.end())
  {
    list<cl_mem> memObjects = memObjectMap[cmd];
    while (!memObjects.empty())
    {
      clReleaseMemObject(memObjects.front());
      memObjects.pop_front();
    }
    memObjectMap.erase(cmd);
  }

  // Release kernel
  if (cmd->type == Queue::KERNEL)
  {
    assert(kernelMap.find(cmd) != kernelMap.end());
    clReleaseKernel(kernelMap[cmd]);
    kernelMap.erase(cmd);
    delete ((Queue::KernelCommand*)cmd)->kernel;
  }

  // Remove event from map
  cl_event event = eventMap[cmd];
  eventMap.erase(cmd);

  // Perform callbacks
  list< pair<void (CL_CALLBACK *)(cl_event, cl_int, void *),
             void*> >::iterator callItr;
  for (callItr = event->callbacks.begin();
       callItr != event->callbacks.end();
       callItr++)
  {
    callItr->first(event, event->event->state, callItr->second);
  }

  // Release events
  list<cl_event>::iterator waitItr;
  for (waitItr = waitListMap[cmd].begin();
       waitItr != waitListMap[cmd].end();
       waitItr++)
  {
    clReleaseEvent(*waitItr);
  }
  waitListMap.erase(cmd);
  clReleaseEvent(event);
}
<commit_msg>More includes with user-include syntax.<commit_after>// async_queue.cpp (Oclgrind)
// Copyright (c) 2013-2014, James Price and Simon McIntosh-Smith,
// University of Bristol. All rights reserved.
//
// This program is provided under a three-clause BSD license. For full
// license terms please see the LICENSE file distributed with this
// source code.

#include "async_queue.h"

#include <cassert>
#include <iostream>
#include <list>
#include <map>

#include "spirsim/Kernel.h"
#include "spirsim/Queue.h"

using namespace oclgrind;
using namespace std;

// Maps to keep track of retained objects
static map< Queue::Command*, list<cl_mem> > memObjectMap;
static map< Queue::Command*, cl_kernel > kernelMap;
static map< Queue::Command*, cl_event > eventMap;
static map< Queue::Command*, list<cl_event> > waitListMap;

void asyncEnqueue(cl_command_queue queue,
                  cl_command_type type,
                  Queue::Command *cmd,
                  cl_uint numEvents,
                  const cl_event *waitList,
                  cl_event *eventOut)
{
  // Add event wait list to command
  for (int i = 0; i < numEvents; i++)
  {
    cmd->waitList.push_back(waitList[i]->event);
    waitListMap[cmd].push_back(waitList[i]);
    clRetainEvent(waitList[i]);
  }

  // Enqueue command
  Event *event = queue->queue->enqueue(cmd);

  // Create event objects
  cl_event _event = new _cl_event;
  _event->dispatch = m_dispatchTable;
  _event->context = queue->context;
  _event->queue = queue;
  _event->type = type;
  _event->event = event;
  _event->refCount = 1;

  // Add event to map
  eventMap[cmd] = _event;

  // Pass event as output and retain (if required)
  if (eventOut)
  {
    clRetainEvent(_event);
    *eventOut = _event;
  }
}

void asyncQueueRetain(Queue::Command *cmd, cl_mem mem)
{
  // Retain object and add to map
  clRetainMemObject(mem);
  memObjectMap[cmd].push_back(mem);
}

void asyncQueueRetain(Queue::Command *cmd, cl_kernel kernel)
{
  assert(kernelMap.find(cmd) == kernelMap.end());

  // Retain kernel and add to map
  clRetainKernel(kernel);
  kernelMap[cmd] = kernel;

  // Retain memory objects arguments
  map<cl_uint,cl_mem>::const_iterator itr;
  for (itr = kernel->memArgs.begin(); itr != kernel->memArgs.end(); itr++)
  {
    asyncQueueRetain(cmd, itr->second);
  }
}

void asyncQueueRelease(Queue::Command *cmd)
{
  // Release memory objects
  if (memObjectMap.find(cmd) != memObjectMap.end())
  {
    list<cl_mem> memObjects = memObjectMap[cmd];
    while (!memObjects.empty())
    {
      clReleaseMemObject(memObjects.front());
      memObjects.pop_front();
    }
    memObjectMap.erase(cmd);
  }

  // Release kernel
  if (cmd->type == Queue::KERNEL)
  {
    assert(kernelMap.find(cmd) != kernelMap.end());
    clReleaseKernel(kernelMap[cmd]);
    kernelMap.erase(cmd);
    delete ((Queue::KernelCommand*)cmd)->kernel;
  }

  // Remove event from map
  cl_event event = eventMap[cmd];
  eventMap.erase(cmd);

  // Perform callbacks
  list< pair<void (CL_CALLBACK *)(cl_event, cl_int, void *),
             void*> >::iterator callItr;
  for (callItr = event->callbacks.begin();
       callItr != event->callbacks.end();
       callItr++)
  {
    callItr->first(event, event->event->state, callItr->second);
  }

  // Release events
  list<cl_event>::iterator waitItr;
  for (waitItr = waitListMap[cmd].begin();
       waitItr != waitListMap[cmd].end();
       waitItr++)
  {
    clReleaseEvent(*waitItr);
  }
  waitListMap.erase(cmd);
  clReleaseEvent(event);
}
<|endoftext|>


<commit_before>#include "catch.hpp"
#include <map>
#include <iostream>
#include <functional>

#include <boost/asio.hpp>

// #include <net/asio/statsd.h>

namespace net {
namespace protocol {

namespace statsd {

/** Represents a single item stored on the server */
class stored_item {
public:
	bool operator<(int64_t v) const { return value_ < v; }
	bool operator>(int64_t v) const { return value_ > v; }
	bool operator==(int64_t v) const { return value_ == v; }

	stored_item &operator=(int64_t v) { value_ = v; return *this; }
	stored_item &operator++() { ++value_; }
	stored_item &operator++(int) { operator++(); return *this; }
	stored_item &operator--() { --value_; }
	stored_item &operator--(int) { operator--(); return *this; }

private:
	std::string key_;
	int64_t value_;
};

class gauge : public stored_item { };
class counter : public stored_item { };
class timer : public stored_item { };
class meter : public stored_item { };

#if 0
class x {
public:

	proto << key_ << ":" << value_ << "|" << type_;
	// key_ is a vector of strings
	// value is int64_t
	std::string key_;
	int64_t value_;
	char type_;
};
#endif

/** The server interface */
class server {
public:
	server() = default;

	/** Returns true if we have any information about the given key */
	bool has(const std::string &k) const { return items_.count(k) > 0; }
	const stored_item &key(const std::string &k) const { return items_.at(k); }

private:
	std::map<std::string, stored_item> items_;
};

/** An item that can be updated */
class item {
public:
	item(const std::string &k):key_(k) { }

	item &operator=(int64_t v) { value_ = v; return *this; }
	item &operator++() { ++value_; }
	item &operator++(int) { operator++(); return *this; }
	item &operator--() { --value_; }
	item &operator--(int) { operator--(); return *this; }

private:
	std::string key_;
	int64_t value_;
};

class client {
public:
	client(server &s):srv_(s) { }
	item key(const std::string &s) { }

private:
	server &srv_;
};

};

};
};

class statsd_server : public std::enable_shared_from_this<statsd_server> {
public:
	statsd_server(
		boost::asio::io_service &service
	):endpoint_{ boost::asio::ip::udp::v4(), 0 },
	  socket_{ service, endpoint_ },
	  max_length_{1024}
	{
	}

	uint16_t port() const { return endpoint_.port(); }

	void on_packet(const std::string &in) {
		std::cout << "Incoming packet: " << in << std::endl;
	}

	/**
	 * statsd server - continuously accepts incoming message packets
	 */
	void
	accept_next()
	{
		auto self = shared_from_this();
		/** Incoming data storage */
		auto storage = std::make_shared<std::vector<char>>(max_length_);
		socket_.async_receive_from(
			boost::asio::buffer(&((*storage)[0]), storage->size()),
			endpoint_,
			/* We want to transfer std::unique_ptr ownership to our lambda, but
			 * might not have C++14 semantics available
			 */
			[self, storage](
				const boost::system::error_code &ec,
				size_t bytes
			) {
				if(ec) {
					std::cerr << "Had an error while waiting for next packet: " << ec.message() << std::endl;
				} else if(bytes > 0) {
					self->on_packet(std::string { storage->cbegin(), storage->cend() });
				}
				self->accept_next();
			}
		);
	}

private:
	boost::asio::ip::udp::endpoint endpoint_;
	boost::asio::ip::udp::socket socket_;
	size_t max_length_;
};

/**
 * statsd client - just sends out a packet for each stat
 */
class statsd_client : public std::enable_shared_from_this<statsd_client> {
public:
	statsd_client(
		boost::asio::io_service &service
	):socket_(service, boost::asio::ip::udp::endpoint(boost::asio::ip::udp::v4(), 0)),
	  max_length_{4096}
	{
	}

	void send_packet(const std::string &in)
	{
		auto self = shared_from_this();
		auto storage = std::make_shared<std::vector<char>>(in.cbegin(), in.cend());
		auto length = storage->size();
		socket_.async_send_to(
			boost::asio::buffer(&((*storage)[0]), storage->size()),
			endpoint_,
			[self, length, storage](
				const boost::system::error_code &ec,
				size_t bytes
			) {
				if(ec) {
					std::cerr << "Error sending: " << ec.message() << std::endl;
				} else if(bytes == length) {
					std::cout << "Sent all expected data\n";
				} else {
					std::cerr << "Sent fewer bytes than we expected\n";
				}
			}
		);
	}
private:
	boost::asio::ip::udp::socket socket_;
	boost::asio::ip::udp::endpoint endpoint_;
	size_t max_length_;
};

#if 0
SCENARIO("statsd server") {
	using namespace net::protocol;
	GIVEN("a statsd server instance") {
		auto srv = statsd::server();
		auto cli = statsd::client(srv);
		WHEN("we inc a key") {
			cli.key("some.key")++;
			THEN("the value is correct") {
				CHECK(srv.has("some.key"));
				CHECK(srv.key("some.key") == 1);
			}
		}
		WHEN("we dec that key") {
			cli.key("some.key")--;
			THEN("the value is correct") {
				CHECK(srv.has("some.key"));
				CHECK(srv.key("some.key") == 0);
			}
		}
	}
}
#endif

SCENARIO("UDP handling", "[statsd][udp]") {
	boost::asio::io_service iosrv;
	GIVEN("a statsd server instance") {
		auto srv = statsd_server(iosrv);
		CHECK(srv.port() > 0);
		std::cout << srv.port() << "\n";
		iosrv.run();
	}
}
<commit_msg>Disable this test pending UDP abstraction refactoring<commit_after>#include "catch.hpp"
#include <map>
#include <iostream>
#include <functional>

#include <boost/asio.hpp>

// #include <net/asio/statsd.h>

namespace net {
namespace protocol {

namespace statsd {

/** Represents a single item stored on the server */
class stored_item {
public:
	bool operator<(int64_t v) const { return value_ < v; }
	bool operator>(int64_t v) const { return value_ > v; }
	bool operator==(int64_t v) const { return value_ == v; }

	stored_item &operator=(int64_t v) { value_ = v; return *this; }
	stored_item &operator++() { ++value_; }
	stored_item &operator++(int) { operator++(); return *this; }
	stored_item &operator--() { --value_; }
	stored_item &operator--(int) { operator--(); return *this; }

private:
	std::string key_;
	int64_t value_;
};

class gauge : public stored_item { };
class counter : public stored_item { };
class timer : public stored_item { };
class meter : public stored_item { };

#if 0
class x {
public:

	proto << key_ << ":" << value_ << "|" << type_;
	// key_ is a vector of strings
	// value is int64_t
	std::string key_;
	int64_t value_;
	char type_;
};
#endif

/** The server interface */
class server {
public:
	server() = default;

	/** Returns true if we have any information about the given key */
	bool has(const std::string &k) const { return items_.count(k) > 0; }
	const stored_item &key(const std::string &k) const { return items_.at(k); }

private:
	std::map<std::string, stored_item> items_;
};

/** An item that can be updated */
class item {
public:
	item(const std::string &k):key_(k) { }

	item &operator=(int64_t v) { value_ = v; return *this; }
	item &operator++() { ++value_; }
	item &operator++(int) { operator++(); return *this; }
	item &operator--() { --value_; }
	item &operator--(int) { operator--(); return *this; }

private:
	std::string key_;
	int64_t value_;
};

class client {
public:
	client(server &s):srv_(s) { }
	item key(const std::string &s) { }

private:
	server &srv_;
};

};

};
};

class statsd_server : public std::enable_shared_from_this<statsd_server> {
public:
	statsd_server(
		boost::asio::io_service &service
	):endpoint_{ boost::asio::ip::udp::v4(), 0 },
	  socket_{ service, endpoint_ },
	  max_length_{1024}
	{
	}

	uint16_t port() const { return endpoint_.port(); }

	void on_packet(const std::string &in) {
		std::cout << "Incoming packet: " << in << std::endl;
	}

	/**
	 * statsd server - continuously accepts incoming message packets
	 */
	void
	accept_next()
	{
		auto self = shared_from_this();
		/** Incoming data storage */
		auto storage = std::make_shared<std::vector<char>>(max_length_);
		socket_.async_receive_from(
			boost::asio::buffer(&((*storage)[0]), storage->size()),
			endpoint_,
			/* We want to transfer std::unique_ptr ownership to our lambda, but
			 * might not have C++14 semantics available
			 */
			[self, storage](
				const boost::system::error_code &ec,
				size_t bytes
			) {
				if(ec) {
					std::cerr << "Had an error while waiting for next packet: " << ec.message() << std::endl;
				} else if(bytes > 0) {
					self->on_packet(std::string { storage->cbegin(), storage->cend() });
				}
				self->accept_next();
			}
		);
	}

private:
	boost::asio::ip::udp::endpoint endpoint_;
	boost::asio::ip::udp::socket socket_;
	size_t max_length_;
};

/**
 * statsd client - just sends out a packet for each stat
 */
class statsd_client : public std::enable_shared_from_this<statsd_client> {
public:
	statsd_client(
		boost::asio::io_service &service
	):socket_(service, boost::asio::ip::udp::endpoint(boost::asio::ip::udp::v4(), 0)),
	  max_length_{4096}
	{
	}

	void send_packet(const std::string &in)
	{
		auto self = shared_from_this();
		auto storage = std::make_shared<std::vector<char>>(in.cbegin(), in.cend());
		auto length = storage->size();
		socket_.async_send_to(
			boost::asio::buffer(&((*storage)[0]), storage->size()),
			endpoint_,
			[self, length, storage](
				const boost::system::error_code &ec,
				size_t bytes
			) {
				if(ec) {
					std::cerr << "Error sending: " << ec.message() << std::endl;
				} else if(bytes == length) {
					std::cout << "Sent all expected data\n";
				} else {
					std::cerr << "Sent fewer bytes than we expected\n";
				}
			}
		);
	}
private:
	boost::asio::ip::udp::socket socket_;
	boost::asio::ip::udp::endpoint endpoint_;
	size_t max_length_;
};

#if 0
SCENARIO("statsd server") {
	using namespace net::protocol;
	GIVEN("a statsd server instance") {
		auto srv = statsd::server();
		auto cli = statsd::client(srv);
		WHEN("we inc a key") {
			cli.key("some.key")++;
			THEN("the value is correct") {
				CHECK(srv.has("some.key"));
				CHECK(srv.key("some.key") == 1);
			}
		}
		WHEN("we dec that key") {
			cli.key("some.key")--;
			THEN("the value is correct") {
				CHECK(srv.has("some.key"));
				CHECK(srv.key("some.key") == 0);
			}
		}
	}
}

SCENARIO("UDP handling", "[statsd][udp]") {
	boost::asio::io_service iosrv;
	GIVEN("a statsd server instance") {
		auto srv = statsd_server(iosrv);
		CHECK(srv.port() > 0);
		std::cout << srv.port() << "\n";
		iosrv.run();
	}
}
#endif
<|endoftext|>


<commit_before>#include "../includes/FileWatcher.h"
#include "../includes/FileWatcherInterface.h"

#if defined(_WIN32)
#include "../includes/FileWatcher32.h"
#define USE_WINDOWS_INIT
#elif defined(__APPLE_CC__) || defined(BSD)
#include "../includes/FileWatcherOSX.h"
#define FILE_WATCHER_INTERFACE FileWatcherOSX
#elif defined(__linux__)
#include "../includes/FileWatcherLinux.h"
#define FILE_WATCHER_INTERFACE FileWatcherLinux
#endif

namespace NSFW {

  FileWatcher::FileWatcher(std::string path)
   : mPath(path), mWatchFiles(false) {}

  FileWatcher::~FileWatcher() {
    #ifndef USE_WINDOWS_INIT
    delete fwInterface;
    #endif
  }

  // Public methods
  bool FileWatcher::running() {
    return mWatchFiles;
  }

  bool FileWatcher::start() {
    if (!mWatchFiles) {
      mWatchFiles = true;

      // normalization
      if (mPath[mPath.length() - 1] == '/' || mPath[mPath.length() - 1] == '\\') {
        mPath = mPath.substr(0, mPath.length() - 2);
      }

      #if defined(USE_WINDOWS_INIT)
      createFileWatcher(mPath, mEventsQueue, mWatchFiles);
      #else
      fwInterface = new FILE_WATCHER_INTERFACE(mPath, mEventsQueue, mWatchFiles);
      fwInterface->start();
      #endif
      return true;
    } else {
      return false;
    }
  }

  bool FileWatcher::stop() {
    if (!mWatchFiles) {
      return false;
    } else {
      mWatchFiles = false;
      #ifndef USE_WINDOWS_INIT
      fwInterface->stop();
      delete fwInterface;
      #endif
      return true;
    }
  }

  // Internal methods
  std::queue<Event> *FileWatcher::pollEvents() {
    if (mEventsQueue.empty) {
      return NULL;
    }
    std::queue<Event> *out = new std::queue<Event>();
    std::swap(mEventsQueue, *out);
    return out;
  }

}
<commit_msg>Fixed syntax error<commit_after>#include "../includes/FileWatcher.h"
#include "../includes/FileWatcherInterface.h"

#if defined(_WIN32)
#include "../includes/FileWatcher32.h"
#define USE_WINDOWS_INIT
#elif defined(__APPLE_CC__) || defined(BSD)
#include "../includes/FileWatcherOSX.h"
#define FILE_WATCHER_INTERFACE FileWatcherOSX
#elif defined(__linux__)
#include "../includes/FileWatcherLinux.h"
#define FILE_WATCHER_INTERFACE FileWatcherLinux
#endif

namespace NSFW {

  FileWatcher::FileWatcher(std::string path)
   : mPath(path), mWatchFiles(false) {}

  FileWatcher::~FileWatcher() {
    #ifndef USE_WINDOWS_INIT
    delete fwInterface;
    #endif
  }

  // Public methods
  bool FileWatcher::running() {
    return mWatchFiles;
  }

  bool FileWatcher::start() {
    if (!mWatchFiles) {
      mWatchFiles = true;

      // normalization
      if (mPath[mPath.length() - 1] == '/' || mPath[mPath.length() - 1] == '\\') {
        mPath = mPath.substr(0, mPath.length() - 2);
      }

      #if defined(USE_WINDOWS_INIT)
      createFileWatcher(mPath, mEventsQueue, mWatchFiles);
      #else
      fwInterface = new FILE_WATCHER_INTERFACE(mPath, mEventsQueue, mWatchFiles);
      fwInterface->start();
      #endif
      return true;
    } else {
      return false;
    }
  }

  bool FileWatcher::stop() {
    if (!mWatchFiles) {
      return false;
    } else {
      mWatchFiles = false;
      #ifndef USE_WINDOWS_INIT
      fwInterface->stop();
      delete fwInterface;
      #endif
      return true;
    }
  }

  // Internal methods
  std::queue<Event> *FileWatcher::pollEvents() {
    if (mEventsQueue.empty()) {
      return NULL;
    }
    std::queue<Event> *out = new std::queue<Event>();
    std::swap(mEventsQueue, *out);
    return out;
  }

}
<|endoftext|>


<commit_before>#include "sto3g.hpp"
//
//
//
void lcao_wavefunction::sto3g::build_repulsion_matrix()
{
//
    v_matrix.create_array(number_of_atoms, number_of_atoms);
    v_matrix.array::set_config(*config);
    v_matrix.set_name("One electron Coulomb repulsion matrix");
//
    double ii_integral = 0.0;
    double ij_integral = 0.0;
    double jj_integral = 0.0;
    double i_distance  = 0.0;
    double j_distance  = 0.0;
    double ij_distance = 0.0;
    double i_atomic_num = 0.0;
    double a = 0.0;
    double b = 0.0;
    double c = 0.0;
    double d = 0.0;
    double e = 0.0;
    double f = 0.0;
    unsigned int i_atom = 0;
    unsigned int i_type = 0;
    #pragma omp parallel for private(i_atom, i_type, i_atomic_num, ij_distance, i_distance, a, b, c, d, e, f) reduction(+:ii_integral, ij_integral, jj_integral) ordered schedule(dynamic)
    for(i_atom = 1; i_atom <= number_of_atoms; i_atom++)
    {
        i_type = (type -> get(i_atom));
        i_atomic_num = ((double) i_type);
        unsigned int j_atom = 0;
        unsigned int j_type = 0;
        #pragma omp parallel for private(j_atom, j_type, ij_distance, j_distance, a, b, c, d, e, f) reduction(+:ii_integral, ij_integral, jj_integral) ordered schedule(dynamic)
        for(j_atom = 1; j_atom <= number_of_atoms; j_atom++)
        {
            j_type = (type -> get(j_atom));
            if(i_atom == j_atom)
            {
                unsigned int m_primitive = 0;
                #pragma omp parallel for private(m_primitive, a, b, c, d, e, f) reduction(+:ii_integral, ij_integral, jj_integral) ordered schedule(dynamic)
                for(m_primitive = 1; m_primitive <= (i_type == 1? 3:6); m_primitive++)
                {
                    unsigned int n_primitive = 0;
                    #pragma omp parallel for private(n_primitive, a, b, c, d, e, f) reduction(+:ii_integral, ij_integral, jj_integral) ordered schedule(dynamic)
                    for(n_primitive = 1; n_primitive <= (i_type == 1? 3:6); n_primitive++)
                    {
                        #pragma omp parallel sections num_threads(4)
                        {
                            #pragma omp section
                            {
                                a = coeff(i_type, m_primitive)*coeff(i_type, n_primitive);
                            }
                            #pragma omp section
                            {
                                b = -2.0*M_PI/(exp(i_type, m_primitive) + exp(i_type, n_primitive));
                            }
                            #pragma omp section
                            {
                                c = gf_product_const(exp(i_type, m_primitive), exp(i_type, n_primitive), 0.0);
                            }
                            #pragma omp section
                            {
                                d = error_function(0.0);
                            }
                        }
//
                        #pragma omp atomic
                        ii_integral += a*b*c*d*i_atomic_num;
//
                        a = b = c = d = 0.0;
                    } // for(n_primitive)
                } // for(m_primitive)
                v_matrix.set(i_atom, j_atom, v_matrix.get(i_atom, j_atom) + ii_integral);
                ii_integral = 0.0;
            }
            else // if(i_atom != j_atom)
            {
                ij_distance = interatomic_distance(i_atom, j_atom);
                for(unsigned int m_primitive = 1; m_primitive <= (i_type == 1? 3:6); m_primitive++)
                {
                    for(unsigned int n_primitive = 1; n_primitive <= (i_type == 1? 3:6); n_primitive++)
                    {
                        gf_midpoint(i_distance,
                                    j_distance,
                                    exp(i_type, m_primitive),
                                    exp(j_type, n_primitive),
                                    ij_distance);
                        a =  gsl_pow_2(i_distance)*(exp(i_type, m_primitive) + exp(j_type, n_primitive));
                        b =  gsl_pow_2(ij_distance)*(exp(j_type, m_primitive) + exp(j_type, n_primitive));
                        #pragma omp parallel sections num_threads(4)
                        {
                            #pragma omp section
                            {
                                c = coeff(i_type, m_primitive)*coeff(j_type, n_primitive);
                            }
                            #pragma omp section
                            {
                                d = -2.0*M_PI/(exp(i_type, m_primitive) + exp(j_type, n_primitive));
                            }
                            #pragma omp section
                            {
                                e = gf_product_const(exp(i_type, m_primitive), exp(j_type, n_primitive), ij_distance);
                            }
                            #pragma omp section
                            {
                                f = error_function(a);
                            }
                        }
//
                        #pragma omp atomic
                        ij_integral += c*d*e*f*i_atomic_num;
//
                        c = d = e = f = 0.0;
                        #pragma omp parallel sections num_threads(4)
                        {
                            #pragma omp section
                            {
                                c = coeff(j_type, m_primitive)*coeff(j_type, n_primitive);
                            }
                            #pragma omp section
                            {
                                d = -2.0*M_PI/(exp(j_type, m_primitive) + exp(j_type, n_primitive));
                            }
                            #pragma omp section
                            {
                                e = gf_product_const(exp(j_type, m_primitive), exp(j_type, n_primitive), 0.0);
                            }
                            #pragma omp section
                            {
                                f = error_function(b);
                            }
                        }
//
                        #pragma omp atomic
                        jj_integral += c*d*e*f*i_atomic_num;
//
                        a = b = c = d = e = f = 0.0;
                    } // for(n_primitive)
                } // for(m_primitive)
                v_matrix.set(i_atom, j_atom, v_matrix.get(i_atom, j_atom) + ij_integral);
                v_matrix.set(j_atom, i_atom, v_matrix.get(i_atom, j_atom));
                v_matrix.set(j_atom, j_atom, v_matrix.get(j_atom, j_atom) + jj_integral);
                ij_integral = jj_integral = i_distance = j_distance = ij_distance = 0.0;
            }
        } // for(j_atom)
    } // for(i_atom)
}
<commit_msg>Delete sto3g__build_repulsion_matrix.cpp<commit_after><|endoftext|>


<commit_before>//
//  OperatorType.cpp
//  lemonscript
//
//  Created by Donald Pinckney on 2/28/16.
//  Copyright © 2016 Donald Pinckney. All rights reserved.
//

#include "OperatorType.h"

#include <string.h>
#include <functional>
#include <math.h>

#include "AvailableCppCommandDeclaration.h"

using namespace lemonscript_expressions;
using namespace lemonscript;
using namespace std;

std::ostream & lemonscript_expressions::operator<<(std::ostream &o, OperatorType opType) {
    o << opType.operatorText;
    return o;
}

/*

const Operator<ExpressionDesc> DataType_unaryNegO("!.*", 1, true, operatorResolve(genericOperatorTypes({BOOLEAN}, {unaryNegO<bool>}, 1)));
const Operator<ExpressionDesc> DataType_unaryMathNegO("-.*", 1, true, operatorResolve(genericOperatorTypes({INT,FLOAT}, {unaryMathNegO<int>, unaryMathNegO<float>}, 1)));

const Operator<ExpressionDesc> DataType_expO(".*\\^.*", 2, true, operatorResolve(genericOperatorTypes({INT,FLOAT}, {binaryExpO<int>, binaryExpO<float>}, 2)));

const Operator<ExpressionDesc> DataType_modO(".*%.*", 2, true, operatorResolve(genericOperatorTypes({INT}, {binaryModO<int>}, 2)));
const Operator<ExpressionDesc> DataType_divO("/", 2, true, operatorResolve(genericOperatorTypes({INT,FLOAT}, {binaryDivO<int>, binaryDivO<float>}, 2)));
const Operator<ExpressionDesc> DataType_andO(".*&&.*", 2, true, operatorResolve(genericOperatorTypes({BOOLEAN}, {binaryAndO<bool>}, 2)));
const Operator<ExpressionDesc> DataType_multO(".*\\*.*", 2, true, operatorResolve(genericOperatorTypes({INT,FLOAT}, {binaryMultO<int>, binaryMultO<float>}, 2)));

const Operator<ExpressionDesc> DataType_subO(".*-.*", 2, true, operatorResolve(genericOperatorTypes({INT,FLOAT}, {binarySubO<int>, binarySubO<float>}, 2)));
const Operator<ExpressionDesc> DataType_orO(".*\\|\\|.*", 2, true, operatorResolve(genericOperatorTypes({BOOLEAN}, {binaryOrO<bool>}, 2)));
const Operator<ExpressionDesc> DataType_addO(".*\\+.*", 2, true, operatorResolve(genericOperatorTypes({INT,FLOAT}, {binaryAddO<int>, binaryAddO<float>}, 2)));

const Operator<ExpressionDesc> DataType_impliesO(".*=>.*", 2, true, operatorResolve(genericOperatorTypes({BOOLEAN}, {binaryImpliesO<bool>}, 2)));

const Operator<ExpressionDesc> DataType_equalsO(".*==.*", 2, true, operatorResolve(genericOperatorTypesOtherReturn({INT,FLOAT,BOOLEAN}, {binaryEqualsO<int>, binaryEqualsFLOAT_O<float>, binaryEqualsO<bool>}, BOOLEAN, 2)));

*/

// Unary operators
// Precedence N/A
template <typename T>
T negation(T x) {
    return -x;
}

template <typename T>
T boolNegation(T x) {
    return !x;
}

// Binary operators

// Exponentiation: 160
template <typename T>
T exp(T x, T y) {
    return (T)powf((float)x, (float)y);
}

// Multiplicative: 150
template <typename T>
T mult(T x, T y) {
    return x * y;
}

template <typename T>
T div(T x, T y) {
    return x / y;
}

template <typename T>
T mod(T x, T y) {
    return x % y;
}

// Additive: 140
template <typename T>
T add(T x, T y) {
    return x + y;
}

template <typename T>
T subtract(T x, T y) {
    return x - y;
}

// Cast: 132
template <typename T, typename U>
U as(T x) {
    return (U)x;
}

// Implication: 131
template <typename T>
T implies(T x, T y) {
    return !x || y;
}

// Comparative: 130
template <typename T>
bool equal(T x, T y) {
    return x == y;
}

template <typename T>
bool notEqual(T x, T y) {
    return x != y;
}

template <typename T>
bool leq(T x, T y) {
    return x <= y;
}

template <typename T>
bool geq(T x, T y) {
    return x >= y;
}

template <typename T>
bool lessThan(T x, T y) {
    return x < y;
}

template <typename T>
bool greaterThan(T x, T y) {
    return x > y;
}

// Conjuctive: 120
template <typename T>
T _and(T x, T y) {
    return x && y;
}

// Disjunctive: 110
template <typename T>
T _or (T x, T y) {
    return x || y;
}

template <typename T>
TypeSpecification generateTypeSpecificationUnaryGenericUniform(DataType t, function<T (T)> f) {

    TypeSpecification spec;
    spec.inputTypes = {t};
    spec.returnType = t;
    spec.func = [f] (std::vector<int> xs) {

        T retVal = f(*(T *)&xs[0]);

        int retInt;
        bzero(&retInt, sizeof(int));

        memcpy(&retInt, &retVal, sizeof(T));

        return retInt;
    };

    return spec;
}

template <typename T>
TypeSpecification generateTypeSpecificationBinaryGenericUniform(DataType t, function<T (T,T)> f) {

    TypeSpecification spec;
    spec.inputTypes = {t, t};
    spec.returnType = t;
    spec.func = [f] (std::vector<int> xs) {

        T retVal = f(*(T *)&xs[0], *(T *)&xs[1]);

        int retInt;
        bzero(&retInt, sizeof(int));

        memcpy(&retInt, &retVal, sizeof(T));

        return retInt;
    };

    return spec;
}

template <typename T, typename U>
TypeSpecification generateTypeSpecificationBinaryGenericUniformSpecificReturn(DataType t, DataType u, function<U (T,T)> f) {

    TypeSpecification spec;
    spec.inputTypes = {t, t};
    spec.returnType = u;
    spec.func = [f] (std::vector<int> xs) {

        U retVal = f(*(T *)&xs[0], *(T *)&xs[1]);

        int retInt;
        bzero(&retInt, sizeof(int));

        memcpy(&retInt, &retVal, sizeof(U));

        return retInt;
    };

    return spec;
}

map<string, OperatorType> OperatorType::operatorTypeMemoization;

OperatorType OperatorType::lookupOperatorType(std::string opString) {

    OperatorType &opType = operatorTypeMemoization[opString];

    if(opType.operatorText.length() > 0) {
        return opType;
    }

    opType.isIdentityOperator = false;
    opType.operatorText = opString;

    int precedence;
    vector<TypeSpecification> typeSpecs;

    if(opString == "!") {
        TypeSpecification unaryNegationBool = generateTypeSpecificationUnaryGenericUniform<bool>(DataType::BOOLEAN, boolNegation<bool>);
        precedence = 999;
        typeSpecs = {unaryNegationBool};
    } else if(opString == "^") {
        TypeSpecification binaryInt = generateTypeSpecificationBinaryGenericUniform<int>(DataType::INT, exp<int>);
        TypeSpecification binaryFloat = generateTypeSpecificationBinaryGenericUniform<float>(DataType::FLOAT, exp<float>);

        typeSpecs = {binaryInt, binaryFloat};
        precedence = 160;
    } else if(opString == "*") {
        TypeSpecification binaryInt = generateTypeSpecificationBinaryGenericUniform<int>(DataType::INT, mult<int>);
        TypeSpecification binaryFloat = generateTypeSpecificationBinaryGenericUniform<float>(DataType::FLOAT, mult<float>);

        typeSpecs = {binaryInt, binaryFloat};
        precedence = 150;
    } else if(opString == "/") {
        TypeSpecification binaryInt = generateTypeSpecificationBinaryGenericUniform<int>(DataType::INT, div<int>);
        TypeSpecification binaryFloat = generateTypeSpecificationBinaryGenericUniform<float>(DataType::FLOAT, div<float>);

        typeSpecs = {binaryInt, binaryFloat};
        precedence = 150;
    } else if(opString == "%") {
        TypeSpecification binaryInt = generateTypeSpecificationBinaryGenericUniform<int>(DataType::INT, mod<int>);

        typeSpecs = {binaryInt};
        precedence = 150;
    } else if(opString == "+") {
        TypeSpecification binaryInt = generateTypeSpecificationBinaryGenericUniform<int>(DataType::INT, add<int>);
        TypeSpecification binaryFloat = generateTypeSpecificationBinaryGenericUniform<float>(DataType::FLOAT, add<float>);

        typeSpecs = {binaryInt, binaryFloat};
        precedence = 140;
    } else if(opString == "-") {
        TypeSpecification unaryMinusInt = generateTypeSpecificationUnaryGenericUniform<int>(DataType::INT, negation<int>);
        TypeSpecification unaryMinusFloat = generateTypeSpecificationUnaryGenericUniform<float>(DataType::FLOAT, negation<float>);

        TypeSpecification binaryMinusInt = generateTypeSpecificationBinaryGenericUniform<int>(DataType::INT, subtract<int>);
        TypeSpecification binaryMinusFloat = generateTypeSpecificationBinaryGenericUniform<float>(DataType::FLOAT, subtract<float>);

        typeSpecs = {unaryMinusInt, unaryMinusFloat, binaryMinusInt, binaryMinusFloat};
        precedence = 140;
    } else if(opString == "=>") {
        TypeSpecification binaryBool = generateTypeSpecificationBinaryGenericUniform<bool>(DataType::BOOLEAN, implies<bool>);

        typeSpecs = {binaryBool};
        precedence = 131;
    } else if(opString == "==") {
        TypeSpecification binaryBool = generateTypeSpecificationBinaryGenericUniformSpecificReturn<bool, bool>(DataType::BOOLEAN, DataType::BOOLEAN, equal<bool>);
        TypeSpecification binaryInt = generateTypeSpecificationBinaryGenericUniformSpecificReturn<int, bool>(DataType::INT, DataType::BOOLEAN, equal<int>);
        TypeSpecification binaryFloat = generateTypeSpecificationBinaryGenericUniformSpecificReturn<float, bool>(DataType::FLOAT, DataType::BOOLEAN, equal<float>);

        typeSpecs = {binaryBool, binaryInt, binaryFloat};
        precedence = 130;
    } else if(opString == "!=") {
        TypeSpecification binaryBool = generateTypeSpecificationBinaryGenericUniformSpecificReturn<bool, bool>(DataType::BOOLEAN, DataType::BOOLEAN, notEqual<bool>);
        TypeSpecification binaryInt = generateTypeSpecificationBinaryGenericUniformSpecificReturn<int, bool>(DataType::INT, DataType::BOOLEAN, notEqual<int>);
        TypeSpecification binaryFloat = generateTypeSpecificationBinaryGenericUniformSpecificReturn<float, bool>(DataType::FLOAT, DataType::BOOLEAN, notEqual<float>);

        typeSpecs = {binaryBool, binaryInt, binaryFloat};
        precedence = 130;
    } else if(opString == "<=") {
        TypeSpecification binaryBool = generateTypeSpecificationBinaryGenericUniformSpecificReturn<bool, bool>(DataType::BOOLEAN, DataType::BOOLEAN, leq<bool>);
        TypeSpecification binaryInt = generateTypeSpecificationBinaryGenericUniformSpecificReturn<int, bool>(DataType::INT, DataType::BOOLEAN, leq<int>);
        TypeSpecification binaryFloat = generateTypeSpecificationBinaryGenericUniformSpecificReturn<float, bool>(DataType::FLOAT, DataType::BOOLEAN, leq<float>);

        typeSpecs = {binaryBool, binaryInt, binaryFloat};
        precedence = 130;
    } else if(opString == ">=") {
        TypeSpecification binaryBool = generateTypeSpecificationBinaryGenericUniformSpecificReturn<bool, bool>(DataType::BOOLEAN, DataType::BOOLEAN, geq<bool>);
        TypeSpecification binaryInt = generateTypeSpecificationBinaryGenericUniformSpecificReturn<int, bool>(DataType::INT, DataType::BOOLEAN, geq<int>);
        TypeSpecification binaryFloat = generateTypeSpecificationBinaryGenericUniformSpecificReturn<float, bool>(DataType::FLOAT, DataType::BOOLEAN, geq<float>);

        typeSpecs = {binaryBool, binaryInt, binaryFloat};
        precedence = 130;
    } else if(opString == "<") {
        TypeSpecification binaryBool = generateTypeSpecificationBinaryGenericUniformSpecificReturn<bool, bool>(DataType::BOOLEAN, DataType::BOOLEAN, lessThan<bool>);
        TypeSpecification binaryInt = generateTypeSpecificationBinaryGenericUniformSpecificReturn<int, bool>(DataType::INT, DataType::BOOLEAN, lessThan<int>);
        TypeSpecification binaryFloat = generateTypeSpecificationBinaryGenericUniformSpecificReturn<float, bool>(DataType::FLOAT, DataType::BOOLEAN, lessThan<float>);

        typeSpecs = {binaryBool, binaryInt, binaryFloat};
        precedence = 130;
    } else if(opString == ">") {
        TypeSpecification binaryBool = generateTypeSpecificationBinaryGenericUniformSpecificReturn<bool, bool>(DataType::BOOLEAN, DataType::BOOLEAN, greaterThan<bool>);
        TypeSpecification binaryInt = generateTypeSpecificationBinaryGenericUniformSpecificReturn<int, bool>(DataType::INT, DataType::BOOLEAN, greaterThan<int>);
        TypeSpecification binaryFloat = generateTypeSpecificationBinaryGenericUniformSpecificReturn<float, bool>(DataType::FLOAT, DataType::BOOLEAN, greaterThan<float>);

        typeSpecs = {binaryBool, binaryInt, binaryFloat};
        precedence = 130;
    } else if(opString == "&&") {
        TypeSpecification binaryBool = generateTypeSpecificationBinaryGenericUniform<bool>(DataType::BOOLEAN, _and<bool>);

        typeSpecs = {binaryBool};
        precedence = 120;
    } else if(opString == "||") {
        TypeSpecification binaryBool = generateTypeSpecificationBinaryGenericUniform<bool>(DataType::BOOLEAN, _or<bool>);

        typeSpecs = {binaryBool};
        precedence = 110;
    } else {
        throw "Unknown operator: " + opString;
    }

    opType.specifications = typeSpecs;
    opType.precedence = precedence;

    return opType;
}

OperatorType OperatorType::identity() {
    std::vector<TypeSpecification> specs;
    std::vector<lemonscript::DataType> types = {lemonscript::DataType::BOOLEAN, lemonscript::DataType::INT, lemonscript::DataType::FLOAT};
    for(auto it = types.begin(); it != types.end(); ++it) {
        lemonscript::DataType t = *it;
        TypeSpecification spec;
        spec.inputTypes = {t};
        spec.returnType = t;
        spec.func = [] (std::vector<int> xs) { return xs[0]; };
        specs.push_back(spec);
    }
    OperatorType opType;
    opType.isIdentityOperator = true;
    opType.specifications = specs;
    opType.operatorText = "i";
    opType.precedence = 999;

    return opType;
}<commit_msg>Fix build on (recent versions of ) GCC (#24)<commit_after>//
//  OperatorType.cpp
//  lemonscript
//
//  Created by Donald Pinckney on 2/28/16.
//  Copyright © 2016 Donald Pinckney. All rights reserved.
//

#include "OperatorType.h"

#include <string.h>
#include <functional>
#include <cmath>

#include "AvailableCppCommandDeclaration.h"

using namespace lemonscript_expressions;
using namespace lemonscript;

using std::function;
using std::vector;
using std::map;
using std::string;

std::ostream & lemonscript_expressions::operator<<(std::ostream &o, OperatorType opType) {
    o << opType.operatorText;
    return o;
}

/*

const Operator<ExpressionDesc> DataType_unaryNegO("!.*", 1, true, operatorResolve(genericOperatorTypes({BOOLEAN}, {unaryNegO<bool>}, 1)));
const Operator<ExpressionDesc> DataType_unaryMathNegO("-.*", 1, true, operatorResolve(genericOperatorTypes({INT,FLOAT}, {unaryMathNegO<int>, unaryMathNegO<float>}, 1)));

const Operator<ExpressionDesc> DataType_expO(".*\\^.*", 2, true, operatorResolve(genericOperatorTypes({INT,FLOAT}, {binaryExpO<int>, binaryExpO<float>}, 2)));

const Operator<ExpressionDesc> DataType_modO(".*%.*", 2, true, operatorResolve(genericOperatorTypes({INT}, {binaryModO<int>}, 2)));
const Operator<ExpressionDesc> DataType_divO("/", 2, true, operatorResolve(genericOperatorTypes({INT,FLOAT}, {binaryDivO<int>, binaryDivO<float>}, 2)));
const Operator<ExpressionDesc> DataType_andO(".*&&.*", 2, true, operatorResolve(genericOperatorTypes({BOOLEAN}, {binaryAndO<bool>}, 2)));
const Operator<ExpressionDesc> DataType_multO(".*\\*.*", 2, true, operatorResolve(genericOperatorTypes({INT,FLOAT}, {binaryMultO<int>, binaryMultO<float>}, 2)));

const Operator<ExpressionDesc> DataType_subO(".*-.*", 2, true, operatorResolve(genericOperatorTypes({INT,FLOAT}, {binarySubO<int>, binarySubO<float>}, 2)));
const Operator<ExpressionDesc> DataType_orO(".*\\|\\|.*", 2, true, operatorResolve(genericOperatorTypes({BOOLEAN}, {binaryOrO<bool>}, 2)));
const Operator<ExpressionDesc> DataType_addO(".*\\+.*", 2, true, operatorResolve(genericOperatorTypes({INT,FLOAT}, {binaryAddO<int>, binaryAddO<float>}, 2)));

const Operator<ExpressionDesc> DataType_impliesO(".*=>.*", 2, true, operatorResolve(genericOperatorTypes({BOOLEAN}, {binaryImpliesO<bool>}, 2)));

const Operator<ExpressionDesc> DataType_equalsO(".*==.*", 2, true, operatorResolve(genericOperatorTypesOtherReturn({INT,FLOAT,BOOLEAN}, {binaryEqualsO<int>, binaryEqualsFLOAT_O<float>, binaryEqualsO<bool>}, BOOLEAN, 2)));

*/

// Unary operators
// Precedence N/A
template <typename T>
T negation(T x) {
    return -x;
}

template <typename T>
T boolNegation(T x) {
    return !x;
}

// Binary operators

// Exponentiation: 160
template <typename T>
T exp(T x, T y) {
    return (T)powf((float)x, (float)y);
}

// Multiplicative: 150
template <typename T>
T mult(T x, T y) {
    return x * y;
}

template <typename T>
T div(T x, T y) {
    return x / y;
}

template <typename T>
T mod(T x, T y) {
    return x % y;
}

// Additive: 140
template <typename T>
T add(T x, T y) {
    return x + y;
}

template <typename T>
T subtract(T x, T y) {
    return x - y;
}

// Cast: 132
template <typename T, typename U>
U as(T x) {
    return (U)x;
}

// Implication: 131
template <typename T>
T implies(T x, T y) {
    return !x || y;
}

// Comparative: 130
template <typename T>
bool equal(T x, T y) {
    return x == y;
}

template <typename T>
bool notEqual(T x, T y) {
    return x != y;
}

template <typename T>
bool leq(T x, T y) {
    return x <= y;
}

template <typename T>
bool geq(T x, T y) {
    return x >= y;
}

template <typename T>
bool lessThan(T x, T y) {
    return x < y;
}

template <typename T>
bool greaterThan(T x, T y) {
    return x > y;
}

// Conjuctive: 120
template <typename T>
T _and(T x, T y) {
    return x && y;
}

// Disjunctive: 110
template <typename T>
T _or (T x, T y) {
    return x || y;
}

template <typename T>
TypeSpecification generateTypeSpecificationUnaryGenericUniform(DataType t, function<T (T)> f) {

    TypeSpecification spec;
    spec.inputTypes = {t};
    spec.returnType = t;
    spec.func = [f] (std::vector<int> xs) {

        T retVal = f(*(T *)&xs[0]);

        int retInt;
        bzero(&retInt, sizeof(int));

        memcpy(&retInt, &retVal, sizeof(T));

        return retInt;
    };

    return spec;
}

template <typename T>
TypeSpecification generateTypeSpecificationBinaryGenericUniform(DataType t, function<T (T,T)> f) {

    TypeSpecification spec;
    spec.inputTypes = {t, t};
    spec.returnType = t;
    spec.func = [f] (std::vector<int> xs) {

        T retVal = f(*(T *)&xs[0], *(T *)&xs[1]);

        int retInt;
        bzero(&retInt, sizeof(int));

        memcpy(&retInt, &retVal, sizeof(T));

        return retInt;
    };

    return spec;
}

template <typename T, typename U>
TypeSpecification generateTypeSpecificationBinaryGenericUniformSpecificReturn(DataType t, DataType u, function<U (T,T)> f) {

    TypeSpecification spec;
    spec.inputTypes = {t, t};
    spec.returnType = u;
    spec.func = [f] (std::vector<int> xs) {

        U retVal = f(*(T *)&xs[0], *(T *)&xs[1]);

        int retInt;
        bzero(&retInt, sizeof(int));

        memcpy(&retInt, &retVal, sizeof(U));

        return retInt;
    };

    return spec;
}

map<string, OperatorType> OperatorType::operatorTypeMemoization;

OperatorType OperatorType::lookupOperatorType(std::string opString) {

    OperatorType &opType = operatorTypeMemoization[opString];

    if(opType.operatorText.length() > 0) {
        return opType;
    }

    opType.isIdentityOperator = false;
    opType.operatorText = opString;

    int precedence;
    vector<TypeSpecification> typeSpecs;

    if(opString == "!") {
        TypeSpecification unaryNegationBool = generateTypeSpecificationUnaryGenericUniform<bool>(DataType::BOOLEAN, boolNegation<bool>);
        precedence = 999;
        typeSpecs = {unaryNegationBool};
    } else if(opString == "^") {
        TypeSpecification binaryInt = generateTypeSpecificationBinaryGenericUniform<int>(DataType::INT, exp<int>);
        TypeSpecification binaryFloat = generateTypeSpecificationBinaryGenericUniform<float>(DataType::FLOAT, exp<float>);

        typeSpecs = {binaryInt, binaryFloat};
        precedence = 160;
    } else if(opString == "*") {
        TypeSpecification binaryInt = generateTypeSpecificationBinaryGenericUniform<int>(DataType::INT, mult<int>);
        TypeSpecification binaryFloat = generateTypeSpecificationBinaryGenericUniform<float>(DataType::FLOAT, mult<float>);

        typeSpecs = {binaryInt, binaryFloat};
        precedence = 150;
    } else if(opString == "/") {
        TypeSpecification binaryInt = generateTypeSpecificationBinaryGenericUniform<int>(DataType::INT, div<int>);
        TypeSpecification binaryFloat = generateTypeSpecificationBinaryGenericUniform<float>(DataType::FLOAT, div<float>);

        typeSpecs = {binaryInt, binaryFloat};
        precedence = 150;
    } else if(opString == "%") {
        TypeSpecification binaryInt = generateTypeSpecificationBinaryGenericUniform<int>(DataType::INT, mod<int>);

        typeSpecs = {binaryInt};
        precedence = 150;
    } else if(opString == "+") {
        TypeSpecification binaryInt = generateTypeSpecificationBinaryGenericUniform<int>(DataType::INT, add<int>);
        TypeSpecification binaryFloat = generateTypeSpecificationBinaryGenericUniform<float>(DataType::FLOAT, add<float>);

        typeSpecs = {binaryInt, binaryFloat};
        precedence = 140;
    } else if(opString == "-") {
        TypeSpecification unaryMinusInt = generateTypeSpecificationUnaryGenericUniform<int>(DataType::INT, negation<int>);
        TypeSpecification unaryMinusFloat = generateTypeSpecificationUnaryGenericUniform<float>(DataType::FLOAT, negation<float>);

        TypeSpecification binaryMinusInt = generateTypeSpecificationBinaryGenericUniform<int>(DataType::INT, subtract<int>);
        TypeSpecification binaryMinusFloat = generateTypeSpecificationBinaryGenericUniform<float>(DataType::FLOAT, subtract<float>);

        typeSpecs = {unaryMinusInt, unaryMinusFloat, binaryMinusInt, binaryMinusFloat};
        precedence = 140;
    } else if(opString == "=>") {
        TypeSpecification binaryBool = generateTypeSpecificationBinaryGenericUniform<bool>(DataType::BOOLEAN, implies<bool>);

        typeSpecs = {binaryBool};
        precedence = 131;
    } else if(opString == "==") {
        TypeSpecification binaryBool = generateTypeSpecificationBinaryGenericUniformSpecificReturn<bool, bool>(DataType::BOOLEAN, DataType::BOOLEAN, equal<bool>);
        TypeSpecification binaryInt = generateTypeSpecificationBinaryGenericUniformSpecificReturn<int, bool>(DataType::INT, DataType::BOOLEAN, equal<int>);
        TypeSpecification binaryFloat = generateTypeSpecificationBinaryGenericUniformSpecificReturn<float, bool>(DataType::FLOAT, DataType::BOOLEAN, equal<float>);

        typeSpecs = {binaryBool, binaryInt, binaryFloat};
        precedence = 130;
    } else if(opString == "!=") {
        TypeSpecification binaryBool = generateTypeSpecificationBinaryGenericUniformSpecificReturn<bool, bool>(DataType::BOOLEAN, DataType::BOOLEAN, notEqual<bool>);
        TypeSpecification binaryInt = generateTypeSpecificationBinaryGenericUniformSpecificReturn<int, bool>(DataType::INT, DataType::BOOLEAN, notEqual<int>);
        TypeSpecification binaryFloat = generateTypeSpecificationBinaryGenericUniformSpecificReturn<float, bool>(DataType::FLOAT, DataType::BOOLEAN, notEqual<float>);

        typeSpecs = {binaryBool, binaryInt, binaryFloat};
        precedence = 130;
    } else if(opString == "<=") {
        TypeSpecification binaryBool = generateTypeSpecificationBinaryGenericUniformSpecificReturn<bool, bool>(DataType::BOOLEAN, DataType::BOOLEAN, leq<bool>);
        TypeSpecification binaryInt = generateTypeSpecificationBinaryGenericUniformSpecificReturn<int, bool>(DataType::INT, DataType::BOOLEAN, leq<int>);
        TypeSpecification binaryFloat = generateTypeSpecificationBinaryGenericUniformSpecificReturn<float, bool>(DataType::FLOAT, DataType::BOOLEAN, leq<float>);

        typeSpecs = {binaryBool, binaryInt, binaryFloat};
        precedence = 130;
    } else if(opString == ">=") {
        TypeSpecification binaryBool = generateTypeSpecificationBinaryGenericUniformSpecificReturn<bool, bool>(DataType::BOOLEAN, DataType::BOOLEAN, geq<bool>);
        TypeSpecification binaryInt = generateTypeSpecificationBinaryGenericUniformSpecificReturn<int, bool>(DataType::INT, DataType::BOOLEAN, geq<int>);
        TypeSpecification binaryFloat = generateTypeSpecificationBinaryGenericUniformSpecificReturn<float, bool>(DataType::FLOAT, DataType::BOOLEAN, geq<float>);

        typeSpecs = {binaryBool, binaryInt, binaryFloat};
        precedence = 130;
    } else if(opString == "<") {
        TypeSpecification binaryBool = generateTypeSpecificationBinaryGenericUniformSpecificReturn<bool, bool>(DataType::BOOLEAN, DataType::BOOLEAN, lessThan<bool>);
        TypeSpecification binaryInt = generateTypeSpecificationBinaryGenericUniformSpecificReturn<int, bool>(DataType::INT, DataType::BOOLEAN, lessThan<int>);
        TypeSpecification binaryFloat = generateTypeSpecificationBinaryGenericUniformSpecificReturn<float, bool>(DataType::FLOAT, DataType::BOOLEAN, lessThan<float>);

        typeSpecs = {binaryBool, binaryInt, binaryFloat};
        precedence = 130;
    } else if(opString == ">") {
        TypeSpecification binaryBool = generateTypeSpecificationBinaryGenericUniformSpecificReturn<bool, bool>(DataType::BOOLEAN, DataType::BOOLEAN, greaterThan<bool>);
        TypeSpecification binaryInt = generateTypeSpecificationBinaryGenericUniformSpecificReturn<int, bool>(DataType::INT, DataType::BOOLEAN, greaterThan<int>);
        TypeSpecification binaryFloat = generateTypeSpecificationBinaryGenericUniformSpecificReturn<float, bool>(DataType::FLOAT, DataType::BOOLEAN, greaterThan<float>);

        typeSpecs = {binaryBool, binaryInt, binaryFloat};
        precedence = 130;
    } else if(opString == "&&") {
        TypeSpecification binaryBool = generateTypeSpecificationBinaryGenericUniform<bool>(DataType::BOOLEAN, _and<bool>);

        typeSpecs = {binaryBool};
        precedence = 120;
    } else if(opString == "||") {
        TypeSpecification binaryBool = generateTypeSpecificationBinaryGenericUniform<bool>(DataType::BOOLEAN, _or<bool>);

        typeSpecs = {binaryBool};
        precedence = 110;
    } else {
        throw "Unknown operator: " + opString;
    }

    opType.specifications = typeSpecs;
    opType.precedence = precedence;

    return opType;
}

OperatorType OperatorType::identity() {
    std::vector<TypeSpecification> specs;
    std::vector<lemonscript::DataType> types = {lemonscript::DataType::BOOLEAN, lemonscript::DataType::INT, lemonscript::DataType::FLOAT};
    for(auto it = types.begin(); it != types.end(); ++it) {
        lemonscript::DataType t = *it;
        TypeSpecification spec;
        spec.inputTypes = {t};
        spec.returnType = t;
        spec.func = [] (std::vector<int> xs) { return xs[0]; };
        specs.push_back(spec);
    }
    OperatorType opType;
    opType.isIdentityOperator = true;
    opType.specifications = specs;
    opType.operatorText = "i";
    opType.precedence = 999;

    return opType;
}
<|endoftext|>


<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/memory/lib/mss_utils.H $   */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2015,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* 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.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */

///
/// @file mss_utils.H
/// @brief Main include file for the Memory Subsystem
///
// *HWP HWP Owner: Craig Hamilton <cchamilt@us.ibm.com>
// *HWP HWP Backup: Brian Silver <bsilver@us.ibm.com>
// *HWP Team: Memory
// *HWP Level: 2
// *HWP Consumed by: HB:FSP

#ifndef _MSS_P9_ATTR_UTILS_H_
#define _MSS_P9_ATTR_UTILS_H_

#include "utils/index.H"
#include "utils/c_str.H"

#endif // _MSS_P9_ATTR_UTILS_H_
<commit_msg>Change include paths in memory/lib, tests<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/memory/lib/mss_utils.H $   */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2015,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* 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.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */

///
/// @file mss_utils.H
/// @brief Main include file for the Memory Subsystem
///
// *HWP HWP Owner: Craig Hamilton <cchamilt@us.ibm.com>
// *HWP HWP Backup: Brian Silver <bsilver@us.ibm.com>
// *HWP Team: Memory
// *HWP Level: 2
// *HWP Consumed by: HB:FSP

#ifndef _MSS_P9_ATTR_UTILS_H_
#define _MSS_P9_ATTR_UTILS_H_

//TK: what is this for? BRS

#include <lib/utils/index.H>
#include <lib/utils/c_str.H>

#endif // _MSS_P9_ATTR_UTILS_H_
<|endoftext|>