<commit_before>#include <sstream>
#include "event.h"

namespace OpenApoc {

Event::Event()
{
  Type = EVENT_UNDEFINED;
	Handled = false;
}

Event::Event(const UString &str)
	: Event()
{
	auto args = str.split(' ');
	if (args.size() < 2 || args[0] != "EVENT")
	{
		LogError("Invalid event string \"%s\"", str.str().c_str());
		return;
	}
	auto type = args[1].split('=');
	if (type.size() != 2)
	{
		LogError("Invalid event string \"%s\" - couldn't parse TYPE", str.str().c_str());
		return;
	}
	if (type[1] == "WINDOW_CLOSED") {
		this->Type = EVENT_WINDOW_CLOSED;
	} else if (type[1] == "KEY_DOWN") {
		this->Type = EVENT_KEY_DOWN;
	} else if (type[1] == "KEY_UP") {
		this->Type = EVENT_KEY_UP;
	} else if (type[1] == "KEY_PRESS") {
		this->Type = EVENT_KEY_PRESS;
	} else if (type[1] == "MOUSE_MOVE") {
		this->Type = EVENT_MOUSE_MOVE;
	} else if (type[1] == "MOUSE_DOWN") {
		this->Type = EVENT_MOUSE_DOWN;
	} else if (type[1] == "MOUSE_UP") {
		this->Type = EVENT_MOUSE_UP;
	} else if (type[1] == "WINDOW_RESIZE") {
		this->Type = EVENT_WINDOW_RESIZE;
	} else if (type[1] == "WINDOW_ACTIVATE") {
		this->Type = EVENT_WINDOW_ACTIVATE;
	} else if (type[1] == "WINDOW_DEACTIVATE") {
		this->Type = EVENT_WINDOW_DEACTIVATE;
	} else if (type[1] == "END_OF_FRAME") {
		this->Type = EVENT_END_OF_FRAME;
	} else {
		LogError("Invalid event string \"%s\" - unhandled TYPE", str.str().c_str());
		return;
	}

	for (size_t i = 2; i < args.size(); i++)
	{
		auto opts = args[i].split('=');
		if (opts.size() != 2)
		{
			LogError("Invalid event string \"%s\" - couldn't parse argument \"%s\"", str.str().c_str(), args[i].str().c_str());
			return;
		}
		if (!Strings::IsNumeric(opts[1]))
		{
			LogError("Invalid event string \"%s\" - couldn't parse option value \"%s\"", str.str().c_str(), args[i].str().c_str());
			return;
		}
		int value = Strings::ToInteger(opts[1]);
		if (opts[0] == "keycode") {
			if (this->Type != EVENT_KEY_DOWN && this->Type != EVENT_KEY_UP && this->Type != EVENT_KEY_PRESS)
			{
				LogError("Invalid event string \"%s\" - option \"%s\" not valid for type", str.str().c_str(), args[i].str().c_str());
				return;
			}
			this->Data.Keyboard.KeyCode = value;
		} else if (opts[0] == "unichar") {
			if (this->Type != EVENT_KEY_DOWN && this->Type != EVENT_KEY_UP && this->Type != EVENT_KEY_PRESS)
			{
				LogError("Invalid event string \"%s\" - option \"%s\" not valid for type", str.str().c_str(), args[i].str().c_str());
				return;
			}
			this->Data.Keyboard.UniChar = value;
		} else if (opts[0] == "modifiers") {
			if (this->Type != EVENT_KEY_DOWN && this->Type != EVENT_KEY_UP && this->Type != EVENT_KEY_PRESS)
			{
				LogError("Invalid event string \"%s\" - option \"%s\" not valid for type", str.str().c_str(), args[i].str().c_str());
				return;
			}
			this->Data.Keyboard.Modifiers = value;
		} else if (opts[0] == "x") {
			if (this->Type != EVENT_MOUSE_MOVE && this->Type != EVENT_MOUSE_UP && this->Type != EVENT_MOUSE_DOWN)
			{
				LogError("Invalid event string \"%s\" - option \"%s\" not valid for type", str.str().c_str(), args[i].str().c_str());
				return;
			}
			this->Data.Mouse.X = value;
		} else if (opts[0] == "y") {
			if (this->Type != EVENT_MOUSE_MOVE && this->Type != EVENT_MOUSE_UP && this->Type != EVENT_MOUSE_DOWN)
			{
				LogError("Invalid event string \"%s\" - option \"%s\" not valid for type", str.str().c_str(), args[i].str().c_str());
				return;
			}
			this->Data.Mouse.Y = value;
		} else if (opts[0] == "dx") {
			if (this->Type != EVENT_MOUSE_MOVE && this->Type != EVENT_MOUSE_UP && this->Type != EVENT_MOUSE_DOWN)
			{
				LogError("Invalid event string \"%s\" - option \"%s\" not valid for type", str.str().c_str(), args[i].str().c_str());
				return;
			}
			this->Data.Mouse.DeltaX = value;
		} else if (opts[0] == "dy") {
			if (this->Type != EVENT_MOUSE_MOVE && this->Type != EVENT_MOUSE_UP && this->Type != EVENT_MOUSE_DOWN)
			{
				LogError("Invalid event string \"%s\" - option \"%s\" not valid for type", str.str().c_str(), args[i].str().c_str());
				return;
			}
			this->Data.Mouse.DeltaY = value;
		} else if (opts[0] == "dv") {
			if (this->Type != EVENT_MOUSE_MOVE && this->Type != EVENT_MOUSE_UP && this->Type != EVENT_MOUSE_DOWN)
			{
				LogError("Invalid event string \"%s\" - option \"%s\" not valid for type", str.str().c_str(), args[i].str().c_str());
				return;
			}
			this->Data.Mouse.WheelVertical = value;
		} else if (opts[0] == "dw") {
			if (this->Type != EVENT_MOUSE_MOVE && this->Type != EVENT_MOUSE_UP && this->Type != EVENT_MOUSE_DOWN)
			{
				LogError("Invalid event string \"%s\" - option \"%s\" not valid for type", str.str().c_str(), args[i].str().c_str());
				return;
			}
			this->Data.Mouse.WheelHorizontal = value;
		} else if (opts[0] == "button") {
			if (this->Type != EVENT_MOUSE_MOVE && this->Type != EVENT_MOUSE_UP && this->Type != EVENT_MOUSE_DOWN)
			{
				LogError("Invalid event string \"%s\" - option \"%s\" not valid for type", str.str().c_str(), args[i].str().c_str());
				return;
			}
			this->Data.Mouse.Button = value;
		} else if (opts[0] == "w") {
			if (this->Type != EVENT_WINDOW_RESIZE)
			{
				LogError("Invalid event string \"%s\" - option \"%s\" not valid for type", str.str().c_str(), args[i].str().c_str());
				return;
			}
			this->Data.Display.Width = value;
		} else if (opts[0] == "h") {
			if (this->Type != EVENT_WINDOW_RESIZE)
			{
				LogError("Invalid event string \"%s\" - option \"%s\" not valid for type", str.str().c_str(), args[i].str().c_str());
				return;
			}
			this->Data.Display.Height = value;
		} else {
			LogError("Invalid event string \"%s\" - unhandled option \"%s\"", str.str().c_str(), args[i].str().c_str());
			return;
		}
	}

}

UString
Event::toString()
{
	std::stringstream ss;
	ss << std::dec;
	ss << "EVENT";
	switch (this->Type)
	{
		case EVENT_WINDOW_CLOSED:
			ss << " type=WINDOW_CLOSED";
			break;
		case EVENT_KEY_DOWN:
			ss << " type=KEY_DOWN";
			ss << " keycode=" << this->Data.Keyboard.KeyCode;
			ss << " unichar=" << this->Data.Keyboard.UniChar;
			ss << " modifiers=" << this->Data.Keyboard.Modifiers;
			break;
		case EVENT_KEY_UP:
			ss << " type=KEY_UP";
			ss << " keycode=" << this->Data.Keyboard.KeyCode;
			ss << " unichar=" << this->Data.Keyboard.UniChar;
			ss << " modifiers=" << this->Data.Keyboard.Modifiers;
			break;
		case EVENT_KEY_PRESS:
			ss << " type=KEY_PRESS";
			ss << " keycode=" << this->Data.Keyboard.KeyCode;
			ss << " unichar=" << this->Data.Keyboard.UniChar;
			ss << " modifiers=" << this->Data.Keyboard.Modifiers;
			break;
		case EVENT_MOUSE_MOVE:
			ss << " type=MOUSE_MOVE";
			ss << " x=" << this->Data.Mouse.X;
			ss << " y=" << this->Data.Mouse.Y;
			ss << " dx=" << this->Data.Mouse.DeltaX;
			ss << " dy=" << this->Data.Mouse.DeltaY;
			ss << " dv=" << this->Data.Mouse.WheelVertical;
			ss << " dw=" << this->Data.Mouse.WheelHorizontal;
			ss << " button=" << this->Data.Mouse.Button;
			break;
		case EVENT_MOUSE_DOWN:
			ss << " type=MOUSE_DOWN";
			ss << " x=" << this->Data.Mouse.X;
			ss << " y=" << this->Data.Mouse.Y;
			ss << " dx=" << this->Data.Mouse.DeltaX;
			ss << " dy=" << this->Data.Mouse.DeltaY;
			ss << " dv=" << this->Data.Mouse.WheelVertical;
			ss << " dw=" << this->Data.Mouse.WheelHorizontal;
			ss << " button=" << this->Data.Mouse.Button;
			break;
		case EVENT_MOUSE_UP:
			ss << " type=MOUSE_UP";
			ss << " x=" << this->Data.Mouse.X;
			ss << " y=" << this->Data.Mouse.Y;
			ss << " dx=" << this->Data.Mouse.DeltaX;
			ss << " dy=" << this->Data.Mouse.DeltaY;
			ss << " dv=" << this->Data.Mouse.WheelVertical;
			ss << " dw=" << this->Data.Mouse.WheelHorizontal;
			ss << " button=" << this->Data.Mouse.Button;
			break;
		case EVENT_WINDOW_RESIZE:
			ss << " type=WINDOW_RESIZE";
			ss << " w=" << this->Data.Display.Width;
			ss << " h=" << this->Data.Display.Height;
			break;
		case EVENT_WINDOW_ACTIVATE:
			ss << " type=WINDOW_ACTIVATE";
			break;
		case EVENT_WINDOW_DEACTIVATE:
			ss << " type=WINDOW_DEACTIVATE";
			break;
		case EVENT_END_OF_FRAME:
			ss << " type=END_OF_FRAME";
			break;
		default:
			LogError("Unhandled event type \"%d\"", this->Type);
			ss << " type=UNDEFINED";
			break;
	}
	return UString(ss.str());
}

Event::~Event()
{

}

}; //namespace OpenApoc
<commit_msg>Include build fix<commit_after>#include "framework/event.h"
#include "framework/logger.h"

#include <sstream>

namespace OpenApoc {

Event::Event()
{
  Type = EVENT_UNDEFINED;
	Handled = false;
}

Event::Event(const UString &str)
	: Event()
{
	auto args = str.split(' ');
	if (args.size() < 2 || args[0] != "EVENT")
	{
		LogError("Invalid event string \"%s\"", str.str().c_str());
		return;
	}
	auto type = args[1].split('=');
	if (type.size() != 2)
	{
		LogError("Invalid event string \"%s\" - couldn't parse TYPE", str.str().c_str());
		return;
	}
	if (type[1] == "WINDOW_CLOSED") {
		this->Type = EVENT_WINDOW_CLOSED;
	} else if (type[1] == "KEY_DOWN") {
		this->Type = EVENT_KEY_DOWN;
	} else if (type[1] == "KEY_UP") {
		this->Type = EVENT_KEY_UP;
	} else if (type[1] == "KEY_PRESS") {
		this->Type = EVENT_KEY_PRESS;
	} else if (type[1] == "MOUSE_MOVE") {
		this->Type = EVENT_MOUSE_MOVE;
	} else if (type[1] == "MOUSE_DOWN") {
		this->Type = EVENT_MOUSE_DOWN;
	} else if (type[1] == "MOUSE_UP") {
		this->Type = EVENT_MOUSE_UP;
	} else if (type[1] == "WINDOW_RESIZE") {
		this->Type = EVENT_WINDOW_RESIZE;
	} else if (type[1] == "WINDOW_ACTIVATE") {
		this->Type = EVENT_WINDOW_ACTIVATE;
	} else if (type[1] == "WINDOW_DEACTIVATE") {
		this->Type = EVENT_WINDOW_DEACTIVATE;
	} else if (type[1] == "END_OF_FRAME") {
		this->Type = EVENT_END_OF_FRAME;
	} else {
		LogError("Invalid event string \"%s\" - unhandled TYPE", str.str().c_str());
		return;
	}

	for (size_t i = 2; i < args.size(); i++)
	{
		auto opts = args[i].split('=');
		if (opts.size() != 2)
		{
			LogError("Invalid event string \"%s\" - couldn't parse argument \"%s\"", str.str().c_str(), args[i].str().c_str());
			return;
		}
		if (!Strings::IsNumeric(opts[1]))
		{
			LogError("Invalid event string \"%s\" - couldn't parse option value \"%s\"", str.str().c_str(), args[i].str().c_str());
			return;
		}
		int value = Strings::ToInteger(opts[1]);
		if (opts[0] == "keycode") {
			if (this->Type != EVENT_KEY_DOWN && this->Type != EVENT_KEY_UP && this->Type != EVENT_KEY_PRESS)
			{
				LogError("Invalid event string \"%s\" - option \"%s\" not valid for type", str.str().c_str(), args[i].str().c_str());
				return;
			}
			this->Data.Keyboard.KeyCode = value;
		} else if (opts[0] == "unichar") {
			if (this->Type != EVENT_KEY_DOWN && this->Type != EVENT_KEY_UP && this->Type != EVENT_KEY_PRESS)
			{
				LogError("Invalid event string \"%s\" - option \"%s\" not valid for type", str.str().c_str(), args[i].str().c_str());
				return;
			}
			this->Data.Keyboard.UniChar = value;
		} else if (opts[0] == "modifiers") {
			if (this->Type != EVENT_KEY_DOWN && this->Type != EVENT_KEY_UP && this->Type != EVENT_KEY_PRESS)
			{
				LogError("Invalid event string \"%s\" - option \"%s\" not valid for type", str.str().c_str(), args[i].str().c_str());
				return;
			}
			this->Data.Keyboard.Modifiers = value;
		} else if (opts[0] == "x") {
			if (this->Type != EVENT_MOUSE_MOVE && this->Type != EVENT_MOUSE_UP && this->Type != EVENT_MOUSE_DOWN)
			{
				LogError("Invalid event string \"%s\" - option \"%s\" not valid for type", str.str().c_str(), args[i].str().c_str());
				return;
			}
			this->Data.Mouse.X = value;
		} else if (opts[0] == "y") {
			if (this->Type != EVENT_MOUSE_MOVE && this->Type != EVENT_MOUSE_UP && this->Type != EVENT_MOUSE_DOWN)
			{
				LogError("Invalid event string \"%s\" - option \"%s\" not valid for type", str.str().c_str(), args[i].str().c_str());
				return;
			}
			this->Data.Mouse.Y = value;
		} else if (opts[0] == "dx") {
			if (this->Type != EVENT_MOUSE_MOVE && this->Type != EVENT_MOUSE_UP && this->Type != EVENT_MOUSE_DOWN)
			{
				LogError("Invalid event string \"%s\" - option \"%s\" not valid for type", str.str().c_str(), args[i].str().c_str());
				return;
			}
			this->Data.Mouse.DeltaX = value;
		} else if (opts[0] == "dy") {
			if (this->Type != EVENT_MOUSE_MOVE && this->Type != EVENT_MOUSE_UP && this->Type != EVENT_MOUSE_DOWN)
			{
				LogError("Invalid event string \"%s\" - option \"%s\" not valid for type", str.str().c_str(), args[i].str().c_str());
				return;
			}
			this->Data.Mouse.DeltaY = value;
		} else if (opts[0] == "dv") {
			if (this->Type != EVENT_MOUSE_MOVE && this->Type != EVENT_MOUSE_UP && this->Type != EVENT_MOUSE_DOWN)
			{
				LogError("Invalid event string \"%s\" - option \"%s\" not valid for type", str.str().c_str(), args[i].str().c_str());
				return;
			}
			this->Data.Mouse.WheelVertical = value;
		} else if (opts[0] == "dw") {
			if (this->Type != EVENT_MOUSE_MOVE && this->Type != EVENT_MOUSE_UP && this->Type != EVENT_MOUSE_DOWN)
			{
				LogError("Invalid event string \"%s\" - option \"%s\" not valid for type", str.str().c_str(), args[i].str().c_str());
				return;
			}
			this->Data.Mouse.WheelHorizontal = value;
		} else if (opts[0] == "button") {
			if (this->Type != EVENT_MOUSE_MOVE && this->Type != EVENT_MOUSE_UP && this->Type != EVENT_MOUSE_DOWN)
			{
				LogError("Invalid event string \"%s\" - option \"%s\" not valid for type", str.str().c_str(), args[i].str().c_str());
				return;
			}
			this->Data.Mouse.Button = value;
		} else if (opts[0] == "w") {
			if (this->Type != EVENT_WINDOW_RESIZE)
			{
				LogError("Invalid event string \"%s\" - option \"%s\" not valid for type", str.str().c_str(), args[i].str().c_str());
				return;
			}
			this->Data.Display.Width = value;
		} else if (opts[0] == "h") {
			if (this->Type != EVENT_WINDOW_RESIZE)
			{
				LogError("Invalid event string \"%s\" - option \"%s\" not valid for type", str.str().c_str(), args[i].str().c_str());
				return;
			}
			this->Data.Display.Height = value;
		} else {
			LogError("Invalid event string \"%s\" - unhandled option \"%s\"", str.str().c_str(), args[i].str().c_str());
			return;
		}
	}

}

UString
Event::toString()
{
	std::stringstream ss;
	ss << std::dec;
	ss << "EVENT";
	switch (this->Type)
	{
		case EVENT_WINDOW_CLOSED:
			ss << " type=WINDOW_CLOSED";
			break;
		case EVENT_KEY_DOWN:
			ss << " type=KEY_DOWN";
			ss << " keycode=" << this->Data.Keyboard.KeyCode;
			ss << " unichar=" << this->Data.Keyboard.UniChar;
			ss << " modifiers=" << this->Data.Keyboard.Modifiers;
			break;
		case EVENT_KEY_UP:
			ss << " type=KEY_UP";
			ss << " keycode=" << this->Data.Keyboard.KeyCode;
			ss << " unichar=" << this->Data.Keyboard.UniChar;
			ss << " modifiers=" << this->Data.Keyboard.Modifiers;
			break;
		case EVENT_KEY_PRESS:
			ss << " type=KEY_PRESS";
			ss << " keycode=" << this->Data.Keyboard.KeyCode;
			ss << " unichar=" << this->Data.Keyboard.UniChar;
			ss << " modifiers=" << this->Data.Keyboard.Modifiers;
			break;
		case EVENT_MOUSE_MOVE:
			ss << " type=MOUSE_MOVE";
			ss << " x=" << this->Data.Mouse.X;
			ss << " y=" << this->Data.Mouse.Y;
			ss << " dx=" << this->Data.Mouse.DeltaX;
			ss << " dy=" << this->Data.Mouse.DeltaY;
			ss << " dv=" << this->Data.Mouse.WheelVertical;
			ss << " dw=" << this->Data.Mouse.WheelHorizontal;
			ss << " button=" << this->Data.Mouse.Button;
			break;
		case EVENT_MOUSE_DOWN:
			ss << " type=MOUSE_DOWN";
			ss << " x=" << this->Data.Mouse.X;
			ss << " y=" << this->Data.Mouse.Y;
			ss << " dx=" << this->Data.Mouse.DeltaX;
			ss << " dy=" << this->Data.Mouse.DeltaY;
			ss << " dv=" << this->Data.Mouse.WheelVertical;
			ss << " dw=" << this->Data.Mouse.WheelHorizontal;
			ss << " button=" << this->Data.Mouse.Button;
			break;
		case EVENT_MOUSE_UP:
			ss << " type=MOUSE_UP";
			ss << " x=" << this->Data.Mouse.X;
			ss << " y=" << this->Data.Mouse.Y;
			ss << " dx=" << this->Data.Mouse.DeltaX;
			ss << " dy=" << this->Data.Mouse.DeltaY;
			ss << " dv=" << this->Data.Mouse.WheelVertical;
			ss << " dw=" << this->Data.Mouse.WheelHorizontal;
			ss << " button=" << this->Data.Mouse.Button;
			break;
		case EVENT_WINDOW_RESIZE:
			ss << " type=WINDOW_RESIZE";
			ss << " w=" << this->Data.Display.Width;
			ss << " h=" << this->Data.Display.Height;
			break;
		case EVENT_WINDOW_ACTIVATE:
			ss << " type=WINDOW_ACTIVATE";
			break;
		case EVENT_WINDOW_DEACTIVATE:
			ss << " type=WINDOW_DEACTIVATE";
			break;
		case EVENT_END_OF_FRAME:
			ss << " type=END_OF_FRAME";
			break;
		default:
			LogError("Unhandled event type \"%d\"", this->Type);
			ss << " type=UNDEFINED";
			break;
	}
	return UString(ss.str());
}

Event::~Event()
{

}

}; //namespace OpenApoc
<|endoftext|>


<commit_before>//===----------------------------------------------------------------------===//
//
//                         PelotonDB
//
// workload.cpp
//
// Identification: benchmark/tpcc/workload.cpp
//
// Copyright (c) 2015, Carnegie Mellon University Database Group
//
//===----------------------------------------------------------------------===//

#include <memory>
#include <string>
#include <unordered_map>
#include <vector>
#include <chrono>
#include <iostream>
#include <ctime>
#include <cassert>
#include <thread>
#include <algorithm>
#include <random>
#include <cstddef>
#include <limits>

#include "backend/benchmark/tpcc/tpcc_workload.h"
#include "backend/benchmark/tpcc/tpcc_configuration.h"
#include "backend/benchmark/tpcc/tpcc_loader.h"

#include "backend/catalog/manager.h"
#include "backend/catalog/schema.h"

#include "backend/common/types.h"
#include "backend/common/value.h"
#include "backend/common/value_factory.h"
#include "backend/common/logger.h"
#include "backend/common/timer.h"
#include "backend/common/generator.h"

#include "backend/concurrency/transaction.h"

#include "backend/executor/executor_context.h"
#include "backend/executor/abstract_executor.h"
#include "backend/executor/logical_tile.h"
#include "backend/executor/logical_tile_factory.h"
#include "backend/executor/materialization_executor.h"
#include "backend/executor/update_executor.h"
#include "backend/executor/index_scan_executor.h"

#include "backend/expression/abstract_expression.h"
#include "backend/expression/constant_value_expression.h"
#include "backend/expression/tuple_value_expression.h"
#include "backend/expression/comparison_expression.h"
#include "backend/expression/expression_util.h"

#include "backend/index/index_factory.h"

#include "backend/logging/log_manager.h"

#include "backend/planner/abstract_plan.h"
#include "backend/planner/materialization_plan.h"
#include "backend/planner/insert_plan.h"
#include "backend/planner/update_plan.h"
#include "backend/planner/index_scan_plan.h"

#include "backend/storage/data_table.h"
#include "backend/storage/table_factory.h"

namespace peloton {
namespace benchmark {
namespace tpcc {

/////////////////////////////////////////////////////////
// TRANSACTION TYPES
/////////////////////////////////////////////////////////

void RunStockLevel();

void RunDelivery();

void RunOrderStatus();

void RunPayment();

void RunNewOrder();

/////////////////////////////////////////////////////////
// WORKLOAD
/////////////////////////////////////////////////////////

std::vector<double> durations;

void RunBackend(oid_t thread_id) {
  auto txn_count = state.transaction_count;

  UniformGenerator generator;
  Timer<> timer;

  // Start timer
  timer.Reset();
  timer.Start();

  // Run these many transactions
  for (oid_t txn_itr = 0; txn_itr < txn_count; txn_itr++) {
    auto rng_val = generator.GetSample();

    if (rng_val <= 0.04) {
      RunStockLevel();
    } else if (rng_val <= 0.08) {
      RunDelivery();
    } else if (rng_val <= 0.12) {
      RunOrderStatus();
    } else if (rng_val <= 0.55) {
      RunPayment();
    } else {
      RunNewOrder();
    }

  }

  // Stop timer
  timer.Stop();

  // Set duration
  durations[thread_id] = timer.GetDuration();
}

double RunWorkload() {

  // Execute the workload to build the log
  std::vector<std::thread> thread_group;
  oid_t num_threads = state.backend_count;
  double max_duration = std::numeric_limits<double>::min();
  durations.reserve(num_threads);

  // Launch a group of threads
  for (oid_t thread_itr = 0; thread_itr < num_threads; ++thread_itr) {
    thread_group.push_back(std::thread(RunBackend, thread_itr));
  }

  // Join the threads with the main thread
  for (oid_t thread_itr = 0; thread_itr < num_threads; ++thread_itr) {
    thread_group[thread_itr].join();
  }

  // Compute max duration
  for (oid_t thread_itr = 0; thread_itr < num_threads; ++thread_itr) {
    max_duration = std::max(max_duration, durations[thread_itr]);
  }

  double throughput = (state.transaction_count * num_threads)/max_duration;

  return throughput;
}

/////////////////////////////////////////////////////////
// HARNESS
/////////////////////////////////////////////////////////

static void ExecuteTest(std::vector<executor::AbstractExecutor *> &executors) {
  time_point_ start, end;
  bool status = false;

  // Run all the executors
  for (auto executor : executors) {
    status = executor->Init();
    if (status == false) {
      throw Exception("Init failed");
    }

    std::vector<std::unique_ptr<executor::LogicalTile>> result_tiles;

    // Execute stuff
    while (executor->Execute() == true) {
      std::unique_ptr<executor::LogicalTile> result_tile(
          executor->GetOutput());
      result_tiles.emplace_back(result_tile.release());
    }
  }

}

/////////////////////////////////////////////////////////
// TRANSACTIONS
/////////////////////////////////////////////////////////

void RunStockLevel() {
  std::vector<executor::AbstractExecutor *> executors;
  ExecuteTest(executors);
}

void RunDelivery(){

}

void RunOrderStatus(){

}

void RunPayment(){

}

void RunNewOrder(){

}

}  // namespace tpcc
}  // namespace benchmark
}  // namespace peloton
<commit_msg>Added tpcc statements<commit_after>//===----------------------------------------------------------------------===//
//
//                         PelotonDB
//
// workload.cpp
//
// Identification: benchmark/tpcc/workload.cpp
//
// Copyright (c) 2015, Carnegie Mellon University Database Group
//
//===----------------------------------------------------------------------===//

#include <memory>
#include <string>
#include <unordered_map>
#include <vector>
#include <chrono>
#include <iostream>
#include <ctime>
#include <cassert>
#include <thread>
#include <algorithm>
#include <random>
#include <cstddef>
#include <limits>

#include "backend/benchmark/tpcc/tpcc_workload.h"
#include "backend/benchmark/tpcc/tpcc_configuration.h"
#include "backend/benchmark/tpcc/tpcc_loader.h"

#include "backend/catalog/manager.h"
#include "backend/catalog/schema.h"

#include "backend/common/types.h"
#include "backend/common/value.h"
#include "backend/common/value_factory.h"
#include "backend/common/logger.h"
#include "backend/common/timer.h"
#include "backend/common/generator.h"

#include "backend/concurrency/transaction.h"

#include "backend/executor/executor_context.h"
#include "backend/executor/abstract_executor.h"
#include "backend/executor/logical_tile.h"
#include "backend/executor/logical_tile_factory.h"
#include "backend/executor/materialization_executor.h"
#include "backend/executor/update_executor.h"
#include "backend/executor/index_scan_executor.h"

#include "backend/expression/abstract_expression.h"
#include "backend/expression/constant_value_expression.h"
#include "backend/expression/tuple_value_expression.h"
#include "backend/expression/comparison_expression.h"
#include "backend/expression/expression_util.h"

#include "backend/index/index_factory.h"

#include "backend/logging/log_manager.h"

#include "backend/planner/abstract_plan.h"
#include "backend/planner/materialization_plan.h"
#include "backend/planner/insert_plan.h"
#include "backend/planner/update_plan.h"
#include "backend/planner/index_scan_plan.h"

#include "backend/storage/data_table.h"
#include "backend/storage/table_factory.h"

namespace peloton {
namespace benchmark {
namespace tpcc {

/////////////////////////////////////////////////////////
// TRANSACTION TYPES
/////////////////////////////////////////////////////////

void RunStockLevel();

void RunDelivery();

void RunOrderStatus();

void RunPayment();

void RunNewOrder();

/////////////////////////////////////////////////////////
// WORKLOAD
/////////////////////////////////////////////////////////

std::vector<double> durations;

void RunBackend(oid_t thread_id) {
  auto txn_count = state.transaction_count;

  UniformGenerator generator;
  Timer<> timer;

  // Start timer
  timer.Reset();
  timer.Start();

  // Run these many transactions
  for (oid_t txn_itr = 0; txn_itr < txn_count; txn_itr++) {
    auto rng_val = generator.GetSample();

    if (rng_val <= 0.04) {
      RunStockLevel();
    } else if (rng_val <= 0.08) {
      RunDelivery();
    } else if (rng_val <= 0.12) {
      RunOrderStatus();
    } else if (rng_val <= 0.55) {
      RunPayment();
    } else {
      RunNewOrder();
    }

  }

  // Stop timer
  timer.Stop();

  // Set duration
  durations[thread_id] = timer.GetDuration();
}

double RunWorkload() {

  // Execute the workload to build the log
  std::vector<std::thread> thread_group;
  oid_t num_threads = state.backend_count;
  double max_duration = std::numeric_limits<double>::min();
  durations.reserve(num_threads);

  // Launch a group of threads
  for (oid_t thread_itr = 0; thread_itr < num_threads; ++thread_itr) {
    thread_group.push_back(std::thread(RunBackend, thread_itr));
  }

  // Join the threads with the main thread
  for (oid_t thread_itr = 0; thread_itr < num_threads; ++thread_itr) {
    thread_group[thread_itr].join();
  }

  // Compute max duration
  for (oid_t thread_itr = 0; thread_itr < num_threads; ++thread_itr) {
    max_duration = std::max(max_duration, durations[thread_itr]);
  }

  double throughput = (state.transaction_count * num_threads)/max_duration;

  return throughput;
}

/////////////////////////////////////////////////////////
// HARNESS
/////////////////////////////////////////////////////////

static void ExecuteTest(std::vector<executor::AbstractExecutor *> &executors) {
  time_point_ start, end;
  bool status = false;

  // Run all the executors
  for (auto executor : executors) {
    status = executor->Init();
    if (status == false) {
      throw Exception("Init failed");
    }

    std::vector<std::unique_ptr<executor::LogicalTile>> result_tiles;

    // Execute stuff
    while (executor->Execute() == true) {
      std::unique_ptr<executor::LogicalTile> result_tile(
          executor->GetOutput());
      result_tiles.emplace_back(result_tile.release());
    }
  }

}

/////////////////////////////////////////////////////////
// TRANSACTIONS
/////////////////////////////////////////////////////////

void RunNewOrder(){
  /*
     "NEW_ORDER": {
     "getWarehouseTaxRate": "SELECT W_TAX FROM WAREHOUSE WHERE W_ID = ?", # w_id
     "getDistrict": "SELECT D_TAX, D_NEXT_O_ID FROM DISTRICT WHERE D_ID = ? AND D_W_ID = ?", # d_id, w_id
     "getCustomer": "SELECT C_DISCOUNT, C_LAST, C_CREDIT FROM CUSTOMER WHERE C_W_ID = ? AND C_D_ID = ? AND C_ID = ?", # w_id, d_id, c_id
     "incrementNextOrderId": "UPDATE DISTRICT SET D_NEXT_O_ID = ? WHERE D_ID = ? AND D_W_ID = ?", # d_next_o_id, d_id, w_id
     "createOrder": "INSERT INTO ORDERS (O_ID, O_D_ID, O_W_ID, O_C_ID, O_ENTRY_D, O_CARRIER_ID, O_OL_CNT, O_ALL_LOCAL) VALUES (?, ?, ?, ?, ?, ?, ?, ?)", # d_next_o_id, d_id, w_id, c_id, o_entry_d, o_carrier_id, o_ol_cnt, o_all_local
     "createNewOrder": "INSERT INTO NEW_ORDER (NO_O_ID, NO_D_ID, NO_W_ID) VALUES (?, ?, ?)", # o_id, d_id, w_id
     "getItemInfo": "SELECT I_PRICE, I_NAME, I_DATA FROM ITEM WHERE I_ID = ?", # ol_i_id
     "getStockInfo": "SELECT S_QUANTITY, S_DATA, S_YTD, S_ORDER_CNT, S_REMOTE_CNT, S_DIST_%02d FROM STOCK WHERE S_I_ID = ? AND S_W_ID = ?", # d_id, ol_i_id, ol_supply_w_id
     "updateStock": "UPDATE STOCK SET S_QUANTITY = ?, S_YTD = ?, S_ORDER_CNT = ?, S_REMOTE_CNT = ? WHERE S_I_ID = ? AND S_W_ID = ?", # s_quantity, s_order_cnt, s_remote_cnt, ol_i_id, ol_supply_w_id
     "createOrderLine": "INSERT INTO ORDER_LINE (OL_O_ID, OL_D_ID, OL_W_ID, OL_NUMBER, OL_I_ID, OL_SUPPLY_W_ID, OL_DELIVERY_D, OL_QUANTITY, OL_AMOUNT, OL_DIST_INFO) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", # o_id, d_id, w_id, ol_number, ol_i_id, ol_supply_w_id, ol_quantity, ol_amount, ol_dist_info
     }
   */

}

void RunPayment(){
  /*
     "PAYMENT": {
     "getWarehouse": "SELECT W_NAME, W_STREET_1, W_STREET_2, W_CITY, W_STATE, W_ZIP FROM WAREHOUSE WHERE W_ID = ?", # w_id
     "updateWarehouseBalance": "UPDATE WAREHOUSE SET W_YTD = W_YTD + ? WHERE W_ID = ?", # h_amount, w_id
     "getDistrict": "SELECT D_NAME, D_STREET_1, D_STREET_2, D_CITY, D_STATE, D_ZIP FROM DISTRICT WHERE D_W_ID = ? AND D_ID = ?", # w_id, d_id
     "updateDistrictBalance": "UPDATE DISTRICT SET D_YTD = D_YTD + ? WHERE D_W_ID = ? AND D_ID = ?", # h_amount, d_w_id, d_id
     "getCustomerByCustomerId": "SELECT C_ID, C_FIRST, C_MIDDLE, C_LAST, C_STREET_1, C_STREET_2, C_CITY, C_STATE, C_ZIP, C_PHONE, C_SINCE, C_CREDIT, C_CREDIT_LIM, C_DISCOUNT, C_BALANCE, C_YTD_PAYMENT, C_PAYMENT_CNT, C_DATA FROM CUSTOMER WHERE C_W_ID = ? AND C_D_ID = ? AND C_ID = ?", # w_id, d_id, c_id
     "getCustomersByLastName": "SELECT C_ID, C_FIRST, C_MIDDLE, C_LAST, C_STREET_1, C_STREET_2, C_CITY, C_STATE, C_ZIP, C_PHONE, C_SINCE, C_CREDIT, C_CREDIT_LIM, C_DISCOUNT, C_BALANCE, C_YTD_PAYMENT, C_PAYMENT_CNT, C_DATA FROM CUSTOMER WHERE C_W_ID = ? AND C_D_ID = ? AND C_LAST = ? ORDER BY C_FIRST", # w_id, d_id, c_last
     "updateBCCustomer": "UPDATE CUSTOMER SET C_BALANCE = ?, C_YTD_PAYMENT = ?, C_PAYMENT_CNT = ?, C_DATA = ? WHERE C_W_ID = ? AND C_D_ID = ? AND C_ID = ?", # c_balance, c_ytd_payment, c_payment_cnt, c_data, c_w_id, c_d_id, c_id
     "updateGCCustomer": "UPDATE CUSTOMER SET C_BALANCE = ?, C_YTD_PAYMENT = ?, C_PAYMENT_CNT = ? WHERE C_W_ID = ? AND C_D_ID = ? AND C_ID = ?", # c_balance, c_ytd_payment, c_payment_cnt, c_w_id, c_d_id, c_id
     "insertHistory": "INSERT INTO HISTORY VALUES (?, ?, ?, ?, ?, ?, ?, ?)",
     }
   */

}

void RunOrderStatus(){
  /*
    "ORDER_STATUS": {
    "getCustomerByCustomerId": "SELECT C_ID, C_FIRST, C_MIDDLE, C_LAST, C_BALANCE FROM CUSTOMER WHERE C_W_ID = ? AND C_D_ID = ? AND C_ID = ?", # w_id, d_id, c_id
    "getCustomersByLastName": "SELECT C_ID, C_FIRST, C_MIDDLE, C_LAST, C_BALANCE FROM CUSTOMER WHERE C_W_ID = ? AND C_D_ID = ? AND C_LAST = ? ORDER BY C_FIRST", # w_id, d_id, c_last
    "getLastOrder": "SELECT O_ID, O_CARRIER_ID, O_ENTRY_D FROM ORDERS WHERE O_W_ID = ? AND O_D_ID = ? AND O_C_ID = ? ORDER BY O_ID DESC LIMIT 1", # w_id, d_id, c_id
    "getOrderLines": "SELECT OL_SUPPLY_W_ID, OL_I_ID, OL_QUANTITY, OL_AMOUNT, OL_DELIVERY_D FROM ORDER_LINE WHERE OL_W_ID = ? AND OL_D_ID = ? AND OL_O_ID = ?", # w_id, d_id, o_id
    }
   */

}

void RunDelivery(){
  /*
   "DELIVERY": {
   "getNewOrder": "SELECT NO_O_ID FROM NEW_ORDER WHERE NO_D_ID = ? AND NO_W_ID = ? AND NO_O_ID > -1 LIMIT 1", #
   "deleteNewOrder": "DELETE FROM NEW_ORDER WHERE NO_D_ID = ? AND NO_W_ID = ? AND NO_O_ID = ?", # d_id, w_id, no_o_id
   "getCId": "SELECT O_C_ID FROM ORDERS WHERE O_ID = ? AND O_D_ID = ? AND O_W_ID = ?", # no_o_id, d_id, w_id
   "updateOrders": "UPDATE ORDERS SET O_CARRIER_ID = ? WHERE O_ID = ? AND O_D_ID = ? AND O_W_ID = ?", # o_carrier_id, no_o_id, d_id, w_id
   "updateOrderLine": "UPDATE ORDER_LINE SET OL_DELIVERY_D = ? WHERE OL_O_ID = ? AND OL_D_ID = ? AND OL_W_ID = ?", # o_entry_d, no_o_id, d_id, w_id
   "sumOLAmount": "SELECT SUM(OL_AMOUNT) FROM ORDER_LINE WHERE OL_O_ID = ? AND OL_D_ID = ? AND OL_W_ID = ?", # no_o_id, d_id, w_id
   "updateCustomer": "UPDATE CUSTOMER SET C_BALANCE = C_BALANCE + ? WHERE C_ID = ? AND C_D_ID = ? AND C_W_ID = ?", # ol_total, c_id, d_id, w_id
   }
   */

}

void RunStockLevel() {
  /*
     "STOCK_LEVEL": {
     "getOId": "SELECT D_NEXT_O_ID FROM DISTRICT WHERE D_W_ID = ? AND D_ID = ?",
     "getStockCount": "SELECT COUNT(DISTINCT(OL_I_ID)) FROM ORDER_LINE, STOCK  WHERE OL_W_ID = ? AND OL_D_ID = ? AND OL_O_ID < ? AND OL_O_ID >= ? AND S_W_ID = ? AND S_I_ID = OL_I_ID AND S_QUANTITY < ?
     }
   */

  std::vector<executor::AbstractExecutor *> executors;
  ExecuteTest(executors);

}

}  // namespace tpcc
}  // namespace benchmark
}  // namespace peloton
<|endoftext|>


<commit_before>#include "backend/planner/aggregate_plan.h"
#include "backend/bridge/dml/expr/pg_func_map.h"
#include "backend/bridge/dml/mapper/mapper.h"
#include "backend/bridge/ddl/schema_transformer.h"
#include "executor/nodeAgg.h"

namespace peloton {
namespace bridge {

planner::AbstractPlan*
PlanTransformer::TransformAgg(const AggPlanState *plan_state) {

  // Alias all I need
  const Agg* agg = plan_state->agg_plan;
  auto numphases = plan_state->numphases;
  auto numaggs = plan_state->numaggs;
  auto targetlist = plan_state->ps_targetlist;
  auto qual = plan_state->ps_qual;
  auto peragg = plan_state->peragg;
  auto tupleDesc = plan_state->result_tupleDescriptor;
  auto aggstrategy = plan_state->agg_plan->aggstrategy;

  LOG_INFO("Number of Agg phases: %d \n", numphases);

  assert(1 == numphases);  // When we'll have >1 phases?

  /* Get project info */
  std::unique_ptr<const planner::ProjectInfo> proj_info(
      BuildProjectInfoFromTLSkipJunk(targetlist));
  LOG_INFO("proj_info : \n%s", proj_info->Debug().c_str());

  /* Get predicate */
  std::unique_ptr<const expression::AbstractExpression> predicate(
      BuildPredicateFromQual(qual));

  /* Get Aggregate terms */
  std::vector<planner::AggregatePlan::AggTerm> unique_agg_terms;

  LOG_INFO("Number of (unique) Agg nodes: %d \n", numaggs);
  for (int aggno = 0; aggno < numaggs; aggno++) {
    auto transfn_oid = peragg[aggno].transfn_oid;

    auto itr = peloton::bridge::kPgTransitFuncMap.find(transfn_oid);
    if (kPgFuncMap.end() == itr) {
      LOG_ERROR("Unmapped Transit function Id : %u\n", transfn_oid);
      return nullptr;
    }

    // We don't check whether the mapped exprtype is a valid aggregate type here.
    PltFuncMetaInfo fn_meta = itr->second;
    // We only take the first argument as input to aggregator because
    // we don't have multi-argument aggregator in Peloton at the moment.
    // WARNING: there can be no arguments (e.g., COUNT(*))
    auto arguments = peragg[aggno].aggrefstate->args;
    expression::AbstractExpression* agg_expr = nullptr;
    if (arguments) {
      GenericExprState *gstate = (GenericExprState *) lfirst(
          list_head(arguments));
      LOG_INFO("Creating Agg Expr");
      agg_expr = ExprTransformer::TransformExpr(gstate->arg);
      LOG_INFO("Done creating Agg Expr");
    }

    /*
     * AggStatePerAggData.sortColIdx along with other related attributes
     * are used to handle ORDER BY and DISTINCT *within* aggregation.
     * E.g.,
     * SELECT count(DISTINCT x) ...
     * SELECT str_agg(y ORDER BY x) ...
     * Currently, we only handle the agg(DISTINCT x) case by
     * checking whether numDistinctCols > 0.
     * Note that numDistinctCols > 0 may be a necessary but not sufficient
     * condition for agg(DISTINCT x).
     */

    bool distinct = (peragg[aggno].numDistinctCols > 0);

    unique_agg_terms.emplace_back(fn_meta.exprtype, agg_expr, distinct);

    LOG_INFO(
        "Unique Agg # : %d , transfn_oid : %u\n , aggtype = %s \n expr = %s, numDistinctCols = %d",
        aggno, transfn_oid, ExpressionTypeToString(fn_meta.exprtype).c_str(),
        agg_expr ? agg_expr->Debug().c_str() : "<NULL>",
        peragg[aggno].numDistinctCols);

    for (int i = 0; i < peragg[aggno].numDistinctCols; i++) {
      LOG_INFO("sortColIdx[%d] : %d \n", i, peragg[aggno].sortColIdx[i]);
    }

  }  // end loop aggno

  /* Get Group by columns */
  std::vector<oid_t> groupby_col_ids;
  LOG_INFO("agg.numCols = %d", agg->numCols);
  for (int i = 0; i < agg->numCols; i++) {
    LOG_INFO("agg.grpColIdx[%d] = %d \n", i, agg->grpColIdx[i]);

    auto attrno = agg->grpColIdx[i];
    if (AttributeNumberIsValid(attrno) && AttrNumberIsForUserDefinedAttr(attrno)) {
      groupby_col_ids.emplace_back(AttrNumberGetAttrOffset(attrno));
    }
  }

  /* Get output schema */
  std::unique_ptr<catalog::Schema> output_schema(
      SchemaTransformer::GetSchemaFromTupleDesc(tupleDesc));

  /* Map agg stragegy */
  LOG_INFO(
      "aggstrategy : %s\n",
      (AGG_HASHED == aggstrategy) ? "HASH" : (AGG_SORTED ? "SORT" : "PLAIN"));

  PelotonAggType agg_type = AGGREGATE_TYPE_INVALID;

  switch (aggstrategy) {
    case AGG_SORTED:
      agg_type = AGGREGATE_TYPE_SORTED;
      break;
    case AGG_HASHED:
      agg_type = AGGREGATE_TYPE_HASH;
      break;
    case AGG_PLAIN:
      agg_type = AGGREGATE_TYPE_PLAIN;
      break;
  }

  std::vector<oid_t> column_ids;
  for(auto agg_term : unique_agg_terms){
    LOG_INFO("AGG TERM :: %s", agg_term.expression->Debug().c_str());
    BuildColumnListFromExpr(column_ids, agg_term.expression);
  }

  auto retval = new planner::AggregatePlan(proj_info.release(),
                                           predicate.release(),
                                           std::move(unique_agg_terms),
                                           std::move(groupby_col_ids),
                                           output_schema.release(), agg_type);

  ((planner::AggregatePlan *)retval)->SetColumnIds(column_ids);

  // Find children
  auto lchild = TransformPlan(outerAbstractPlanState(plan_state));
  retval->AddChild(lchild);

  return retval;
}

}
}
<commit_msg>fix count(*) causes seg fault<commit_after>#include "backend/planner/aggregate_plan.h"
#include "backend/bridge/dml/expr/pg_func_map.h"
#include "backend/bridge/dml/mapper/mapper.h"
#include "backend/bridge/ddl/schema_transformer.h"
#include "executor/nodeAgg.h"

namespace peloton {
namespace bridge {

planner::AbstractPlan*
PlanTransformer::TransformAgg(const AggPlanState *plan_state) {

  // Alias all I need
  const Agg* agg = plan_state->agg_plan;
  auto numphases = plan_state->numphases;
  auto numaggs = plan_state->numaggs;
  auto targetlist = plan_state->ps_targetlist;
  auto qual = plan_state->ps_qual;
  auto peragg = plan_state->peragg;
  auto tupleDesc = plan_state->result_tupleDescriptor;
  auto aggstrategy = plan_state->agg_plan->aggstrategy;

  LOG_INFO("Number of Agg phases: %d \n", numphases);

  assert(1 == numphases);  // When we'll have >1 phases?

  /* Get project info */
  std::unique_ptr<const planner::ProjectInfo> proj_info(
      BuildProjectInfoFromTLSkipJunk(targetlist));
  LOG_INFO("proj_info : \n%s", proj_info->Debug().c_str());

  /* Get predicate */
  std::unique_ptr<const expression::AbstractExpression> predicate(
      BuildPredicateFromQual(qual));

  /* Get Aggregate terms */
  std::vector<planner::AggregatePlan::AggTerm> unique_agg_terms;

  LOG_INFO("Number of (unique) Agg nodes: %d \n", numaggs);
  for (int aggno = 0; aggno < numaggs; aggno++) {
    auto transfn_oid = peragg[aggno].transfn_oid;

    auto itr = peloton::bridge::kPgTransitFuncMap.find(transfn_oid);
    if (kPgFuncMap.end() == itr) {
      LOG_ERROR("Unmapped Transit function Id : %u\n", transfn_oid);
      return nullptr;
    }

    // We don't check whether the mapped exprtype is a valid aggregate type here.
    PltFuncMetaInfo fn_meta = itr->second;
    // We only take the first argument as input to aggregator because
    // we don't have multi-argument aggregator in Peloton at the moment.
    // WARNING: there can be no arguments (e.g., COUNT(*))
    auto arguments = peragg[aggno].aggrefstate->args;
    expression::AbstractExpression* agg_expr = nullptr;
    if (arguments) {
      GenericExprState *gstate = (GenericExprState *) lfirst(
          list_head(arguments));
      LOG_INFO("Creating Agg Expr");
      agg_expr = ExprTransformer::TransformExpr(gstate->arg);
      LOG_INFO("Done creating Agg Expr");
    }

    /*
     * AggStatePerAggData.sortColIdx along with other related attributes
     * are used to handle ORDER BY and DISTINCT *within* aggregation.
     * E.g.,
     * SELECT count(DISTINCT x) ...
     * SELECT str_agg(y ORDER BY x) ...
     * Currently, we only handle the agg(DISTINCT x) case by
     * checking whether numDistinctCols > 0.
     * Note that numDistinctCols > 0 may be a necessary but not sufficient
     * condition for agg(DISTINCT x).
     */

    bool distinct = (peragg[aggno].numDistinctCols > 0);

    unique_agg_terms.emplace_back(fn_meta.exprtype, agg_expr, distinct);

    LOG_INFO(
        "Unique Agg # : %d , transfn_oid : %u\n , aggtype = %s \n expr = %s, numDistinctCols = %d",
        aggno, transfn_oid, ExpressionTypeToString(fn_meta.exprtype).c_str(),
        agg_expr ? agg_expr->Debug().c_str() : "<NULL>",
        peragg[aggno].numDistinctCols);

    for (int i = 0; i < peragg[aggno].numDistinctCols; i++) {
      LOG_INFO("sortColIdx[%d] : %d \n", i, peragg[aggno].sortColIdx[i]);
    }

  }  // end loop aggno

  /* Get Group by columns */
  std::vector<oid_t> groupby_col_ids;
  LOG_INFO("agg.numCols = %d", agg->numCols);
  for (int i = 0; i < agg->numCols; i++) {
    LOG_INFO("agg.grpColIdx[%d] = %d \n", i, agg->grpColIdx[i]);

    auto attrno = agg->grpColIdx[i];
    if (AttributeNumberIsValid(attrno) && AttrNumberIsForUserDefinedAttr(attrno)) {
      groupby_col_ids.emplace_back(AttrNumberGetAttrOffset(attrno));
    }
  }

  /* Get output schema */
  std::unique_ptr<catalog::Schema> output_schema(
      SchemaTransformer::GetSchemaFromTupleDesc(tupleDesc));

  /* Map agg stragegy */
  LOG_INFO(
      "aggstrategy : %s\n",
      (AGG_HASHED == aggstrategy) ? "HASH" : (AGG_SORTED ? "SORT" : "PLAIN"));

  PelotonAggType agg_type = AGGREGATE_TYPE_INVALID;

  switch (aggstrategy) {
    case AGG_SORTED:
      agg_type = AGGREGATE_TYPE_SORTED;
      break;
    case AGG_HASHED:
      agg_type = AGGREGATE_TYPE_HASH;
      break;
    case AGG_PLAIN:
      agg_type = AGGREGATE_TYPE_PLAIN;
      break;
  }

  std::vector<oid_t> column_ids;
  for(auto agg_term : unique_agg_terms){
    if (agg_term.expression) {
      LOG_INFO("AGG TERM :: %s", agg_term.expression->Debug().c_str());
    }
    BuildColumnListFromExpr(column_ids, agg_term.expression);
  }

  auto retval = new planner::AggregatePlan(proj_info.release(),
                                           predicate.release(),
                                           std::move(unique_agg_terms),
                                           std::move(groupby_col_ids),
                                           output_schema.release(), agg_type);

  ((planner::AggregatePlan *)retval)->SetColumnIds(column_ids);

  // Find children
  auto lchild = TransformPlan(outerAbstractPlanState(plan_state));
  retval->AddChild(lchild);

  return retval;
}

}
}
<|endoftext|>


<commit_before>/*
 * Copyright 2014 Open Connectome Project (http://openconnecto.me)
 * Written by Da Zheng (zhengda1936@gmail.com)
 *
 * This file is part of FlashMatrix.
 *
 * 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 <string.h>
#include <assert.h>

#include <vector>
#include <string>

#include "log.h"
#include "FG_basic_types.h"
#include "vertex.h"
#include "graph_file_header.h"
#include "vertex_index.h"

#include "generic_type.h"
#include "data_io.h"
#include "data_frame.h"
#include "mem_data_frame.h"
#include "mem_vector.h"
#include "vector_vector.h"
#include "fm_utils.h"

using namespace fm;

/*
 * This class parses a line into an edge (source, destination).
 */
class edge_parser: public line_parser
{
public:
	size_t parse(const std::vector<std::string> &lines, data_frame &df) const;
	size_t get_num_cols() const {
		return 2;
	}

	std::string get_col_name(off_t idx) const {
		if (idx == 0)
			return "source";
		else
			return "dest";
	}

	const scalar_type &get_col_type(off_t idx) const {
		return get_scalar_type<fg::vertex_id_t>();
	}
};

size_t edge_parser::parse(const std::vector<std::string> &lines,
		data_frame &df) const
{
	type_mem_vector<fg::vertex_id_t>::ptr froms
		= type_mem_vector<fg::vertex_id_t>::create(lines.size());
	type_mem_vector<fg::vertex_id_t>::ptr tos
		= type_mem_vector<fg::vertex_id_t>::create(lines.size());
	for (size_t i = 0; i < lines.size(); i++) {
		const char *line = lines[i].c_str();
		int len = strlen(line);
		const char *first = line;
		// Skip space
		for (; isspace(*first); first++);
		// Make sure we get a number.
		if (!isdigit(*first)) {
			BOOST_LOG_TRIVIAL(error)
				<< std::string("the first entry isn't a number: ") + first;
			continue;
		}
		long from = atol(first);
		assert(from >= 0 && from < fg::MAX_VERTEX_ID);

		const char *second = first;
		// Go to the end of the first number.
		for (; isdigit(*second); second++);
		if (second - line == len) {
			BOOST_LOG_TRIVIAL(error)
				<< std::string("there isn't second entry: ") + line;
			continue;
		}
		// Skip space between two numbers.
		for (; isspace(*second); second++);
		// Make sure we get a number.
		if (!isdigit(*second)) {
			BOOST_LOG_TRIVIAL(error)
				<< std::string("the second entry isn't a number: ") + second;
			continue;
		}
		long to = atol(second);
		assert(to >= 0 && to < fg::MAX_VERTEX_ID);

		froms->set(i, from);
		tos->set(i, to);
	}

	df.get_vec(0)->append(*froms);
	df.get_vec(1)->append(*tos);
	return froms->get_length();
}

int main(int argc, char *argv[])
{
	if (argc < 3) {
		fprintf(stderr, "el2al edge_file graph_file\n");
		return -1;
	}

	std::string file_name = argv[1];
	std::string adj_file = std::string(argv[2]) + ".adj";
	std::string index_file = std::string(argv[2]) + ".index";
	std::vector<std::string> files;
	files.push_back(file_name);

	edge_parser parser;
	data_frame::ptr df = read_lines(files, parser);
	size_t num_edges = df->get_num_entries();
	printf("There are %ld edges\n", num_edges);
	fg::vertex_id_t max_vid = 0;
	for (size_t i = 0; i < df->get_num_vecs(); i++) {
		type_mem_vector<fg::vertex_id_t>::ptr vec
			= type_mem_vector<fg::vertex_id_t>::cast(df->get_vec(i));
		max_vid = std::max(max_vid, vec->max());
	}
	printf("max id: %d\n", max_vid);

	vector::ptr seq_vec = create_vector<fg::vertex_id_t>(0, max_vid, 1);
	vector::ptr rep_vec = create_vector<fg::vertex_id_t>(max_vid + 1,
			fg::INVALID_VERTEX_ID);
	assert(seq_vec->get_length() == rep_vec->get_length());
	// I artificially add an invalid out-edge for each vertex, so it's
	// guaranteed that each vertex exists in the adjacency lists.
	mem_data_frame::ptr new_df = mem_data_frame::create();
	new_df->add_vec(parser.get_col_name(0), seq_vec);
	new_df->add_vec(parser.get_col_name(1), rep_vec);
	df->append(new_df);

	// I artificially add an invalid in-edge for each vertex.
	new_df = mem_data_frame::create();
	new_df->add_vec(parser.get_col_name(1), seq_vec);
	new_df->add_vec(parser.get_col_name(0), rep_vec);
	df->append(new_df);

	// For in-edge adjacency lists, all edges share the same destination vertex
	// should be stored together.
	mem_data_frame::ptr tmp = mem_data_frame::create();
	tmp->add_vec("dest", df->get_vec("dest"));
	tmp->add_vec("source", df->get_vec("source"));
	df = tmp;
	vector_vector::ptr in_adjs = fm::create_1d_matrix(df);
	printf("There are %ld in-edge adjacency lists and they use %ld bytes in total\n",
			in_adjs->get_num_vecs(), in_adjs->get_tot_num_entries());

	// For out-edge adjacency lists, all edges share the same source vertex
	// should be stored together.
	tmp = mem_data_frame::create();
	tmp->add_vec("source", df->get_vec("source"));
	tmp->add_vec("dest", df->get_vec("dest"));
	df = tmp;
	vector_vector::ptr out_adjs = create_1d_matrix(df);
	printf("There are %ld out-edge adjacency lists and they use %ld bytes in total\n",
			out_adjs->get_num_vecs(), out_adjs->get_tot_num_entries());

	assert(out_adjs->get_num_vecs() == in_adjs->get_num_vecs());
	size_t num_vertices = out_adjs->get_num_vecs();
	type_mem_vector<fg::vsize_t>::ptr num_in_edges
		= type_mem_vector<fg::vsize_t>::create(num_vertices);
	type_mem_vector<fg::vsize_t>::ptr num_out_edges
		= type_mem_vector<fg::vsize_t>::create(num_vertices);
	for (size_t i = 0; i < num_vertices; i++) {
		num_in_edges->set(i, in_adjs->get_length(i));
		num_out_edges->set(i, out_adjs->get_length(i));
	}
	fg::graph_header header(fg::graph_type::DIRECTED, num_vertices, num_edges, 0);

	// Construct the vertex index.
	// The vectors that contains the numbers of edges have the length of #V + 1
	// because we add -1 to the edge lists artificially and the last entries
	// are the number of vertices.
	fg::cdirected_vertex_index::ptr vindex
		= fg::cdirected_vertex_index::construct(num_vertices,
				(const fg::vsize_t *) num_in_edges->get_raw_arr(),
				(const fg::vsize_t *) num_out_edges->get_raw_arr(),
				header);
	vindex->dump(index_file);

	// Construct the file for the adjacency list file.
	FILE *f_graph = fopen(adj_file.c_str(), "w");
	if (f_graph == NULL) {
		BOOST_LOG_TRIVIAL(error) << boost::format("open %1%: %2%")
			% adj_file % strerror(errno);
		return -1;
	}
	fwrite(&header, sizeof(header), 1, f_graph);
	bool ret = mem_vector::cast(in_adjs->cat())->export2(f_graph);
	assert(ret);
	ret = mem_vector::cast(out_adjs->cat())->export2(f_graph);
	assert(ret);
	fclose(f_graph);

	return 0;
}
<commit_msg>[Matrix]: fix a bug in el2al.<commit_after>/*
 * Copyright 2014 Open Connectome Project (http://openconnecto.me)
 * Written by Da Zheng (zhengda1936@gmail.com)
 *
 * This file is part of FlashMatrix.
 *
 * 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 <string.h>
#include <assert.h>

#include <vector>
#include <string>

#include "log.h"
#include "FG_basic_types.h"
#include "vertex.h"
#include "graph_file_header.h"
#include "vertex_index.h"

#include "generic_type.h"
#include "data_io.h"
#include "data_frame.h"
#include "mem_data_frame.h"
#include "mem_vector.h"
#include "vector_vector.h"
#include "fm_utils.h"

using namespace fm;

/*
 * This class parses a line into an edge (source, destination).
 */
class edge_parser: public line_parser
{
public:
	size_t parse(const std::vector<std::string> &lines, data_frame &df) const;
	size_t get_num_cols() const {
		return 2;
	}

	std::string get_col_name(off_t idx) const {
		if (idx == 0)
			return "source";
		else
			return "dest";
	}

	const scalar_type &get_col_type(off_t idx) const {
		return get_scalar_type<fg::vertex_id_t>();
	}
};

size_t edge_parser::parse(const std::vector<std::string> &lines,
		data_frame &df) const
{
	type_mem_vector<fg::vertex_id_t>::ptr froms
		= type_mem_vector<fg::vertex_id_t>::create(lines.size());
	type_mem_vector<fg::vertex_id_t>::ptr tos
		= type_mem_vector<fg::vertex_id_t>::create(lines.size());
	for (size_t i = 0; i < lines.size(); i++) {
		const char *line = lines[i].c_str();
		int len = strlen(line);
		const char *first = line;
		// Skip space
		for (; isspace(*first); first++);
		// Make sure we get a number.
		if (!isdigit(*first)) {
			BOOST_LOG_TRIVIAL(error)
				<< std::string("the first entry isn't a number: ") + first;
			continue;
		}
		long from = atol(first);
		assert(from >= 0 && from < fg::MAX_VERTEX_ID);

		const char *second = first;
		// Go to the end of the first number.
		for (; isdigit(*second); second++);
		if (second - line == len) {
			BOOST_LOG_TRIVIAL(error)
				<< std::string("there isn't second entry: ") + line;
			continue;
		}
		// Skip space between two numbers.
		for (; isspace(*second); second++);
		// Make sure we get a number.
		if (!isdigit(*second)) {
			BOOST_LOG_TRIVIAL(error)
				<< std::string("the second entry isn't a number: ") + second;
			continue;
		}
		long to = atol(second);
		assert(to >= 0 && to < fg::MAX_VERTEX_ID);

		froms->set(i, from);
		tos->set(i, to);
	}

	df.get_vec(0)->append(*froms);
	df.get_vec(1)->append(*tos);
	return froms->get_length();
}

int main(int argc, char *argv[])
{
	if (argc < 3) {
		fprintf(stderr, "el2al edge_file graph_file\n");
		return -1;
	}

	std::string file_name = argv[1];
	std::string adj_file = std::string(argv[2]) + ".adj";
	std::string index_file = std::string(argv[2]) + ".index";
	std::vector<std::string> files;
	files.push_back(file_name);

	edge_parser parser;
	data_frame::ptr df = read_lines(files, parser);
	size_t num_edges = df->get_num_entries();
	printf("There are %ld edges\n", num_edges);
	fg::vertex_id_t max_vid = 0;
	for (size_t i = 0; i < df->get_num_vecs(); i++) {
		type_mem_vector<fg::vertex_id_t>::ptr vec
			= type_mem_vector<fg::vertex_id_t>::cast(df->get_vec(i));
		max_vid = std::max(max_vid, vec->max());
	}
	printf("max id: %d\n", max_vid);

	vector::ptr seq_vec = create_vector<fg::vertex_id_t>(0, max_vid, 1);
	vector::ptr rep_vec = create_vector<fg::vertex_id_t>(max_vid + 1,
			fg::INVALID_VERTEX_ID);
	assert(seq_vec->get_length() == rep_vec->get_length());
	// I artificially add an invalid out-edge for each vertex, so it's
	// guaranteed that each vertex exists in the adjacency lists.
	mem_data_frame::ptr new_df = mem_data_frame::create();
	new_df->add_vec(parser.get_col_name(0), seq_vec);
	new_df->add_vec(parser.get_col_name(1), rep_vec);
	df->append(new_df);

	// I artificially add an invalid in-edge for each vertex.
	new_df = mem_data_frame::create();
	new_df->add_vec(parser.get_col_name(1), seq_vec);
	new_df->add_vec(parser.get_col_name(0), rep_vec);
	df->append(new_df);

	// For in-edge adjacency lists, all edges share the same destination vertex
	// should be stored together.
	mem_data_frame::ptr tmp = mem_data_frame::create();
	tmp->add_vec("dest", df->get_vec("dest"));
	tmp->add_vec("source", df->get_vec("source"));
	df = tmp;
	vector_vector::ptr in_adjs = fm::create_1d_matrix(df);
	printf("There are %ld in-edge adjacency lists and they use %ld bytes in total\n",
			in_adjs->get_num_vecs(), in_adjs->get_tot_num_entries());

	// For out-edge adjacency lists, all edges share the same source vertex
	// should be stored together.
	tmp = mem_data_frame::create();
	tmp->add_vec("source", df->get_vec("source"));
	tmp->add_vec("dest", df->get_vec("dest"));
	df = tmp;
	vector_vector::ptr out_adjs = create_1d_matrix(df);
	printf("There are %ld out-edge adjacency lists and they use %ld bytes in total\n",
			out_adjs->get_num_vecs(), out_adjs->get_tot_num_entries());

	assert(out_adjs->get_num_vecs() == in_adjs->get_num_vecs());
	size_t num_vertices = out_adjs->get_num_vecs();
	type_mem_vector<fg::vsize_t>::ptr num_in_edges
		= type_mem_vector<fg::vsize_t>::create(num_vertices);
	type_mem_vector<fg::vsize_t>::ptr num_out_edges
		= type_mem_vector<fg::vsize_t>::create(num_vertices);
	for (size_t i = 0; i < num_vertices; i++) {
		num_in_edges->set(i,
				fg::ext_mem_undirected_vertex::vsize2num_edges(
					in_adjs->get_length(i), 0));
		num_out_edges->set(i,
				fg::ext_mem_undirected_vertex::vsize2num_edges(
					out_adjs->get_length(i), 0));
	}
	fg::graph_header header(fg::graph_type::DIRECTED, num_vertices, num_edges, 0);

	// Construct the vertex index.
	// The vectors that contains the numbers of edges have the length of #V + 1
	// because we add -1 to the edge lists artificially and the last entries
	// are the number of vertices.
	fg::cdirected_vertex_index::ptr vindex
		= fg::cdirected_vertex_index::construct(num_vertices,
				(const fg::vsize_t *) num_in_edges->get_raw_arr(),
				(const fg::vsize_t *) num_out_edges->get_raw_arr(),
				header);
	vindex->dump(index_file);

	// Construct the file for the adjacency list file.
	FILE *f_graph = fopen(adj_file.c_str(), "w");
	if (f_graph == NULL) {
		BOOST_LOG_TRIVIAL(error) << boost::format("open %1%: %2%")
			% adj_file % strerror(errno);
		return -1;
	}
	fwrite(&header, sizeof(header), 1, f_graph);
	bool ret = mem_vector::cast(in_adjs->cat())->export2(f_graph);
	assert(ret);
	ret = mem_vector::cast(out_adjs->cat())->export2(f_graph);
	assert(ret);
	fclose(f_graph);

	return 0;
}
<|endoftext|>


<commit_before>///////////////////////////////////////////////////////////////////////////////
// The MIT License(MIT)
//
// Copyright (c) 2014 Tiangang Song
//
// 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.
/////////////////////////////////////////////////////////////////////////////////

#ifndef CLS_FACTORY_HPP
#define CLS_FACTORY_HPP

#include <vector>
#include <map>
#include <memory>
#include <functional>
#include "algorithm.hpp"
#include "cls_defs.h"

_CLS_BEGIN
namespace detail {
template<typename T, template<typename...> class Ptr = unique_ptr>
struct ObjCreator {
    template<typename... Args>
    Ptr<T> operator()(Args&&... args)
    {
        return Ptr<T>(new T(forward<Args>(args)...));
    };

    template<typename... Args>
    Ptr<T> create(Args&&... args)
    {
        return (*this)(forward<Args>(args)...);
    };
};

template<typename IDType>
class ObjFactoryBase {
public:
    virtual bool removeType(const IDType& ID) = 0;
};

template<typename BaseType, typename IDType, template<typename...> class Ptr, typename... CtorArgs>
class ObjFactory : public ObjFactoryBase<IDType> {
public:
    using BasePtr = Ptr<BaseType>;
    using Creator = function<BasePtr(CtorArgs...)>;

    bool addType(const IDType& ID, const Creator& creator)
    {
        if (creators_map.find(ID) == creators_map.end()) {
            creators_map.insert({ID, creator});
            return true;
        }

        return false;
    }

    template<typename Derived>
    bool addType(const IDType& ID)
    {
        return addType(ID, ObjCreator<Derived, Ptr>());
    }

    virtual bool removeType(const IDType& ID) override
    {
        if (creators_map.find(ID) != creators_map.end()) {
            creators_map.erase(ID);
            return true;
        }

        return false;
    }

    BasePtr create(const IDType& ID, CtorArgs&&... args) const
    {
        auto iter = creators_map.find(ID);
        if (iter != creators_map.end()) {
            return (iter->second)(forward<CtorArgs>(args)...);
        }

        return nullptr;
    }

    static ObjFactory& instance()
    {
        static ObjFactory obj_factory;
        return obj_factory;
    }

private:
    ObjFactory() = default;

    map<IDType, Creator> creators_map;
};
} // End namespace detail

///////////////////////////////////////////////////////////////////////////////////////////////////
template<typename Base, typename IDType = string, template<typename...> class Ptr = unique_ptr>
class Factory {
    using ObjFactoryBasePtr = detail::ObjFactoryBase<IDType>*;

    template<typename... CtorArgs>
    using ObjFactory = detail::ObjFactory<Base, IDType, Ptr, CtorArgs...>;

    template<typename... CtorArgs>
    using Creator = typename ObjFactory<CtorArgs...>::Creator;

public:
    template<typename Derived, typename... CtorArgs>
    static bool addType(const IDType& id)
    {
        auto& obj_factory = ObjFactory<CtorArgs...>::instance();
        auto success =  obj_factory.addType<Derived>(id);
        if (success) {
            instance().obj_factory_vec[id].emplace_back(&obj_factory);
        }

        return success;
    };

    template<typename Derived, typename... CtorArgs>
    static bool addType(const IDType& id, const Creator<CtorArgs...>& creator)
    {
        auto& obj_factory = ObjFactory<CtorArgs...>::instance();
        auto success =  obj_factory.addType(id, creator);
        if (success) {
            instance().obj_factory_vec[id].emplace_back(&obj_factory);
        }

        return success;
    };

    template<typename... CtorArgs>
    static Ptr<Base> create(const IDType& id, CtorArgs&&... args)
    {
        auto& obj_factory = ObjFactory<CtorArgs...>::instance();
        return obj_factory.create(id, forward<CtorArgs>(args)...);
    }

    static bool removeType(const IDType& ID)
    {
        bool success = true;
        auto& type_factories = instance().obj_factory_vec[ID];
        for_each(type_factories, [&ID, &success](ObjFactoryBasePtr iter) {
            success &= iter->removeType(ID);
        });

        return success;
    }

    static Factory& instance()
    {
        static Factory factory;
        return factory;
    }

private:
    map<IDType, vector<ObjFactoryBasePtr>> obj_factory_vec;
};

_CLS_END

///////////////////////////////////////////////////////////////////////////////////////////////////
// Use these macros in *.cpp file
#define REGISTER_TO_FACTORY(BaseType, DerivedType) \
namespace { \
    const bool ADD_##DerivedType = cls::Factory<BaseType>::addType<DerivedType>(#DerivedType); \
}

#endif // CLS_FACTORY_HPP<commit_msg>Use variadic macros in REGISTER_TO_FACTORY<commit_after>///////////////////////////////////////////////////////////////////////////////
// The MIT License(MIT)
//
// Copyright (c) 2014 Tiangang Song
//
// 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.
/////////////////////////////////////////////////////////////////////////////////

#ifndef CLS_FACTORY_HPP
#define CLS_FACTORY_HPP

#include <vector>
#include <map>
#include <memory>
#include <functional>
#include "algorithm.hpp"
#include "cls_defs.h"

_CLS_BEGIN
namespace detail {
template<typename T, template<typename...> class Ptr = unique_ptr>
struct ObjCreator {
    template<typename... Args>
    Ptr<T> operator()(Args&&... args)
    {
        return Ptr<T>(new T(forward<Args>(args)...));
    };

    template<typename... Args>
    Ptr<T> create(Args&&... args)
    {
        return (*this)(forward<Args>(args)...);
    };
};

template<typename IDType>
class ObjFactoryBase {
public:
    virtual bool removeType(const IDType& ID) = 0;
};

template<typename BaseType, typename IDType, template<typename...> class Ptr, typename... CtorArgs>
class ObjFactory : public ObjFactoryBase<IDType> {
public:
    using BasePtr = Ptr<BaseType>;
    using Creator = function<BasePtr(CtorArgs...)>;

    bool addType(const IDType& ID, const Creator& creator)
    {
        if (creators_map.find(ID) == creators_map.end()) {
            creators_map.insert({ID, creator});
            return true;
        }

        return false;
    }

    template<typename Derived>
    bool addType(const IDType& ID)
    {
        return addType(ID, ObjCreator<Derived, Ptr>());
    }

    virtual bool removeType(const IDType& ID) override
    {
        if (creators_map.find(ID) != creators_map.end()) {
            creators_map.erase(ID);
            return true;
        }

        return false;
    }

    BasePtr create(const IDType& ID, CtorArgs&&... args) const
    {
        auto iter = creators_map.find(ID);
        if (iter != creators_map.end()) {
            return (iter->second)(forward<CtorArgs>(args)...);
        }

        return nullptr;
    }

    static ObjFactory& instance()
    {
        static ObjFactory obj_factory;
        return obj_factory;
    }

private:
    ObjFactory() = default;

    map<IDType, Creator> creators_map;
};
} // End namespace detail

///////////////////////////////////////////////////////////////////////////////////////////////////
template<typename Base, typename IDType = string, template<typename...> class Ptr = unique_ptr>
class Factory {
    using ObjFactoryBasePtr = detail::ObjFactoryBase<IDType>*;

    template<typename... CtorArgs>
    using ObjFactory = detail::ObjFactory<Base, IDType, Ptr, CtorArgs...>;

    template<typename... CtorArgs>
    using Creator = typename ObjFactory<CtorArgs...>::Creator;

public:
    template<typename Derived, typename... CtorArgs>
    static bool addType(const IDType& id)
    {
        auto& obj_factory = ObjFactory<CtorArgs...>::instance();
        auto success =  obj_factory.addType<Derived>(id);
        if (success) {
            instance().obj_factory_vec[id].emplace_back(&obj_factory);
        }

        return success;
    };

    template<typename Derived, typename... CtorArgs>
    static bool addType(const IDType& id, const Creator<CtorArgs...>& creator)
    {
        auto& obj_factory = ObjFactory<CtorArgs...>::instance();
        auto success =  obj_factory.addType(id, creator);
        if (success) {
            instance().obj_factory_vec[id].emplace_back(&obj_factory);
        }

        return success;
    };

    template<typename... CtorArgs>
    static Ptr<Base> create(const IDType& id, CtorArgs&&... args)
    {
        auto& obj_factory = ObjFactory<CtorArgs...>::instance();
        return obj_factory.create(id, forward<CtorArgs>(args)...);
    }

    static bool removeType(const IDType& ID)
    {
        bool success = true;
        auto& type_factories = instance().obj_factory_vec[ID];
        for_each(type_factories, [&ID, &success](ObjFactoryBasePtr iter) {
            success &= iter->removeType(ID);
        });

        return success;
    }

    static Factory& instance()
    {
        static Factory factory;
        return factory;
    }

private:
    map<IDType, vector<ObjFactoryBasePtr>> obj_factory_vec;
};

_CLS_END

///////////////////////////////////////////////////////////////////////////////////////////////////
// Use these macros in *.cpp file
#define REGISTER_TO_FACTORY(BaseType, DerivedType, ...) \
namespace { \
    const bool ADD_##DerivedType = cls::Factory<BaseType>::addType<DerivedType, ##__VA_ARGS__>(#DerivedType); \
}

#endif // CLS_FACTORY_HPP<|endoftext|>


<commit_before>/*
 * Copyright 2015 Cloudius Systems
 */

#include "http/httpd.hh"
#include "http/handlers.hh"
#include "http/matcher.hh"
#include "http/matchrules.hh"
#include "json/formatter.hh"
#include "http/routes.hh"
#include "http/exception.hh"
#include "http/transformers.hh"
#include "tests/test-utils.hh"

using namespace httpd;

class handl : public httpd::handler_base {
public:
    virtual future<std::unique_ptr<reply> > handle(const sstring& path,
            std::unique_ptr<request> req, std::unique_ptr<reply> rep) {
        rep->done("html");
        return make_ready_future<std::unique_ptr<reply>>(std::move(rep));
    }
};

SEASTAR_TEST_CASE(test_reply)
{
    reply r;
    r.set_content_type("txt");
    BOOST_REQUIRE_EQUAL(r._headers["Content-Type"], sstring("text/plain"));
    return make_ready_future<>();
}

SEASTAR_TEST_CASE(test_str_matcher)
{

    str_matcher m("/hello");
    parameters param;
    BOOST_REQUIRE_EQUAL(m.match("/abc/hello", 4, param), 10);
    return make_ready_future<>();
}

SEASTAR_TEST_CASE(test_param_matcher)
{

    param_matcher m("param");
    parameters param;
    BOOST_REQUIRE_EQUAL(m.match("/abc/hello", 4, param), 10);
    BOOST_REQUIRE_EQUAL(param.path("param"), "/hello");
    BOOST_REQUIRE_EQUAL(param["param"], "hello");
    return make_ready_future<>();
}

SEASTAR_TEST_CASE(test_match_rule)
{

    parameters param;
    handl* h = new handl();
    match_rule mr(h);
    mr.add_str("/hello").add_param("param");
    httpd::handler_base* res = mr.get("/hello/val1", param);
    BOOST_REQUIRE_EQUAL(res, h);
    BOOST_REQUIRE_EQUAL(param["param"], "val1");
    res = mr.get("/hell/val1", param);
    httpd::handler_base* nl = nullptr;
    BOOST_REQUIRE_EQUAL(res, nl);
    return make_ready_future<>();
}

SEASTAR_TEST_CASE(test_formatter)
{
    BOOST_REQUIRE_EQUAL(json::formatter::to_json(true), "true");
    BOOST_REQUIRE_EQUAL(json::formatter::to_json(false), "false");
    BOOST_REQUIRE_EQUAL(json::formatter::to_json(1), "1");
    const char* txt = "efg";
    BOOST_REQUIRE_EQUAL(json::formatter::to_json(txt), "\"efg\"");
    sstring str = "abc";
    BOOST_REQUIRE_EQUAL(json::formatter::to_json(str), "\"abc\"");
    return make_ready_future<>();
}

SEASTAR_TEST_CASE(test_decode_url) {
    request req;
    req._url = "/a?q=%23%24%23";
    sstring url = http_server::connection::set_query_param(req);
    BOOST_REQUIRE_EQUAL(url, "/a");
    BOOST_REQUIRE_EQUAL(req.get_query_param("q"), "#$#");
    req._url = "/a?a=%23%24%23&b=%22%26%22";
    http_server::connection::set_query_param(req);
    BOOST_REQUIRE_EQUAL(req.get_query_param("a"), "#$#");
    BOOST_REQUIRE_EQUAL(req.get_query_param("b"), "\"&\"");
    return make_ready_future<>();
}

SEASTAR_TEST_CASE(test_routes) {
    handl* h1 = new handl();
    handl* h2 = new handl();
    routes route;
    route.add(operation_type::GET, url("/api").remainder("path"), h1);
    route.add(operation_type::GET, url("/"), h2);
    std::unique_ptr<request> req = std::make_unique<request>();
    std::unique_ptr<reply> rep = std::make_unique<reply>();

    BOOST_CHECK_NO_THROW(
            route.handle("/api", std::move(req), std::move(rep)).then(
                    [&rep](std::unique_ptr<reply> _rep) {
                        rep = std::move(_rep);
                    }));
    BOOST_REQUIRE_EQUAL((int )rep->_status, (int )reply::status_type::ok);
    req.reset(new request);
    rep.reset(new reply);

    BOOST_CHECK_NO_THROW(
            route.handle("/", std::move(req), std::move(rep)).then(
                    [&rep](std::unique_ptr<reply> _rep) {
                        rep = std::move(_rep);
                    }));
    BOOST_REQUIRE_EQUAL((int )rep->_status, (int )reply::status_type::ok);
    req.reset(new request);
    rep.reset(new reply);
    BOOST_CHECK_NO_THROW(
            route.handle("/api/abc", std::move(req), std::move(rep)).then(
                    [&rep](std::unique_ptr<reply> _rep) {
                        rep = std::move(_rep);
                    }));
    req.reset(new request);
    rep.reset(new reply);
    BOOST_CHECK_NO_THROW(
            route.handle("/ap", std::move(req), std::move(rep)).then(
                    [&rep](std::unique_ptr<reply> _rep) {
                        rep = std::move(_rep);
                    }));
    BOOST_REQUIRE_EQUAL((int )rep->_status,
            (int )reply::status_type::not_found);

    return make_ready_future<>();
}

SEASTAR_TEST_CASE(test_transformer) {
    request req;
    content_replace cr("json");
    sstring content = "hello-{{Protocol}}-xyz-{{Host}}";
    cr.transform(content, req, "html");
    BOOST_REQUIRE_EQUAL(content, "hello-{{Protocol}}-xyz-{{Host}}");
    req._headers["Host"] = "localhost";
    cr.transform(content, req, "json");
    BOOST_REQUIRE_EQUAL(content, "hello-http-xyz-localhost");
    return make_ready_future<>();
}
<commit_msg>tests: make httpd test wait for continuations to execute<commit_after>/*
 * Copyright 2015 Cloudius Systems
 */

#include "http/httpd.hh"
#include "http/handlers.hh"
#include "http/matcher.hh"
#include "http/matchrules.hh"
#include "json/formatter.hh"
#include "http/routes.hh"
#include "http/exception.hh"
#include "http/transformers.hh"
#include "core/future-util.hh"
#include "tests/test-utils.hh"

using namespace httpd;

class handl : public httpd::handler_base {
public:
    virtual future<std::unique_ptr<reply> > handle(const sstring& path,
            std::unique_ptr<request> req, std::unique_ptr<reply> rep) {
        rep->done("html");
        return make_ready_future<std::unique_ptr<reply>>(std::move(rep));
    }
};

SEASTAR_TEST_CASE(test_reply)
{
    reply r;
    r.set_content_type("txt");
    BOOST_REQUIRE_EQUAL(r._headers["Content-Type"], sstring("text/plain"));
    return make_ready_future<>();
}

SEASTAR_TEST_CASE(test_str_matcher)
{

    str_matcher m("/hello");
    parameters param;
    BOOST_REQUIRE_EQUAL(m.match("/abc/hello", 4, param), 10);
    return make_ready_future<>();
}

SEASTAR_TEST_CASE(test_param_matcher)
{

    param_matcher m("param");
    parameters param;
    BOOST_REQUIRE_EQUAL(m.match("/abc/hello", 4, param), 10);
    BOOST_REQUIRE_EQUAL(param.path("param"), "/hello");
    BOOST_REQUIRE_EQUAL(param["param"], "hello");
    return make_ready_future<>();
}

SEASTAR_TEST_CASE(test_match_rule)
{

    parameters param;
    handl* h = new handl();
    match_rule mr(h);
    mr.add_str("/hello").add_param("param");
    httpd::handler_base* res = mr.get("/hello/val1", param);
    BOOST_REQUIRE_EQUAL(res, h);
    BOOST_REQUIRE_EQUAL(param["param"], "val1");
    res = mr.get("/hell/val1", param);
    httpd::handler_base* nl = nullptr;
    BOOST_REQUIRE_EQUAL(res, nl);
    return make_ready_future<>();
}

SEASTAR_TEST_CASE(test_formatter)
{
    BOOST_REQUIRE_EQUAL(json::formatter::to_json(true), "true");
    BOOST_REQUIRE_EQUAL(json::formatter::to_json(false), "false");
    BOOST_REQUIRE_EQUAL(json::formatter::to_json(1), "1");
    const char* txt = "efg";
    BOOST_REQUIRE_EQUAL(json::formatter::to_json(txt), "\"efg\"");
    sstring str = "abc";
    BOOST_REQUIRE_EQUAL(json::formatter::to_json(str), "\"abc\"");
    return make_ready_future<>();
}

SEASTAR_TEST_CASE(test_decode_url) {
    request req;
    req._url = "/a?q=%23%24%23";
    sstring url = http_server::connection::set_query_param(req);
    BOOST_REQUIRE_EQUAL(url, "/a");
    BOOST_REQUIRE_EQUAL(req.get_query_param("q"), "#$#");
    req._url = "/a?a=%23%24%23&b=%22%26%22";
    http_server::connection::set_query_param(req);
    BOOST_REQUIRE_EQUAL(req.get_query_param("a"), "#$#");
    BOOST_REQUIRE_EQUAL(req.get_query_param("b"), "\"&\"");
    return make_ready_future<>();
}

SEASTAR_TEST_CASE(test_routes) {
    handl* h1 = new handl();
    handl* h2 = new handl();
    routes route;
    route.add(operation_type::GET, url("/api").remainder("path"), h1);
    route.add(operation_type::GET, url("/"), h2);
    std::unique_ptr<request> req = std::make_unique<request>();
    std::unique_ptr<reply> rep = std::make_unique<reply>();

    auto f1 =
            route.handle("/api", std::move(req), std::move(rep)).then(
                    [] (std::unique_ptr<reply> rep) {
                        BOOST_REQUIRE_EQUAL((int )rep->_status, (int )reply::status_type::ok);
                    });
    req.reset(new request);
    rep.reset(new reply);

    auto f2 =
            route.handle("/", std::move(req), std::move(rep)).then(
                    [] (std::unique_ptr<reply> rep) {
                        BOOST_REQUIRE_EQUAL((int )rep->_status, (int )reply::status_type::ok);
                    });
    req.reset(new request);
    rep.reset(new reply);
    auto f3 =
            route.handle("/api/abc", std::move(req), std::move(rep)).then(
                    [] (std::unique_ptr<reply> rep) {
                    });
    req.reset(new request);
    rep.reset(new reply);
    auto f4 =
            route.handle("/ap", std::move(req), std::move(rep)).then(
                    [] (std::unique_ptr<reply> rep) {
                        BOOST_REQUIRE_EQUAL((int )rep->_status,
                                            (int )reply::status_type::not_found);
                    });
    return when_all(std::move(f1), std::move(f2), std::move(f3), std::move(f4))
            .then([] (std::tuple<future<>, future<>, future<>, future<>> fs) {
        std::get<0>(fs).get();
        std::get<1>(fs).get();
        std::get<2>(fs).get();
        std::get<3>(fs).get();
    });
}

SEASTAR_TEST_CASE(test_transformer) {
    request req;
    content_replace cr("json");
    sstring content = "hello-{{Protocol}}-xyz-{{Host}}";
    cr.transform(content, req, "html");
    BOOST_REQUIRE_EQUAL(content, "hello-{{Protocol}}-xyz-{{Host}}");
    req._headers["Host"] = "localhost";
    cr.transform(content, req, "json");
    BOOST_REQUIRE_EQUAL(content, "hello-http-xyz-localhost");
    return make_ready_future<>();
}
<|endoftext|>


<commit_before>#pragma once

#include "conv2d.hpp"
#include "corr2d.hpp"

namespace ncv
{
        namespace tensor
        {
                ///
                /// \brief 3D convolution output: odata(o) = sum(i, idata(i) @ kdata(i, o))
                ///
                template
                <
                        typename ttensor,
                        typename tsize = typename ttensor::Index,
                        typename tscalar = typename ttensor::Scalar
                >
                class conv3d_t
                {
                public:

                        ///
                        /// \brief constructor
                        ///
                        conv3d_t()
                                :       m_idims(0),
                                        m_odims(0)
                        {
                        }

                        ///
                        /// \brief change convolutions
                        ///
                        bool reset(const ttensor& kdata_io, const tsize idims, const tsize odims);

                        ///
                        /// \brief output
                        ///
                        template
                        <
                                typename ttensori,
                                typename ttensoro
                        >
                        bool output(const ttensori& idata, ttensoro&& odata) const;

                        ///
                        /// \brief gradient wrt the input
                        ///
                        template
                        <
                                typename ttensori,
                                typename ttensoro
                        >
                        bool ginput(ttensori&& idata, const ttensoro& odata) const;

                        ///
                        /// \brief gradient wrt the parameters
                        ///
                        template
                        <
                                typename ttensori,
                                typename ttensork,
                                typename ttensoro
                        >
                        bool gparam(const ttensori& idata, ttensork&& kdata, const ttensoro& odata) const;

                        const ttensor& kdata() const
                        {
                                return m_kdata_io;
                        }

                private:

                        // attributes
                        ttensor         m_kdata_io;     ///< convolutions organized as (input i, output o)
                        ttensor         m_kdata_oi;     ///< convolutions organized as (output o, input i)
                        tsize           m_idims;
                        tsize           m_odims;
                };

                template
                <
                        typename ttensor,
                        typename tsize,
                        typename tscalar
                >
                bool conv3d_t<ttensor, tsize, tscalar>::reset(
                        const ttensor& kdata_io, const tsize idims, const tsize odims)
                {
                        if (idims * odims != kdata_io.dims())
                        {
                                return false;
                        }

                        else
                        {
                                m_idims = idims;
                                m_odims = odims;

                                m_kdata_io = kdata_io;
                                m_kdata_oi = kdata_io;

                                for (tsize o = 0; o < m_odims; o ++)
                                {
                                        for (tsize i = 0; i < m_idims; i ++)
                                        {
                                                m_kdata_oi.vector(o * m_idims + i) =
                                                m_kdata_io.vector(i * m_odims + o);
                                        }
                                }

                                return true;
                        }
                }

                template
                <
                        typename ttensor,
                        typename tsize,
                        typename tscalar
                >
                template
                <
                        typename ttensori,
                        typename ttensoro
                >
                bool conv3d_t<ttensor, tsize, tscalar>::output(const ttensori& idata, ttensoro&& odata) const
                {
                        if (    idata.dims() != m_idims ||
                                odata.dims() != m_odims)
                        {
                                return false;
                        }

                        const auto& kdata = m_kdata_oi;

                        const auto osize = odata.planeSize();
                        const auto ksize = kdata.planeSize();

                        typedef typename tensor::matrix_types_t<tscalar>::tmatrix tmatrix;

                        tmatrix idata_lin(m_idims * ksize, osize);

                        conv2d_linearizer_t<tscalar> conv2dlin;
                        for (tsize i = 0; i < m_idims; i ++)
                        {
                                idata_lin.block(i * ksize, 0, ksize, osize) =
                                conv2dlin(idata.matrix(i), kdata);
                        }

                        tensor::map_matrix(odata.data(), m_odims, osize) =
                        tensor::map_matrix(kdata.data(), m_odims, m_idims * ksize) *
                        idata_lin;

                        return true;
                }

                template
                <
                        typename ttensor,
                        typename tsize,
                        typename tscalar
                >
                template
                <
                        typename ttensori,
                        typename ttensoro
                >
                bool conv3d_t<ttensor, tsize, tscalar>::ginput(
                        ttensori&& idata, const ttensoro& odata) const
                {
                        if (    idata.dims() != m_idims ||
                                odata.dims() != m_odims)
                        {
                                return false;
                        }

                        const auto& kdata = m_kdata_oi;

                        const auto isize = idata.planeSize();
                        const auto ksize = kdata.planeSize();

//                        typedef typename tensor::matrix_types_t<tscalar>::tmatrix tmatrix;

//                        tmatrix odata_lin(m_odims * ksize, isize);

//                        corr2d_linearizer_t<tscalar> corr2lin;
//                        for (tsize o = 0; o < m_odims; o ++)
//                        {
//                                odata_lin.block(o * ksize, 0, ksize, isize) =
//                                corr2lin(odata.matrix(o), kdata);
//                        }

//                        tensor::map_matrix(idata.data(), m_idims, isize) =
//                        tensor::map_matrix(kdata.data(), m_idims, m_odims * ksize) *
//                        odata_lin;

                        idata.setZero();

                        corr2d_linearizer_t<tscalar> corr2lin;
                        for (tsize o = 0; o < m_odims; o ++)
                        {
                                corr2lin(odata.matrix(o), kdata);

                                for (tsize i = 0; i < m_idims; i ++)
                                {
                                        tensor::map_vector(idata.planeData(i), isize) +=
                                        corr2lin.m_transf.transpose() *
                                        tensor::map_vector(kdata.planeData(o * m_idims + i), ksize);
                                }
                        }

                        return true;
                }

                template
                <
                        typename ttensor,
                        typename tsize,
                        typename tscalar
                >
                template
                <
                        typename ttensori,
                        typename ttensork,
                        typename ttensoro
                >
                bool conv3d_t<ttensor, tsize, tscalar>::gparam(
                        const ttensori& idata, ttensork&& kdata, const ttensoro& odata) const
                {
                        if (    idata.dims() != m_idims ||
                                odata.dims() != m_odims ||
                                kdata.dims() != m_idims * m_odims)
                        {
                                return false;
                        }

                        const auto osize = odata.planeSize();
                        const auto ksize = kdata.planeSize();

                        conv2d_linearizer_t<tscalar> conv2dlin;

                        for (tsize i = 0; i < m_idims; i ++)
                        {
                                tensor::map_matrix(kdata.planeData(i * m_odims), m_odims, ksize) =
                                tensor::map_matrix(odata.data(), m_odims, osize) *
                                conv2dlin(idata.matrix(i), odata);
                        }

                        return true;
                }
        }
}

<commit_msg>3D correlation using a single matrix multiplication<commit_after>#pragma once

#include "conv2d.hpp"
#include "corr2d.hpp"

namespace ncv
{
        namespace tensor
        {
                ///
                /// \brief 3D convolution output: odata(o) = sum(i, idata(i) @ kdata(i, o))
                ///
                template
                <
                        typename ttensor,
                        typename tsize = typename ttensor::Index,
                        typename tscalar = typename ttensor::Scalar
                >
                class conv3d_t
                {
                public:

                        ///
                        /// \brief constructor
                        ///
                        conv3d_t()
                                :       m_idims(0),
                                        m_odims(0)
                        {
                        }

                        ///
                        /// \brief change convolutions
                        ///
                        bool reset(const ttensor& kdata_io, const tsize idims, const tsize odims);

                        ///
                        /// \brief output
                        ///
                        template
                        <
                                typename ttensori,
                                typename ttensoro
                        >
                        bool output(const ttensori& idata, ttensoro&& odata) const;

                        ///
                        /// \brief gradient wrt the input
                        ///
                        template
                        <
                                typename ttensori,
                                typename ttensoro
                        >
                        bool ginput(ttensori&& idata, const ttensoro& odata) const;

                        ///
                        /// \brief gradient wrt the parameters
                        ///
                        template
                        <
                                typename ttensori,
                                typename ttensork,
                                typename ttensoro
                        >
                        bool gparam(const ttensori& idata, ttensork&& kdata, const ttensoro& odata) const;

                        const ttensor& kdata() const
                        {
                                return m_kdata_io;
                        }

                private:

                        // attributes
                        ttensor         m_kdata_io;     ///< convolutions organized as (input i, output o)
                        ttensor         m_kdata_oi;     ///< convolutions organized as (output o, input i)
                        tsize           m_idims;
                        tsize           m_odims;
                };

                template
                <
                        typename ttensor,
                        typename tsize,
                        typename tscalar
                >
                bool conv3d_t<ttensor, tsize, tscalar>::reset(
                        const ttensor& kdata_io, const tsize idims, const tsize odims)
                {
                        if (idims * odims != kdata_io.dims())
                        {
                                return false;
                        }

                        else
                        {
                                m_idims = idims;
                                m_odims = odims;

                                m_kdata_io = kdata_io;
                                m_kdata_oi = kdata_io;

                                for (tsize o = 0; o < m_odims; o ++)
                                {
                                        for (tsize i = 0; i < m_idims; i ++)
                                        {
                                                m_kdata_oi.vector(o * m_idims + i) =
                                                m_kdata_io.vector(i * m_odims + o);
                                        }
                                }

                                return true;
                        }
                }

                template
                <
                        typename ttensor,
                        typename tsize,
                        typename tscalar
                >
                template
                <
                        typename ttensori,
                        typename ttensoro
                >
                bool conv3d_t<ttensor, tsize, tscalar>::output(const ttensori& idata, ttensoro&& odata) const
                {
                        if (    idata.dims() != m_idims ||
                                odata.dims() != m_odims)
                        {
                                return false;
                        }

                        const auto& kdata = m_kdata_oi;

                        const auto osize = odata.planeSize();
                        const auto ksize = kdata.planeSize();

                        typedef typename tensor::matrix_types_t<tscalar>::tmatrix tmatrix;

                        tmatrix idata_lin(m_idims * ksize, osize);

                        conv2d_linearizer_t<tscalar> conv2dlin;
                        for (tsize i = 0; i < m_idims; i ++)
                        {
                                idata_lin.block(i * ksize, 0, ksize, osize) =
                                conv2dlin(idata.matrix(i), kdata);
                        }

                        tensor::map_matrix(odata.data(), m_odims, osize) =
                        tensor::map_matrix(kdata.data(), m_odims, m_idims * ksize) *
                        idata_lin;

                        return true;
                }

                template
                <
                        typename ttensor,
                        typename tsize,
                        typename tscalar
                >
                template
                <
                        typename ttensori,
                        typename ttensoro
                >
                bool conv3d_t<ttensor, tsize, tscalar>::ginput(
                        ttensori&& idata, const ttensoro& odata) const
                {
                        if (    idata.dims() != m_idims ||
                                odata.dims() != m_odims)
                        {
                                return false;
                        }

                        const auto& kdata = m_kdata_io;

                        const auto isize = idata.planeSize();
                        const auto ksize = kdata.planeSize();

                        typedef typename tensor::matrix_types_t<tscalar>::tmatrix tmatrix;

                        tmatrix odata_lin(m_odims * ksize, isize);

                        corr2d_linearizer_t<tscalar> corr2lin;
                        for (tsize o = 0; o < m_odims; o ++)
                        {
                                odata_lin.block(o * ksize, 0, ksize, isize) =
                                corr2lin(odata.matrix(o), kdata);
                        }

                        tensor::map_matrix(idata.data(), m_idims, isize) =
                        tensor::map_matrix(kdata.data(), m_idims, m_odims * ksize) *
                        odata_lin;

                        return true;
                }

                template
                <
                        typename ttensor,
                        typename tsize,
                        typename tscalar
                >
                template
                <
                        typename ttensori,
                        typename ttensork,
                        typename ttensoro
                >
                bool conv3d_t<ttensor, tsize, tscalar>::gparam(
                        const ttensori& idata, ttensork&& kdata, const ttensoro& odata) const
                {
                        if (    idata.dims() != m_idims ||
                                odata.dims() != m_odims ||
                                kdata.dims() != m_idims * m_odims)
                        {
                                return false;
                        }

                        const auto osize = odata.planeSize();
                        const auto ksize = kdata.planeSize();

                        conv2d_linearizer_t<tscalar> conv2dlin;

                        for (tsize i = 0; i < m_idims; i ++)
                        {
                                tensor::map_matrix(kdata.planeData(i * m_odims), m_odims, ksize) =
                                tensor::map_matrix(odata.data(), m_odims, osize) *
                                conv2dlin(idata.matrix(i), odata);
                        }

                        return true;
                }
        }
}

<|endoftext|>