<commit_before>/*###################################################
  ##################Cic-Cac-Coe######################
  ######## All rights reserved to SAFAD(C) ##########
  ###########Please read the LICENSE file############
  ###################################################*/

#include <iostream>
#include <cstdlib>
#include <vector>
#include <algorithm>

using namespace std;

//This is our board, 0 => empty, 1 => X, 2 => O
vector<char> board;
//the game is running or not ? 1 yes , 0 no
int status = 0;
//turns 1 = player1, 2 = player2 OR CPU
int turn = 1;
//to define the character we put in the column
char block;
//the user input
int selection;
//AI vs Human
int opponent;

int checkGame(vector<char> board);
void run();
//show the board
void show_board() {
    cout << "+++++++++++++++++++++++++++++" << endl;
    for(int i=0; i<7; i+=3) {
        cout << "+++++ "<< board[i] <<" ++++ "<< board[i+1] << " +++++ " << board[i+2] <<" ++++++" << endl;
        cout << "+++++++++++++++++++++++++++++" << endl;
    }
}

//tell them spike, tell them its a draw !!
void show_draw(){
	cout << "Nothing to see here Peeps, its a Draw" << endl;
}
//show winner !
void show_winner(){
	cout << "Winner is Player " << turn << " congratulations !!" << endl;
}

//check who won !
bool check_winner(vector<char> board){

    for(int i=0; i<7; i+=3) {
        if((board[i] == 'X' && board[i+1] == 'X' && board[i+2] == 'X') || (board[i] == 'O' && board[i+1] == 'O' && board[i+2] == 'O')){
            return true;
        }
    }

    for(int i=0; i<3; i++) {
        if((board[i] == 'X' && board[i+3] == 'X' && board[i+6] == 'X') || (board[i] == 'O' && board[i+3] == 'O' && board[i+6] == 'O')){
            return true;
        }
    }

    for(int i=0; i<3; i+=2) {
        if((board[i] == 'X' && board[4] == 'X' && board[8-i] == 'X') || (board[i] == 'O' && board[4] == 'O' && board[8-i] == 'O')){
            return true;
        }
    }

    return false;
}

bool check_draw(vector<char> board){
    if (std::find(board.begin(), board.end(), '0') != board.end())
    {
        //there still are no more moves
        //now lets see if someone one
        if (!check_winner(board)) {
            return true;
        }
    }

	return false;

}

//validates the user input
bool validate_selection(int selection){
	//first we check if it is out of range
	if (selection > 8 || selection < 0)
	{
		return false;
	}
	if(board[selection] == 'X' || board[selection] == 'O'){
		return false;
	}
	else {
		return true;
	}
}

//function to switch from player one to two and vice versa
void switch_turns(){
	if(turn == 1){
		turn = 2;
	}
	else{
		turn = 1;
	}
	run();
}

void check_status(vector<char> board){
	int gameStatus = checkGame(board);
	//before we switch turns, we check if the user won or not
	if(gameStatus == 0){
		switch_turns();

	}
	//what if the game is a Draw ?
	else if(gameStatus == 1){
		show_board();
		show_draw();
		status = 0;
	}
	else{
		//winnnnnn
		show_board();
		show_winner();
		status = 0;
	}
}

vector<int> getAllPossibleMoves(vector<char> board){
	vector<int> spaces;
	for (int i = 0; i < 9; ++i)
	{
		if (board[i] == 'E')
		{
			//this is the chosen one
			spaces.push_back(i);
		}
	}
	return spaces;
}

//we use this function to check the game status, is it won, or draw
//int unfinished = 0, won = 1, draw = 2;

int checkGame(vector<char> board){
	if(check_winner(board)){
		return 1;
	}
	//what if the game is a Draw ?
	else if(check_draw(board)){
		return 2;

	}
	return 0;
}

int getScore(vector<char> board, char turn){
	int bestScore = 0,
		iterations = 0,
		MAXWIN = 100,
		penalty = -5;
	//here, we read all the possible moves, and choose the best based on the score
	//score, MAXWIN = 100, DRAW = 0, MAXLOSE = -5
	//The MAXWIN score is acheived by doing the least of iterations
	//MAXLOSE score is achieved by doing the most of iterations, this means the computer, if he is going to lose, choose the longest path
	//How to calculate score: MAXWIN += -5*(iterations); MAXLOSE += 5*(iterations);
	//first we get all the possible moves
	vector<int> moves = getAllPossibleMoves(board);
	//now we loop through every possibility
	for(std::vector<int>::size_type i = 0; i != moves.size(); i++)
	{
		//okay so for this we clone the board, add our move
		vector<char> newBoard(board);
		//then we add a move
		newBoard[moves[i]] = turn;
		//now we check if the game is won or a draw
		if (checkGame(newBoard) == 1){
			//this move, wins the game, but who won?
			//if the AI wins : calculate the score, if it is better, save it as best score
			//if the opponent wins : we calculate the lose score, compare it if it is better, then save it..
			int score;
			if (turn == 'O')
			{
				//its me mittens!
				score =  MAXWIN + penalty*iterations;
			}else{
				//its the human being...
				score = -MAXWIN - penalty*iterations;

			}
			bestScore = (bestScore < score) ? score : bestScore;

		}else if (checkGame(newBoard) == 2){
			//its a draw, we see if the bestScore is a losing score, we rather draw than lose..
			bestScore = (bestScore < 0) ? 0 : bestScore;
		}else{
			//the game is unfinished
			++iterations;
			//now we create a new board, and get its best score..
			vector<char> clonedBoard(newBoard);
			char newTurn = (turn == 'X') ? 'O' : 'X';
			int score = getScore(clonedBoard,newTurn);
			bestScore = (bestScore < score) ? score : bestScore;
		}

	}
	return bestScore;
}
int nextMove(){
	//first we see, if the game has just begun
	//first we generate a list of all possible moves
	//then we loop over it
	//then we get the score of each move
	//and we compare it to the bestScore, if it is better take it and keep it as best move
	int bestScore,
		bestMove;

	vector<int> moves = getAllPossibleMoves(board);
	int size = moves.size();
	if (size == 8)
	{
		int random = rand() % size;
		return moves[random];

	}
	for(std::vector<int>::size_type i = 0; i != size; i++) {
	    vector<char> newBoard(board);
		newBoard[moves[i]] = 'O';
		int score = getScore(newBoard,'X');
		if (bestScore < score)
		{
			bestScore = score;
			bestMove = moves[i];
		}
	}
	cout << bestMove << endl;
	return bestMove;
}

void AI(){
	cout << "Calculating..." << endl;
	int next = nextMove();
	//now we use it on screen
	if(validate_selection(next)){
		board[next] = 'O';
		check_status(board);
	}
	else{
		AI();
	}
}

void player(){
	cout << "Player " << turn << " Please enter a valid number (0-8) :" <<endl;
	cin >> selection;
	if(validate_selection(selection)){
		board[selection] = block;
		check_status(board);
	}else{
		//his choice is invalid
		cout << "invalid move" << endl;
		player();
	}
}

//function to show the board
void run(){
	show_board();
	block = (turn == 1) ? 'X' : 'O';
	//Artificial Inteligence :)
	if(opponent == 2 && turn == 2){
		AI();
	}
	else{
		player();
	}

}

int main(){
	//we first populate the board with dummy strings
	char dummy[9] = {'E','E','E','E','E','E','E','E','E'};

	for(int index=0;index<9; ++index)
	{
		board.push_back(dummy[index]);
	}

	if(status == 0){
		cout << "Play VS :" << endl;
		cout << "1. Human" << endl;
		cout << "2. AI (CPU)" << endl;
		cin >> opponent;
		status = 1;
	}
	run();
}

<commit_msg>few changes here and there, half stupid AI, still crashes..<commit_after>/*###################################################
  ##################Cic-Cac-Coe######################
  ######## All rights reserved to SAFAD(C) ##########
  ###########Please read the LICENSE file############
  ###################################################*/

#include <iostream>
#include <cstdlib>
#include <vector>
#include <algorithm>

using namespace std;

//This is our board, 0 => empty, 1 => X, 2 => O
vector<char> board;
//the game is running or not ? 1 yes , 0 no
int status = 0;
//turns 1 = player1, 2 = player2 OR CPU
int turn = 1;
//to define the character we put in the column
char block;
//the user input
int selection;
//AI vs Human
int opponent;

int checkGame(vector<char> board);
void run();
//show the board
void show_board() {
    cout << "+++++++++++++++++++++++++++++" << endl;
    for(int i=0; i<7; i+=3) {
        cout << "+++++ "<< board[i] <<" ++++ "<< board[i+1] << " +++++ " << board[i+2] <<" ++++++" << endl;
        cout << "+++++++++++++++++++++++++++++" << endl;
    }
}

//tell them spike, tell them its a draw !!
void show_draw(){
	cout << "Nothing to see here Peeps, its a Draw" << endl;
}
//show winner !
void show_winner(){
	cout << "Winner is Player " << turn << " congratulations !!" << endl;
}

//check who won !
bool check_winner(vector<char> board){

    for(int i=0; i<7; i+=3) {
        if((board[i] == 'X' && board[i+1] == 'X' && board[i+2] == 'X') || (board[i] == 'O' && board[i+1] == 'O' && board[i+2] == 'O')){
            return true;
        }
    }

    for(int i=0; i<3; i++) {
        if((board[i] == 'X' && board[i+3] == 'X' && board[i+6] == 'X') || (board[i] == 'O' && board[i+3] == 'O' && board[i+6] == 'O')){
            return true;
        }
    }

    for(int i=0; i<3; i+=2) {
        if((board[i] == 'X' && board[4] == 'X' && board[8-i] == 'X') || (board[i] == 'O' && board[4] == 'O' && board[8-i] == 'O')){
            return true;
        }
    }

    return false;
}

bool check_draw(vector<char> board){
    if (std::count(board.begin(), board.end(), 'E') < 0)
    {
        //there still are no more moves
        //now lets see if someone one
        if (!check_winner(board)) {
            return true;
        }
    }

	return false;

}

//validates the user input
bool validate_selection(int selection){
	//first we check if it is out of range
	if (selection > 8 || selection < 0)
	{
		return false;
	}
	if(board[selection] == 'X' || board[selection] == 'O'){
		return false;
	}
	else {
		return true;
	}
}

//function to switch from player one to two and vice versa
void switch_turns(){
	if(turn == 1){
		turn = 2;
	}
	else{
		turn = 1;
	}
	run();
}

void check_status(vector<char> board){
	int gameStatus = checkGame(board);
	//before we switch turns, we check if the user won or not
	if(gameStatus == 0){
		switch_turns();

	}
	//what if the game is a Draw ?
	else if(gameStatus == 2){
		show_board();
		show_draw();
		status = 0;
	}
	else if(gameStatus == 1){
		//winnnnnn
		show_board();
		show_winner();
		status = 0;
	}
}

vector<int> getAllPossibleMoves(vector<char> board){
	vector<int> spaces;
	for (int i = 0; i < 9; ++i)
	{
		if (board[i] == 'E')
		{
			//this is the chosen one
			spaces.push_back(i);
		}
	}
	return spaces;
}

//we use this function to check the game status, is it won, or draw
//int unfinished = 0, won = 1, draw = 2;

int checkGame(vector<char> board){
	if(check_winner(board)){
		return 1;
	}
	//what if the game is a Draw ?
	else if(check_draw(board)){
		return 2;

	}
	return 0;
}

int getScore(vector<char> board, char turn){
	int bestScore = 0,
		iterations = 0,
		MAXWIN = 100,
		penalty = -5;
	//here, we read all the possible moves, and choose the best based on the score
	//score, MAXWIN = 100, DRAW = 0, MAXLOSE = -5
	//The MAXWIN score is acheived by doing the least of iterations
	//MAXLOSE score is achieved by doing the most of iterations, this means the computer, if he is going to lose, choose the longest path
	//How to calculate score: MAXWIN += -5*(iterations); MAXLOSE += 5*(iterations);
	//first we get all the possible moves
	vector<int> moves = getAllPossibleMoves(board);
	//now we loop through every possibility
	for(std::vector<int>::size_type i = 0; i != moves.size(); i++)
	{
		//okay so for this we clone the board, add our move
		vector<char> newBoard(board);
		//then we add a move
		newBoard[moves[i]] = turn;
		//now we check if the game is won or a draw
		if (checkGame(newBoard) == 1){
			//this move, wins the game, but who won?
			//if the AI wins : calculate the score, if it is better, save it as best score
			//if the opponent wins : we calculate the lose score, compare it if it is better, then save it..
			int score;
			if (turn == 'O')
			{
				//its me mittens!
				score =  MAXWIN + penalty*iterations;
			}else{
				//its the human being...
				score = -MAXWIN - penalty*iterations;

			}
			bestScore = (bestScore < score) ? score : bestScore;

		}else if (checkGame(newBoard) == 2){
			//its a draw, we see if the bestScore is a losing score, we rather draw than lose..
			bestScore = (bestScore < 0) ? 0 : bestScore;
		}else{
			//the game is unfinished
			++iterations;
			//now we create a new board, and get its best score..
			vector<char> clonedBoard(newBoard);
			char newTurn = (turn == 'X') ? 'O' : 'X';
			int score = getScore(clonedBoard,newTurn);
			bestScore = (bestScore < score) ? score : bestScore;
		}

	}
	return bestScore;
}
int nextMove(){
	//first we see, if the game has just begun
	//first we generate a list of all possible moves
	//then we loop over it
	//then we get the score of each move
	//and we compare it to the bestScore, if it is better take it and keep it as best move
	int bestScore = 0,
		bestMove = 0;

	vector<int> moves = getAllPossibleMoves(board);
	int size = moves.size();
	if (size == 8)
	{
		int random = rand() % size;
		return moves[random];

	}
	for(std::vector<int>::size_type i = 0; i != size; i++) {
	    vector<char> newBoard(board);
		newBoard[moves[i]] = 'O';
		int score = getScore(newBoard,'X');
		if (bestScore < score)
		{
			bestScore = score;
			bestMove = moves[i];
		}
	}
	return bestMove;
}

void AI(){
	cout << "Calculating..." << endl;
	int next = nextMove();
	//now we use it on screen
	if(validate_selection(next)){
		board[next] = 'O';
		check_status(board);
	}
	else{
		AI();
	}
}

void player(){
	cout << "Player " << turn << " Please enter a valid number (0-8) :" <<endl;
	cin >> selection;
	if(validate_selection(selection)){
		board[selection] = block;
		check_status(board);
	}else{
		//his choice is invalid
		cout << "invalid move" << endl;
		player();
	}
}

//function to show the board
void run(){
	show_board();
	block = (turn == 1) ? 'X' : 'O';
	//Artificial Inteligence :)
	if(opponent == 2 && turn == 2){
		AI();
	}
	else{
		player();
	}

}

int main(){
	//we first populate the board with dummy strings
	char dummy[9] = {'E','E','E','E','E','E','E','E','E'};

	for(int index=0;index<9; ++index)
	{
		board.push_back(dummy[index]);
	}

	if(status == 0){
		cout << "Play VS :" << endl;
		cout << "1. Human" << endl;
		cout << "2. AI (CPU)" << endl;
		cin >> opponent;
		status = 1;
	}
	run();
}

<|endoftext|>


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

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

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

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

=========================================================================*/
#include "otbMeanShiftSegmentationFilter.h"
#include "itkMacro.h"
#include "otbImage.h"
#include "otbVectorImage.h"
#include "otbImageFileReader.h"
#include "otbImageFileWriter.h"

int otbMeanShiftSegmentationFilter(int argc, char * argv[])
{
  if (argc != 6)
    {
    std::cerr << "Usage: " << argv[0] <<
    " inputFileName outputLabelFileName outputClusteredFileName spatialBandwidth rangeBandwidth"
              << std::endl;
    return EXIT_FAILURE;
    }

  const char *       inputFileName             = argv[1];
  const char *       outputLabelFileName       = argv[2];
  const char *       outputClusteredFileName   = argv[3];
  const double       spatialBandwidth          = atof(argv[4]);
  const double       rangeBandwidth            = atof(argv[5]);

  /* maxit - threshold */

  const unsigned int Dimension = 2;
  typedef float                                            PixelType;
  typedef double                                           KernelType;
  typedef otb::VectorImage<PixelType, Dimension>           ImageType;
  typedef otb::Image<unsigned int, Dimension>              LabelImageType;
  typedef otb::ImageFileReader<ImageType>                  ReaderType;
  typedef otb::ImageFileWriter<ImageType>                  ClusteredWriterType;
  typedef otb::ImageFileWriter<LabelImageType>             LabelWriterType;

  typedef otb::MeanShiftSegmentationFilter<ImageType, LabelImageType, ImageType> FilterType;

  // Instantiating object
  FilterType::Pointer filter = FilterType::New();
  ReaderType::Pointer reader = ReaderType::New();

  reader->SetFileName(inputFileName);

  // Set filter parameters
  filter->SetSpatialBandwidth(spatialBandwidth);
  filter->SetRangeBandwidth(rangeBandwidth);
  filter->SetInput(reader->GetOutput());

  //filter->SetNumberOfThreads(1);
  ClusteredWriterType::Pointer writerClustered = ClusteredWriterType::New();
  LabelWriterType::Pointer writerLabel = LabelWriterType::New();

  writerClustered->SetFileName(outputClusteredFileName);
  writerLabel->SetFileName(outputLabelFileName);

  writerClustered->SetInput(filter->GetClusteredOutput());
  writerLabel->SetInput(filter->GetLabelOutput());

//  writerClustered->Update();
  writerLabel->Update();

  return EXIT_SUCCESS;
}
<commit_msg>TEST: Activating 2nd output<commit_after>/*=========================================================================

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

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

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

=========================================================================*/
#include "otbMeanShiftSegmentationFilter.h"
#include "itkMacro.h"
#include "otbImage.h"
#include "otbVectorImage.h"
#include "otbImageFileReader.h"
#include "otbImageFileWriter.h"

int otbMeanShiftSegmentationFilter(int argc, char * argv[])
{
  if (argc != 6)
    {
    std::cerr << "Usage: " << argv[0] <<
    " inputFileName outputLabelFileName outputClusteredFileName spatialBandwidth rangeBandwidth"
              << std::endl;
    return EXIT_FAILURE;
    }

  const char *       inputFileName             = argv[1];
  const char *       outputLabelFileName       = argv[2];
  const char *       outputClusteredFileName   = argv[3];
  const double       spatialBandwidth          = atof(argv[4]);
  const double       rangeBandwidth            = atof(argv[5]);

  /* maxit - threshold */

  const unsigned int Dimension = 2;
  typedef float                                            PixelType;
  typedef double                                           KernelType;
  typedef otb::VectorImage<PixelType, Dimension>           ImageType;
  typedef otb::Image<unsigned int, Dimension>              LabelImageType;
  typedef otb::ImageFileReader<ImageType>                  ReaderType;
  typedef otb::ImageFileWriter<ImageType>                  ClusteredWriterType;
  typedef otb::ImageFileWriter<LabelImageType>             LabelWriterType;

  typedef otb::MeanShiftSegmentationFilter<ImageType, LabelImageType, ImageType> FilterType;

  // Instantiating object
  FilterType::Pointer filter = FilterType::New();
  ReaderType::Pointer reader = ReaderType::New();

  reader->SetFileName(inputFileName);

  // Set filter parameters
  filter->SetSpatialBandwidth(spatialBandwidth);
  filter->SetRangeBandwidth(rangeBandwidth);
  filter->SetInput(reader->GetOutput());

  //filter->SetNumberOfThreads(1);
  ClusteredWriterType::Pointer writerClustered = ClusteredWriterType::New();
  LabelWriterType::Pointer writerLabel = LabelWriterType::New();

  writerClustered->SetFileName(outputClusteredFileName);
  writerLabel->SetFileName(outputLabelFileName);

  writerClustered->SetInput(filter->GetClusteredOutput());
  writerLabel->SetInput(filter->GetLabelOutput());

  writerClustered->Update();
  writerLabel->Update();

  return EXIT_SUCCESS;
}
<|endoftext|>


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

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

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

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

=========================================================================*/
#include "itkExceptionObject.h"
#include "itkFixedArray.h"
#include "otbLandsatTMIndices.h"

int otbLandsatTMIndexVis(int argc, char * argv[])
{
  typedef double                           OutputPixelType;
  typedef itk::FixedArray< double, 8 >     InputPixelType;

  typedef otb::Functor::LandsatTM::Vis<InputPixelType, OutputPixelType> FunctorType;

  FunctorType visFunct = FunctorType();

  double TM1 = (::atof(argv[1]));
  double TM2 = (::atof(argv[2]));
  double TM3 = (::atof(argv[3]));
  double TM4 = (::atof(argv[4]));
  double TM5 = (::atof(argv[5]));
  double TM61 = (::atof(argv[6]));
  double TM62 = (::atof(argv[7]));
  double TM7 = (::atof(argv[8]));

  double goodResult = (TM1+TM2+TM3)/3.0;

  std::cout << goodResult ;

  InputPixelType pixel;
  pixel[0] = TM1;
  pixel[1] = TM2;
  pixel[2] = TM3;
  pixel[3] = TM4;
  pixel[4] = TM5;
  pixel[5] = TM61;
  pixel[6] = TM62;
  pixel[7] = TM7;

  double result = visFunct(pixel);

  std::cout << " " << result << std::endl;

  if( result!=goodResult ) return EXIT_FAILURE;

  return EXIT_SUCCESS;
}
<commit_msg>TEST: Landsat TM NIR test<commit_after>/*=========================================================================

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

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

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

=========================================================================*/
#include "itkExceptionObject.h"
#include "itkFixedArray.h"
#include "otbLandsatTMIndices.h"

int otbLandsatTMIndexNIR(int argc, char * argv[])
{
  typedef double                           OutputPixelType;
  typedef itk::FixedArray< double, 8 >     InputPixelType;

  typedef otb::Functor::LandsatTM::NIR<InputPixelType, OutputPixelType> FunctorType;

  FunctorType nirFunct = FunctorType();

  double TM1 = (::atof(argv[1]));
  double TM2 = (::atof(argv[2]));
  double TM3 = (::atof(argv[3]));
  double TM4 = (::atof(argv[4]));
  double TM5 = (::atof(argv[5]));
  double TM61 = (::atof(argv[6]));
  double TM62 = (::atof(argv[7]));
  double TM7 = (::atof(argv[8]));

  double goodResult = TM4;

  std::cout << goodResult ;

  InputPixelType pixel;
  pixel[0] = TM1;
  pixel[1] = TM2;
  pixel[2] = TM3;
  pixel[3] = TM4;
  pixel[4] = TM5;
  pixel[5] = TM61;
  pixel[6] = TM62;
  pixel[7] = TM7;

  double result = visFunct(pixel);

  std::cout << " " << result << std::endl;

  if( result!=goodResult ) return EXIT_FAILURE;

  return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>#pragma once

// generic (non-architecture-specific) implementations of gemmBitserial
// and other related functions

GEMMContext allocGEMMContext_generic(
  uint64_t lhsRows, uint64_t depth, uint64_t rhsRows,
  uint64_t lhsBits, uint64_t rhsBits,
  bool lhsSigned, bool rhsSigned
) {
  const uint64_t regblock_lhs = 2;
  const uint64_t regblock_d = 1;
  const uint64_t regblock_rhs = 2;
  const uint64_t cacheBits = 32*1024*8;

  GEMMContext ret;
  uint64_t depth_al = alignTo(depth, regblock_d*64);
  // TODO add bypass for small enough matrices here?
  // use cache blocking; compute sizes
  computeBlockSize(
    regblock_lhs, regblock_rhs, cacheBits, depth_al,
    ret.lhsBlock, ret.rhsBlock
  );
  if(ret.lhsBlock > lhsRows || ret.rhsBlock > rhsRows) {
    // use register blocking only
    ret.lhsBlock = regblock_lhs;
    ret.rhsBlock = regblock_rhs;
  }
  // allocate aligned bit serial matrices
  ret.lhs = BitSerialMatrix::alloc(
    lhsBits, lhsRows, depth, lhsSigned, ret.lhsBlock, regblock_d*64
  );
  ret.rhs = BitSerialMatrix::alloc(
    rhsBits, rhsRows, depth, rhsSigned, ret.rhsBlock, regblock_d*64
  );
  // allocate result matrix. note that it is not aligned -- the
  // elements corresponding to alignment parts won't materialize.
  ret.res = new int32_t[lhsRows * rhsRows];
  return ret;
};

/* Multiply a lhs_block x rhs_block chunk of the given matrices, starting at
  (bA, bBT) using 2x1x2 register tiling. For internal use.
*/
inline void gemmBinary_generic_chunk_tile2x1x2(
  uint64_t * A, uint64_t * BT, int32_t * CT,
  int32_t alpha,
  uint64_t rowsA, uint64_t depth_words, uint64_t rowsBT,
  uint64_t bA, uint64_t bBT,
  uint64_t lhs_block, uint64_t rhs_block,
  uint64_t rowsA_orig, uint64_t rowsBT_orig) {
  const uint64_t Atile = 2, DepthTile = 1, BTtile = 2;
  const size_t num_acc = Atile*BTtile;

  for(uint64_t rBT = bBT; rBT < bBT + rhs_block; rBT += BTtile) {
    uint64_t * BTptr = &BT[rBT * depth_words];
    for(uint64_t rA = bA; rA < bA + lhs_block; rA += Atile) {
      uint64_t * Aptr = &A[rA * depth_words];
      int32_t acc[num_acc] = {0};
      for(uint64_t d = 0; d < depth_words; d += DepthTile) {
        const uint64_t a0 = Aptr[d], a1 = Aptr[d + depth_words];
        const uint64_t b0 = BTptr[d], b1 = BTptr[d + depth_words];
        acc[0] += __builtin_popcountll(a0 & b0);
        acc[1] += __builtin_popcountll(a0 & b1);
        acc[2] += __builtin_popcountll(a1 & b0);
        acc[3] += __builtin_popcountll(a1 & b1);
      }
      for(uint64_t at = 0; at < Atile; at++) {
        for(uint64_t bt = 0; bt < BTtile; bt++) {
          // TODO less than or leq?
          if(((rBT + bt) < rowsBT_orig) && ((rA + at) < rowsA_orig)) {
            CT[(rBT + bt) * rowsA_orig + (rA + at)] += acc[at * BTtile + bt] * alpha;
          }
        }
      }
    }
  }
}

/* CT = A * BT using cache blocking and 2x1x2 register blocking where possible.
   For internal use.
*/
void gemmBinary_generic_L1_tile2x1x2(
  uint64_t * A, uint64_t * BT, int32_t * CT, int32_t alpha,
  uint64_t rowsA, uint64_t depth_words, uint64_t rowsBT,
  uint64_t rowsA_orig, uint64_t rowsBT_orig,
  uint64_t lhsBlock, uint64_t rhsBlock
  ) {
  const uint64_t Atile = 2, DepthTile = 1, BTtile = 2;
  assert(rowsBT % rhsBlock == 0);
  assert(rowsA % lhsBlock == 0);
  assert(lhsBlock % Atile == 0);
  assert(rhsBlock % BTtile == 0);

  for(uint64_t bBT = 0; bBT < rowsBT; bBT += rhsBlock) {
    for(uint64_t bA = 0; bA < rowsA; bA += lhsBlock) {
      gemmBinary_generic_chunk_tile2x1x2(
        A, BT, CT, alpha, rowsA, depth_words, rowsBT, bA, bBT,
        lhsBlock, rhsBlock, rowsA_orig, rowsBT_orig
      );
    }
  }
}

/* Bit-serial GEMM via a series of calls to gemmBinary.
   Note that rhs must be given in transposed form, and the result is also
   produced transposed.
*/

void gemmBitSerial_generic_usingBinary(GEMMContext ctx) {
  // ensure that matrix shapes are compatible
  assert(ctx.lhs.ncols == ctx.rhs.ncols);
  const uint64_t lhsbits = ctx.lhs.nbits;
  const uint64_t rhsbits = ctx.rhs.nbits;
  // clear contents of result matrix by setting everything to zero
  memset(ctx.res, 0, ctx.lhs.nrows*ctx.rhs.nrows*sizeof(int32_t));
  // call binary GEMM for each bit position
  for(uint64_t lbit = 0; lbit < lhsbits; lbit++) {
    bool neg_lhs = ctx.lhs.issigned && (lbit == lhsbits-1);
    for(uint64_t rbit = 0; rbit < rhsbits; rbit++) {
      bool neg_rhs = ctx.rhs.issigned && (rbit == rhsbits-1);
      bool neg = neg_rhs ^ neg_lhs;
      int32_t alpha = neg ? -(1 << (lbit+rbit)) : (1 << (lbit+rbit));
      gemmBinary_generic_L1_tile2x1x2(
        ctx.lhs.bitplaneptr(lbit), ctx.rhs.bitplaneptr(rbit), ctx.res, alpha,
        ctx.lhs.nrows_a, ctx.lhs.wordsPerRow(), ctx.rhs.nrows_a,
        ctx.lhs.nrows, ctx.rhs.nrows, ctx.lhsBlock, ctx.rhsBlock
      );
    }
  }
}
<commit_msg>fix blocking for small matrices<commit_after>#pragma once

// generic (non-architecture-specific) implementations of gemmBitserial
// and other related functions

GEMMContext allocGEMMContext_generic(
  uint64_t lhsRows, uint64_t depth, uint64_t rhsRows,
  uint64_t lhsBits, uint64_t rhsBits,
  bool lhsSigned, bool rhsSigned
) {
  const uint64_t regblock_lhs = 2;
  const uint64_t regblock_d = 1;
  const uint64_t regblock_rhs = 2;
  const uint64_t cacheBits = 32*1024*8;

  GEMMContext ret;
  uint64_t depth_al = alignTo(depth, regblock_d*64);
  // TODO add bypass for small enough matrices here?
  // use cache blocking; compute sizes
  computeBlockSize(
    regblock_lhs, regblock_rhs, cacheBits, depth_al,
    ret.lhsBlock, ret.rhsBlock
  );
  if(ret.lhsBlock > lhsRows || ret.rhsBlock > rhsRows) {
    // use register blocking only
    ret.lhsBlock = alignTo(lhsRows, regblock_lhs);
    ret.rhsBlock = alignTo(rhsRows, regblock_rhs);
  }
  // allocate aligned bit serial matrices
  ret.lhs = BitSerialMatrix::alloc(
    lhsBits, lhsRows, depth, lhsSigned, ret.lhsBlock, regblock_d*64
  );
  ret.rhs = BitSerialMatrix::alloc(
    rhsBits, rhsRows, depth, rhsSigned, ret.rhsBlock, regblock_d*64
  );
  // allocate result matrix. note that it is not aligned -- the
  // elements corresponding to alignment parts won't materialize.
  ret.res = new int32_t[lhsRows * rhsRows];
  return ret;
};

/* Multiply a lhs_block x rhs_block chunk of the given matrices, starting at
  (bA, bBT) using 2x1x2 register tiling. For internal use.
*/
inline void gemmBinary_generic_chunk_tile2x1x2(
  uint64_t * A, uint64_t * BT, int32_t * CT,
  int32_t alpha,
  uint64_t rowsA, uint64_t depth_words, uint64_t rowsBT,
  uint64_t bA, uint64_t bBT,
  uint64_t lhs_block, uint64_t rhs_block,
  uint64_t rowsA_orig, uint64_t rowsBT_orig) {
  const uint64_t Atile = 2, DepthTile = 1, BTtile = 2;
  const size_t num_acc = Atile*BTtile;

  for(uint64_t rBT = bBT; rBT < bBT + rhs_block; rBT += BTtile) {
    uint64_t * BTptr = &BT[rBT * depth_words];
    for(uint64_t rA = bA; rA < bA + lhs_block; rA += Atile) {
      uint64_t * Aptr = &A[rA * depth_words];
      int32_t acc[num_acc] = {0};
      for(uint64_t d = 0; d < depth_words; d += DepthTile) {
        const uint64_t a0 = Aptr[d], a1 = Aptr[d + depth_words];
        const uint64_t b0 = BTptr[d], b1 = BTptr[d + depth_words];
        acc[0] += __builtin_popcountll(a0 & b0);
        acc[1] += __builtin_popcountll(a0 & b1);
        acc[2] += __builtin_popcountll(a1 & b0);
        acc[3] += __builtin_popcountll(a1 & b1);
      }
      for(uint64_t at = 0; at < Atile; at++) {
        for(uint64_t bt = 0; bt < BTtile; bt++) {
          if(((rBT + bt) < rowsBT_orig) && ((rA + at) < rowsA_orig)) {
            CT[(rBT + bt) * rowsA_orig + (rA + at)] += acc[at * BTtile + bt] * alpha;
          }
        }
      }
    }
  }
}

/* CT = A * BT using cache blocking and 2x1x2 register blocking where possible.
   For internal use.
*/
void gemmBinary_generic_L1_tile2x1x2(
  uint64_t * A, uint64_t * BT, int32_t * CT, int32_t alpha,
  uint64_t rowsA, uint64_t depth_words, uint64_t rowsBT,
  uint64_t rowsA_orig, uint64_t rowsBT_orig,
  uint64_t lhsBlock, uint64_t rhsBlock
  ) {
  const uint64_t Atile = 2, DepthTile = 1, BTtile = 2;
  assert(rowsBT % rhsBlock == 0);
  assert(rowsA % lhsBlock == 0);
  assert(lhsBlock % Atile == 0);
  assert(rhsBlock % BTtile == 0);

  for(uint64_t bBT = 0; bBT < rowsBT; bBT += rhsBlock) {
    for(uint64_t bA = 0; bA < rowsA; bA += lhsBlock) {
      gemmBinary_generic_chunk_tile2x1x2(
        A, BT, CT, alpha, rowsA, depth_words, rowsBT, bA, bBT,
        lhsBlock, rhsBlock, rowsA_orig, rowsBT_orig
      );
    }
  }
}

/* Bit-serial GEMM via a series of calls to gemmBinary.
   Note that rhs must be given in transposed form, and the result is also
   produced transposed.
*/

void gemmBitSerial_generic_usingBinary(GEMMContext ctx) {
  // ensure that matrix shapes are compatible
  assert(ctx.lhs.ncols == ctx.rhs.ncols);
  const uint64_t lhsbits = ctx.lhs.nbits;
  const uint64_t rhsbits = ctx.rhs.nbits;
  // clear contents of result matrix by setting everything to zero
  memset(ctx.res, 0, ctx.lhs.nrows*ctx.rhs.nrows*sizeof(int32_t));
  // call binary GEMM for each bit position
  for(uint64_t lbit = 0; lbit < lhsbits; lbit++) {
    bool neg_lhs = ctx.lhs.issigned && (lbit == lhsbits-1);
    for(uint64_t rbit = 0; rbit < rhsbits; rbit++) {
      bool neg_rhs = ctx.rhs.issigned && (rbit == rhsbits-1);
      bool neg = neg_rhs ^ neg_lhs;
      int32_t alpha = neg ? -(1 << (lbit+rbit)) : (1 << (lbit+rbit));
      gemmBinary_generic_L1_tile2x1x2(
        ctx.lhs.bitplaneptr(lbit), ctx.rhs.bitplaneptr(rbit), ctx.res, alpha,
        ctx.lhs.nrows_a, ctx.lhs.wordsPerRow(), ctx.rhs.nrows_a,
        ctx.lhs.nrows, ctx.rhs.nrows, ctx.lhsBlock, ctx.rhsBlock
      );
    }
  }
}
<|endoftext|>


<commit_before>#include "OpenAddressingHash.hpp"

#include "Logging.hpp"

#include <boost/functional/hash.hpp>

namespace tell {
namespace store {

namespace {

void* const  gDeletedPtr = reinterpret_cast<void*>(0x1u);
void* const gInvalidPtr = reinterpret_cast<void*>(0x2u);

/**
 * @brief Check the wellformedness of tableId and keyId
 */
void checkDataKey(uint64_t table, uint64_t key) {
    LOG_ASSERT(table != 0x0u, "Table ID must not be 0");
    LOG_ASSERT(key != 0x0u, "Key ID must not be 0");
}

/**
 * @brief Check the wellformedness of data pointers
 */
void checkDataPtr(const void* ptr) {
    LOG_ASSERT(ptr != nullptr, "Data pointer not allowed to be null");
    LOG_ASSERT(ptr != gDeletedPtr, "The two LSBs have to be zero");
    LOG_ASSERT(ptr != gInvalidPtr, "The two LSBs have to be zero");
}

} // anonymous namespace

OpenAddressingTable::OpenAddressingTable(size_t capacity)
        : mCapacity(capacity),
          mBuckets(new Entry[mCapacity]),
          mTableHash(mCapacity),
          mKeyHash(mCapacity) {
}

OpenAddressingTable::~OpenAddressingTable() {
    delete[] mBuckets;
}

const void* OpenAddressingTable::get(uint64_t table, uint64_t key) const {
    checkDataKey(table, key);

    return execOnElement(table, key, static_cast<const void*>(nullptr), [] (const Entry& /* entry */, const void* ptr) {
        return ptr;
    });
}

bool OpenAddressingTable::insert(uint64_t table, uint64_t key, void* data) {
    checkDataKey(table, key);
    checkDataPtr(data);

    auto hash = calculateHash(table, key);
    for (auto pos = hash;; ++pos) {
        auto& entry = mBuckets[pos % mCapacity];
        auto ptr = entry.ptr.load();

        // Check if pointer is invalid
        if (ptr == gInvalidPtr) {
            continue;
        }

        // Check if pointer denotes a valid element
        if (ptr != nullptr && ptr != gDeletedPtr) {
            // Check if bucket belongs to another element, skip bucket if it does
            if (entry.tableId.load() != table || entry.keyId.load() != key) {
                continue;
            }

            // Entry exists
            return false;
        }

        // Try to claim this bucket by setting the table
        // If this fails somebody else claimed the bucket in the mean time
        uint64_t t = 0x0u;
        if (!entry.tableId.compare_exchange_strong(t, table)) {
            continue;
        }
        entry.keyId.store(key);

        // Check if another concurrent insert conflicts with ours
        // If this fails somebody else is inserting the same key, set pointer to invalid and free bucket
        if (hasInsertConflict(hash, pos, table, key)) {
            entry.ptr.store(gInvalidPtr);
            deleteEntry(entry);
            return false;
        }

        // Try to set the pointer from null or deleted to our data pointer
        // If this fails somebody else set us to invalid, so we have to free bucket
        if (!entry.ptr.compare_exchange_strong(ptr, data)) {
            deleteEntry(entry);
            return false;
        }

        return true;
    }
}

bool OpenAddressingTable::update(uint64_t table, uint64_t key, const void* oldData, void* newData) {
    checkDataKey(table, key);
    checkDataPtr(oldData);
    checkDataPtr(newData);

    return execOnElement(table, key, false, [oldData, newData] (Entry& entry, const void* /* ptr */) {
        // Set the element pointer from old to new
        auto expected = oldData;
        return entry.ptr.compare_exchange_strong(expected, newData);
    });
}

bool OpenAddressingTable::erase(uint64_t table, uint64_t key, const void* oldData) {
    checkDataKey(table, key);
    checkDataPtr(oldData);

    return execOnElement(table, key, true, [oldData] (Entry& entry, const void* /* ptr */) {
        // Try to set the pointer to invalid
        // If this fails then somebody else modified the element
        auto expected = oldData;
        if (!entry.ptr.compare_exchange_strong(expected, gInvalidPtr)) {
            return false;
        }
        deleteEntry(entry);

        return true;
    });
}

void OpenAddressingTable::deleteEntry(Entry& entry) {
    entry.tableId.store(0x0u);
    entry.keyId.store(0x0u);
    entry.ptr.store(gDeletedPtr);
}

uint64_t OpenAddressingTable::calculateHash(uint64_t table, uint64_t key) const {
    auto hash = mTableHash(table);
    boost::hash_combine(hash, mKeyHash(key));
    return hash;
}

bool OpenAddressingTable::hasInsertConflict(size_t hash, size_t insertPos, uint64_t table, uint64_t key) {
    for (auto pos = hash;; ++pos) {
        // Skip our own entry
        if (pos == insertPos) {
            continue;
        }

        auto& entry = mBuckets[pos % mCapacity];
        auto ptr = entry.ptr.load();

        // Check if pointer is invalid, skip bucket if it is
        if (ptr == gInvalidPtr) {
            continue;
        }

        auto t = entry.tableId.load();

        // Check if we reached the end of the overflow bucket and nobody is writing to this bucket
        if (ptr == nullptr && t == 0x0u) {
            LOG_ASSERT(pos > insertPos, "Reached end of overflow before reaching insert element");
            return false;
        }

        // Check if bucket belongs to another element, skip bucket if it does
        if (t != table || entry.keyId.load() != key) {
            continue;
        }

        // Check if the pointer is already set (not null without marker)
        // In this case we have to abort the insert, because another thread already completed the insert
        if ((reinterpret_cast<uintptr_t>(ptr) >> 2) != 0x0u) {
            return true;
        }

        // At this point there is a concurrent insert conflict but both threads did not yet complete the insert
        // We conflict if the element of the other thread is located in a bucket before our own insert bucket
        if (pos < insertPos) {
            return true;
        }

        // The element is located in a bucket after our own insert bucket so we try to set the other pointer to invalid
        // If this fails then the other thread completed its insert operation in the meantime and we have to abort
        if (!entry.ptr.compare_exchange_strong(ptr, gInvalidPtr)) {
            if (ptr != gInvalidPtr) {
                return true;
            }
        }
    }
}

template <typename T, typename F>
T OpenAddressingTable::execOnElement(uint64_t table, uint64_t key, T notFound, F fun) const {
    for (auto pos = calculateHash(table, key);; ++pos) {
        auto& entry = mBuckets[pos % mCapacity];
        auto ptr = entry.ptr.load();

        // Check if pointer is invalid or deleted, skip bucket if it is
        if ((reinterpret_cast<uintptr_t>(ptr) & (0x2u | 0x1u)) != 0) {
            continue;
        }

        auto t = entry.tableId.load();

        // Check if we reached the end of the overflow bucket
        if (ptr == nullptr) {
            // Check if somebody else is currently writing to this bucket, skip bucket if this is the case
            if (t != 0x0u) {
                continue;
            }

            // End of overflow bucket, element not found
            return notFound;
        }

        // Check if bucket belongs to another element, skip bucket if it does
        if (t != table || entry.keyId.load() != key) {
            continue;
        }

        // Element found
        return fun(entry, ptr);
    }
}

template <typename T, typename F>
T OpenAddressingTable::execOnElement(uint64_t table, uint64_t key, T notFound, F fun) {
    return const_cast<const OpenAddressingTable*>(this)->execOnElement(table, key, notFound,
            [&fun] (const Entry& entry, const void* ptr) {
        return fun(const_cast<Entry&>(entry), ptr);
    });
}

} // namespace store
} // namespace tell
<commit_msg>Remove restriction that key has to be 0<commit_after>#include "OpenAddressingHash.hpp"

#include "Logging.hpp"

#include <boost/functional/hash.hpp>

namespace tell {
namespace store {

namespace {

void* const  gDeletedPtr = reinterpret_cast<void*>(0x1u);
void* const gInvalidPtr = reinterpret_cast<void*>(0x2u);

/**
 * @brief Check the wellformedness of tableId and key
 */
void checkDataKey(uint64_t table, uint64_t /* key */) {
    LOG_ASSERT(table != 0x0u, "Table ID must not be 0");
}

/**
 * @brief Check the wellformedness of data pointers
 */
void checkDataPtr(const void* ptr) {
    LOG_ASSERT(ptr != nullptr, "Data pointer not allowed to be null");
    LOG_ASSERT(ptr != gDeletedPtr, "The two LSBs have to be zero");
    LOG_ASSERT(ptr != gInvalidPtr, "The two LSBs have to be zero");
}

} // anonymous namespace

OpenAddressingTable::OpenAddressingTable(size_t capacity)
        : mCapacity(capacity),
          mBuckets(new Entry[mCapacity]),
          mTableHash(mCapacity),
          mKeyHash(mCapacity) {
}

OpenAddressingTable::~OpenAddressingTable() {
    delete[] mBuckets;
}

const void* OpenAddressingTable::get(uint64_t table, uint64_t key) const {
    checkDataKey(table, key);

    return execOnElement(table, key, static_cast<const void*>(nullptr), [] (const Entry& /* entry */, const void* ptr) {
        return ptr;
    });
}

bool OpenAddressingTable::insert(uint64_t table, uint64_t key, void* data) {
    checkDataKey(table, key);
    checkDataPtr(data);

    auto hash = calculateHash(table, key);
    for (auto pos = hash;; ++pos) {
        auto& entry = mBuckets[pos % mCapacity];
        auto ptr = entry.ptr.load();

        // Check if pointer is invalid
        if (ptr == gInvalidPtr) {
            continue;
        }

        // Check if pointer denotes a valid element
        if (ptr != nullptr && ptr != gDeletedPtr) {
            // Check if bucket belongs to another element, skip bucket if it does
            if (entry.tableId.load() != table || entry.keyId.load() != key) {
                continue;
            }

            // Entry exists
            return false;
        }

        // Try to claim this bucket by setting the table
        // If this fails somebody else claimed the bucket in the mean time
        uint64_t t = 0x0u;
        if (!entry.tableId.compare_exchange_strong(t, table)) {
            continue;
        }
        entry.keyId.store(key);

        // Check if another concurrent insert conflicts with ours
        // If this fails somebody else is inserting the same key, set pointer to invalid and free bucket
        if (hasInsertConflict(hash, pos, table, key)) {
            entry.ptr.store(gInvalidPtr);
            deleteEntry(entry);
            return false;
        }

        // Try to set the pointer from null or deleted to our data pointer
        // If this fails somebody else set us to invalid, so we have to free bucket
        if (!entry.ptr.compare_exchange_strong(ptr, data)) {
            deleteEntry(entry);
            return false;
        }

        return true;
    }
}

bool OpenAddressingTable::update(uint64_t table, uint64_t key, const void* oldData, void* newData) {
    checkDataKey(table, key);
    checkDataPtr(oldData);
    checkDataPtr(newData);

    return execOnElement(table, key, false, [oldData, newData] (Entry& entry, const void* /* ptr */) {
        // Set the element pointer from old to new
        auto expected = oldData;
        return entry.ptr.compare_exchange_strong(expected, newData);
    });
}

bool OpenAddressingTable::erase(uint64_t table, uint64_t key, const void* oldData) {
    checkDataKey(table, key);
    checkDataPtr(oldData);

    return execOnElement(table, key, true, [oldData] (Entry& entry, const void* /* ptr */) {
        // Try to set the pointer to invalid
        // If this fails then somebody else modified the element
        auto expected = oldData;
        if (!entry.ptr.compare_exchange_strong(expected, gInvalidPtr)) {
            return false;
        }
        deleteEntry(entry);

        return true;
    });
}

void OpenAddressingTable::deleteEntry(Entry& entry) {
    entry.tableId.store(0x0u);
    entry.keyId.store(0x0u);
    entry.ptr.store(gDeletedPtr);
}

uint64_t OpenAddressingTable::calculateHash(uint64_t table, uint64_t key) const {
    auto hash = mTableHash(table);
    boost::hash_combine(hash, mKeyHash(key));
    return hash;
}

bool OpenAddressingTable::hasInsertConflict(size_t hash, size_t insertPos, uint64_t table, uint64_t key) {
    for (auto pos = hash;; ++pos) {
        // Skip our own entry
        if (pos == insertPos) {
            continue;
        }

        auto& entry = mBuckets[pos % mCapacity];
        auto ptr = entry.ptr.load();

        // Check if pointer is invalid, skip bucket if it is
        if (ptr == gInvalidPtr) {
            continue;
        }

        auto t = entry.tableId.load();

        // Check if we reached the end of the overflow bucket and nobody is writing to this bucket
        if (ptr == nullptr && t == 0x0u) {
            LOG_ASSERT(pos > insertPos, "Reached end of overflow before reaching insert element");
            return false;
        }

        // Check if bucket belongs to another element, skip bucket if it does
        if (t != table || entry.keyId.load() != key) {
            continue;
        }

        // Check if the pointer is already set (not null without marker)
        // In this case we have to abort the insert, because another thread already completed the insert
        if ((reinterpret_cast<uintptr_t>(ptr) >> 2) != 0x0u) {
            return true;
        }

        // At this point there is a concurrent insert conflict but both threads did not yet complete the insert
        // We conflict if the element of the other thread is located in a bucket before our own insert bucket
        if (pos < insertPos) {
            return true;
        }

        // The element is located in a bucket after our own insert bucket so we try to set the other pointer to invalid
        // If this fails then the other thread completed its insert operation in the meantime and we have to abort
        if (!entry.ptr.compare_exchange_strong(ptr, gInvalidPtr)) {
            if (ptr != gInvalidPtr) {
                return true;
            }
        }
    }
}

template <typename T, typename F>
T OpenAddressingTable::execOnElement(uint64_t table, uint64_t key, T notFound, F fun) const {
    for (auto pos = calculateHash(table, key);; ++pos) {
        auto& entry = mBuckets[pos % mCapacity];
        auto ptr = entry.ptr.load();

        // Check if pointer is invalid or deleted, skip bucket if it is
        if ((reinterpret_cast<uintptr_t>(ptr) & (0x2u | 0x1u)) != 0) {
            continue;
        }

        auto t = entry.tableId.load();

        // Check if we reached the end of the overflow bucket
        if (ptr == nullptr) {
            // Check if somebody else is currently writing to this bucket, skip bucket if this is the case
            if (t != 0x0u) {
                continue;
            }

            // End of overflow bucket, element not found
            return notFound;
        }

        // Check if bucket belongs to another element, skip bucket if it does
        if (t != table || entry.keyId.load() != key) {
            continue;
        }

        // Element found
        return fun(entry, ptr);
    }
}

template <typename T, typename F>
T OpenAddressingTable::execOnElement(uint64_t table, uint64_t key, T notFound, F fun) {
    return const_cast<const OpenAddressingTable*>(this)->execOnElement(table, key, notFound,
            [&fun] (const Entry& entry, const void* ptr) {
        return fun(const_cast<Entry&>(entry), ptr);
    });
}

} // namespace store
} // namespace tell
<|endoftext|>


<commit_before>#include "graph_node.h"
#include "graph_edge.h"

using namespace v8;

namespace nodex {

Persistent<ObjectTemplate> GraphNode::node_template_;

void GraphNode::Initialize() {
  node_template_ = Persistent<ObjectTemplate>::New(ObjectTemplate::New());
  node_template_->SetInternalFieldCount(1);
  node_template_->SetAccessor(String::New("type"), GraphNode::GetType);
  node_template_->SetAccessor(String::New("name"), GraphNode::GetName);
  node_template_->SetAccessor(String::New("id"), GraphNode::GetId);
  node_template_->SetAccessor(String::New("ptr"), GraphNode::GetPtr);
  node_template_->SetAccessor(String::New("childrenCount"), GraphNode::GetChildrenCount);
  node_template_->SetAccessor(String::New("retainersCount"), GraphNode::GetRetainersCount);
  node_template_->SetAccessor(String::New("size"), GraphNode::GetSize);
  node_template_->SetAccessor(String::New("dominatorNode"), GraphNode::GetDominator);
  node_template_->Set(String::New("getChild"), FunctionTemplate::New(GraphNode::GetChild));
  node_template_->Set(String::New("retainedSize"), FunctionTemplate::New(GraphNode::GetRetainedSize));
  node_template_->Set(String::New("getRetainer"), FunctionTemplate::New(GraphNode::GetRetainer));
}

Handle<Value> GraphNode::GetType(Local<String> property, const AccessorInfo& info) {
  HandleScope scope;
  Local<Object> self = info.Holder();
  void* ptr = self->GetPointerFromInternalField(0);
  int32_t type = static_cast<int32_t>(static_cast<HeapGraphNode*>(ptr)->GetType());
  Local<String> t;
  switch(type) {
    case HeapGraphNode::kArray :
        t = String::New("Array");
        break;
    case HeapGraphNode::kString :
        t = String::New("String");
        break;
    case HeapGraphNode::kObject :
        t = String::New("Object");
        break;
    case HeapGraphNode::kCode :
        t = String::New("Code");
        break;
    case HeapGraphNode::kClosure :
        t = String::New("Closure");
        break;
    case HeapGraphNode::kRegExp :
        t = String::New("RegExp");
        break;
    case HeapGraphNode::kHeapNumber :
        t = String::New("HeapNumber");
        break;
    case HeapGraphNode::kNative :
        t = String::New("Native");
        break;
    default:
        t = String::New("Hidden");
  }
  return scope.Close(t);
}

Handle<Value> GraphNode::GetName(Local<String> property, const AccessorInfo& info) {
  HandleScope scope;
  Local<Object> self = info.Holder();
  void* ptr = self->GetPointerFromInternalField(0);
  Handle<String> title = static_cast<HeapGraphNode*>(ptr)->GetName();
  return scope.Close(title);
}

Handle<Value> GraphNode::GetId(Local<String> property, const AccessorInfo& info) {
  HandleScope scope;
  Local<Object> self = info.Holder();
  void* ptr = self->GetPointerFromInternalField(0);
  uint64_t id = static_cast<HeapGraphNode*>(ptr)->GetId();
  return scope.Close(Integer::NewFromUnsigned(id));
}

Handle<Value> GraphNode::GetPtr(Local<String> property, const AccessorInfo& info) {
  HandleScope scope;
  Local<Object> self = info.Holder();
  void* ptr = self->GetPointerFromInternalField(0);
  uint64_t id = reinterpret_cast<uint64_t>(ptr);
  return scope.Close(Integer::NewFromUnsigned(id));
}

Handle<Value> GraphNode::GetChildrenCount(Local<String> property, const AccessorInfo& info) {
  HandleScope scope;
  Local<Object> self = info.Holder();
  void* ptr = self->GetPointerFromInternalField(0);
  int32_t count = static_cast<HeapGraphNode*>(ptr)->GetChildrenCount();
  return scope.Close(Integer::New(count));
}

Handle<Value> GraphNode::GetRetainersCount(Local<String> property, const AccessorInfo& info) {
  HandleScope scope;
  Local<Object> self = info.Holder();
  void* ptr = self->GetPointerFromInternalField(0);
  int32_t count = static_cast<HeapGraphNode*>(ptr)->GetRetainersCount();
  return scope.Close(Integer::New(count));
}

Handle<Value> GraphNode::GetSize(Local<String> property, const AccessorInfo& info) {
  HandleScope scope;
  Local<Object> self = info.Holder();
  void* ptr = self->GetPointerFromInternalField(0);
  int32_t count = static_cast<HeapGraphNode*>(ptr)->GetSelfSize();
  return scope.Close(Integer::New(count));
}

Handle<Value> GraphNode::GetChild(const Arguments& args) {
  HandleScope scope;
  if (args.Length() < 1) {
    return ThrowException(Exception::Error(String::New("No index specified")));
  } else if (!args[0]->IsInt32()) {
    return ThrowException(Exception::Error(String::New("Argument must be integer")));
  }
  int32_t index = args[0]->Int32Value();
  Handle<Object> self = args.This();
  void* ptr = self->GetPointerFromInternalField(0);
  const HeapGraphEdge* edge = static_cast<HeapGraphNode*>(ptr)->GetChild(index);
  return scope.Close(GraphEdge::New(edge));
}

Handle<Value> GraphNode::GetRetainedSize(const Arguments& args) {
  HandleScope scope;
  Handle<Object> self = args.This();
  void* ptr = self->GetPointerFromInternalField(0);
  int32_t size = static_cast<HeapGraphNode*>(ptr)->GetRetainedSize();
  return scope.Close(Integer::New(size));
}

Handle<Value> GraphNode::GetRetainer(const Arguments& args) {
  HandleScope scope;
  if (args.Length() < 1) {
    return ThrowException(Exception::Error(String::New("No index specified")));
  } else if (!args[0]->IsInt32()) {
    return ThrowException(Exception::Error(String::New("Argument must be integer")));
  }
  int32_t index = args[0]->Int32Value();
  Handle<Object> self = args.This();
  void* ptr = self->GetPointerFromInternalField(0);
  const HeapGraphEdge* edge = static_cast<HeapGraphNode*>(ptr)->GetRetainer(index);
  return scope.Close(GraphEdge::New(edge));
}

Handle<Value> GraphNode::GetDominator(Local<String> property, const AccessorInfo& info) {
  HandleScope scope;
  Local<Object> self = info.Holder();
  void* ptr = self->GetPointerFromInternalField(0);
  const HeapGraphNode* node = static_cast<HeapGraphNode*>(ptr)->GetDominatorNode();
  return scope.Close(GraphNode::New(node));
}

Handle<Value> GraphNode::New(const HeapGraphNode* node) {
  HandleScope scope;

  if (node_template_.IsEmpty()) {
    GraphNode::Initialize();
  }

  if(!node) {
    return Undefined();
  }
  else {
    Local<Object> obj = node_template_->NewInstance();
    obj->SetPointerInInternalField(0, const_cast<HeapGraphNode*>(node));
    return scope.Close(obj);
  }
}
}
<commit_msg>Fixes compilation for node 0.6.x<commit_after>#include "graph_node.h"
#include "graph_edge.h"
#include "node_version.h"

using namespace v8;

namespace nodex {

Persistent<ObjectTemplate> GraphNode::node_template_;

void GraphNode::Initialize() {
  node_template_ = Persistent<ObjectTemplate>::New(ObjectTemplate::New());
  node_template_->SetInternalFieldCount(1);
  node_template_->SetAccessor(String::New("type"), GraphNode::GetType);
  node_template_->SetAccessor(String::New("name"), GraphNode::GetName);
  node_template_->SetAccessor(String::New("id"), GraphNode::GetId);
  node_template_->SetAccessor(String::New("ptr"), GraphNode::GetPtr);
  node_template_->SetAccessor(String::New("childrenCount"), GraphNode::GetChildrenCount);
  node_template_->SetAccessor(String::New("retainersCount"), GraphNode::GetRetainersCount);
  node_template_->SetAccessor(String::New("size"), GraphNode::GetSize);
  node_template_->SetAccessor(String::New("dominatorNode"), GraphNode::GetDominator);
  node_template_->Set(String::New("getChild"), FunctionTemplate::New(GraphNode::GetChild));
  node_template_->Set(String::New("retainedSize"), FunctionTemplate::New(GraphNode::GetRetainedSize));
  node_template_->Set(String::New("getRetainer"), FunctionTemplate::New(GraphNode::GetRetainer));
}

Handle<Value> GraphNode::GetType(Local<String> property, const AccessorInfo& info) {
  HandleScope scope;
  Local<Object> self = info.Holder();
  void* ptr = self->GetPointerFromInternalField(0);
  int32_t type = static_cast<int32_t>(static_cast<HeapGraphNode*>(ptr)->GetType());
  Local<String> t;
  switch(type) {
    case HeapGraphNode::kArray :
        t = String::New("Array");
        break;
    case HeapGraphNode::kString :
        t = String::New("String");
        break;
    case HeapGraphNode::kObject :
        t = String::New("Object");
        break;
    case HeapGraphNode::kCode :
        t = String::New("Code");
        break;
    case HeapGraphNode::kClosure :
        t = String::New("Closure");
        break;
    case HeapGraphNode::kRegExp :
        t = String::New("RegExp");
        break;
    case HeapGraphNode::kHeapNumber :
        t = String::New("HeapNumber");
        break;
    case HeapGraphNode::kNative :
        t = String::New("Native");
        break;
    default:
        t = String::New("Hidden");
  }
  return scope.Close(t);
}

Handle<Value> GraphNode::GetName(Local<String> property, const AccessorInfo& info) {
  HandleScope scope;
  Local<Object> self = info.Holder();
  void* ptr = self->GetPointerFromInternalField(0);
  Handle<String> title = static_cast<HeapGraphNode*>(ptr)->GetName();
  return scope.Close(title);
}

Handle<Value> GraphNode::GetId(Local<String> property, const AccessorInfo& info) {
  HandleScope scope;
  Local<Object> self = info.Holder();
  void* ptr = self->GetPointerFromInternalField(0);
  uint64_t id = static_cast<HeapGraphNode*>(ptr)->GetId();
  return scope.Close(Integer::NewFromUnsigned(id));
}

Handle<Value> GraphNode::GetPtr(Local<String> property, const AccessorInfo& info) {
  HandleScope scope;
  Local<Object> self = info.Holder();
  void* ptr = self->GetPointerFromInternalField(0);
  uint64_t id = reinterpret_cast<uint64_t>(ptr);
  return scope.Close(Integer::NewFromUnsigned(id));
}

Handle<Value> GraphNode::GetChildrenCount(Local<String> property, const AccessorInfo& info) {
  HandleScope scope;
  Local<Object> self = info.Holder();
  void* ptr = self->GetPointerFromInternalField(0);
  int32_t count = static_cast<HeapGraphNode*>(ptr)->GetChildrenCount();
  return scope.Close(Integer::New(count));
}

Handle<Value> GraphNode::GetRetainersCount(Local<String> property, const AccessorInfo& info) {
  HandleScope scope;
  Local<Object> self = info.Holder();
  void* ptr = self->GetPointerFromInternalField(0);
  int32_t count = static_cast<HeapGraphNode*>(ptr)->GetRetainersCount();
  return scope.Close(Integer::New(count));
}

Handle<Value> GraphNode::GetSize(Local<String> property, const AccessorInfo& info) {
  HandleScope scope;
  Local<Object> self = info.Holder();
  void* ptr = self->GetPointerFromInternalField(0);
  int32_t count = static_cast<HeapGraphNode*>(ptr)->GetSelfSize();
  return scope.Close(Integer::New(count));
}

Handle<Value> GraphNode::GetChild(const Arguments& args) {
  HandleScope scope;
  if (args.Length() < 1) {
    return ThrowException(Exception::Error(String::New("No index specified")));
  } else if (!args[0]->IsInt32()) {
    return ThrowException(Exception::Error(String::New("Argument must be integer")));
  }
  int32_t index = args[0]->Int32Value();
  Handle<Object> self = args.This();
  void* ptr = self->GetPointerFromInternalField(0);
  const HeapGraphEdge* edge = static_cast<HeapGraphNode*>(ptr)->GetChild(index);
  return scope.Close(GraphEdge::New(edge));
}

Handle<Value> GraphNode::GetRetainedSize(const Arguments& args) {
  HandleScope scope;

  Handle<Object> self = args.This();
  void* ptr = self->GetPointerFromInternalField(0);

#if NODE_VERSION_AT_LEAST(0, 7, 0)
  int32_t size = static_cast<HeapGraphNode*>(ptr)->GetRetainedSize();
#else
  bool exact = false;
  if (args.Length() > 0) {
    exact = args[0]->BooleanValue();
  }
  int32_t size = static_cast<HeapGraphNode*>(ptr)->GetRetainedSize(exact);
#endif

  return scope.Close(Integer::New(size));
}

Handle<Value> GraphNode::GetRetainer(const Arguments& args) {
  HandleScope scope;
  if (args.Length() < 1) {
    return ThrowException(Exception::Error(String::New("No index specified")));
  } else if (!args[0]->IsInt32()) {
    return ThrowException(Exception::Error(String::New("Argument must be integer")));
  }
  int32_t index = args[0]->Int32Value();
  Handle<Object> self = args.This();
  void* ptr = self->GetPointerFromInternalField(0);
  const HeapGraphEdge* edge = static_cast<HeapGraphNode*>(ptr)->GetRetainer(index);
  return scope.Close(GraphEdge::New(edge));
}

Handle<Value> GraphNode::GetDominator(Local<String> property, const AccessorInfo& info) {
  HandleScope scope;
  Local<Object> self = info.Holder();
  void* ptr = self->GetPointerFromInternalField(0);
  const HeapGraphNode* node = static_cast<HeapGraphNode*>(ptr)->GetDominatorNode();
  return scope.Close(GraphNode::New(node));
}

Handle<Value> GraphNode::New(const HeapGraphNode* node) {
  HandleScope scope;

  if (node_template_.IsEmpty()) {
    GraphNode::Initialize();
  }

  if(!node) {
    return Undefined();
  }
  else {
    Local<Object> obj = node_template_->NewInstance();
    obj->SetPointerInInternalField(0, const_cast<HeapGraphNode*>(node));
    return scope.Close(obj);
  }
}
}
<|endoftext|>


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

#include "RecipeFileParser.h"
#include <memory>
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <locale.h>

static void parseCmdLineArgs(int argc, char** argv, const char*& recipeFilename, const char*& scope);
static void usage();

int main(int argc, char** argv)
{
    auto parser = std::make_unique<RecipeFileParser>();
    const char* recipeFilename;
    const char* scope;
    StringVector recipeScopes;
    StringVector steps;
    StringVector ingredients;

    setlocale(LC_ALL, "");
    parseCmdLineArgs(argc, argv, recipeFilename, scope);

    //--------
    // Parse and error-check a file containing recipes.
    //--------
    try
    {
        parser->parse(recipeFilename, scope);
    }
    catch (const RecipeFileParserException& ex)
    {
        std::cerr << ex.what() << std::endl;
        return 1;
    }

    //--------
    // Print information about the recipes.
    //--------
    parser->listRecipeScopes(recipeScopes);
    const std::size_t len = recipeScopes.size();
    std::cout << "There are " << len << " recipes\n";

    for ( std::size_t i = 0; i < len; ++i )
    {
        const char* name = parser->getRecipeName(recipeScopes[i].c_str());
        parser->getRecipeIngredients(recipeScopes[i].c_str(), ingredients);
        parser->getRecipeSteps(recipeScopes[i].c_str(), steps);
        std::cout << "\nRecipe \"" << name << "\":\n";
        const std::size_t ingredientsLen = ingredients.size();
        std::cout << "\tThis recipe has " << ingredientsLen << " ingredients:\n";

        for (std::size_t i2 = 0; i2 < ingredientsLen; ++i2)
        {
            std::cout << "\t\t\"" << ingredients[i2].c_str() << "\"\n";
        }

        const std::size_t stepsLen = steps.size();
        std::cout << "\tThis recipe has " << stepsLen << " steps:\n";

        for (std::size_t i2 = 0; i2 < stepsLen; ++i2)
        {
            std::cout << "\t\t\"" << steps[i2].c_str() << "%s\"\n";
        }
    }

    return 0;
}

static void parseCmdLineArgs(int argc, char** argv, const char*& recipeFilename, const char*& scope)
{
    int i;

    recipeFilename = "";
    scope = "";

    for (i = 1; i < argc; i++)
    {
        if (strcmp(argv[i], "-h") == 0)
        {
            usage();
        }
        else if (strcmp(argv[i], "-recipes") == 0)
        {
            if (i == argc - 1)
            {
                usage();
            }
            recipeFilename = argv[i + 1];
            i++;
        }
        else if (strcmp(argv[i], "-scope") == 0)
        {
            if (i == argc - 1)
            {
                usage();
            }
            scope = argv[i + 1];
            i++;
        }
        else
        {
            fprintf(stderr, "Unrecognised option '%s'\n\n", argv[i]);
            usage();
        }
    }
    if (strcmp(recipeFilename, "") == 0)
    {
        usage();
    }
}

static void usage()
{
    std::cerr << "\n"
        << "usage: demo <options> -recipes <source>\n"
        << "\n"
        << "The <options> can be:\n"
        << "  -h                Print this usage statement\n"
        << "  -scope            scope within recipes file\n"
        << "A <source> can be one of the following:\n"
        << "  file.cfg          A file\n"
        << "  file#file.cfg     A file\n"
        << "  exec#<command>    Output from executing the specified command\n\n";
    exit(1);
}
<commit_msg>Demo refactored.<commit_after>// Copyright (c) 2017 offa
// Copyright 2011 Ciaran McHale.
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions.
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

#include "RecipeFileParser.h"
#include <memory>
#include <iostream>
#include <tuple>

#include <stdio.h>
#include <stdlib.h>
#include <locale.h>

static std::tuple<std::string, std::string> parseCmdLineArgs(int argc, char** argv);
static void usage();

int main(int argc, char** argv)
{
    auto parser = std::make_unique<RecipeFileParser>();
    StringVector recipeScopes;
    StringVector steps;
    StringVector ingredients;

    setlocale(LC_ALL, "");
    std::string recipeFilename;
    std::string scope;
    std::tie(recipeFilename, scope) = parseCmdLineArgs(argc, argv);

    //--------
    // Parse and error-check a file containing recipes.
    //--------
    try
    {
        parser->parse(recipeFilename.c_str(), scope.c_str());
    }
    catch (const RecipeFileParserException& ex)
    {
        std::cerr << ex.what() << std::endl;
        return 1;
    }

    //--------
    // Print information about the recipes.
    //--------
    parser->listRecipeScopes(recipeScopes);
    const std::size_t len = recipeScopes.size();
    std::cout << "There are " << len << " recipes\n";

    for ( std::size_t i = 0; i < len; ++i )
    {
        const char* name = parser->getRecipeName(recipeScopes[i].c_str());
        parser->getRecipeIngredients(recipeScopes[i].c_str(), ingredients);
        parser->getRecipeSteps(recipeScopes[i].c_str(), steps);
        std::cout << "\nRecipe \"" << name << "\":\n";
        const std::size_t ingredientsLen = ingredients.size();
        std::cout << "\tThis recipe has " << ingredientsLen << " ingredients:\n";

        for (std::size_t i2 = 0; i2 < ingredientsLen; ++i2)
        {
            std::cout << "\t\t\"" << ingredients[i2].c_str() << "\"\n";
        }

        const std::size_t stepsLen = steps.size();
        std::cout << "\tThis recipe has " << stepsLen << " steps:\n";

        for (std::size_t i2 = 0; i2 < stepsLen; ++i2)
        {
            std::cout << "\t\t\"" << steps[i2].c_str() << "%s\"\n";
        }
    }

    return 0;
}

static std::tuple<std::string, std::string> parseCmdLineArgs(int argc, char** argv)
{
    int i;

    std::string recipeFilename = "";
    std::string scope = "";

    for (i = 1; i < argc; i++)
    {
        if (strcmp(argv[i], "-h") == 0)
        {
            usage();
        }
        else if (strcmp(argv[i], "-recipes") == 0)
        {
            if (i == argc - 1)
            {
                usage();
            }
            recipeFilename = argv[i + 1];
            i++;
        }
        else if (strcmp(argv[i], "-scope") == 0)
        {
            if (i == argc - 1)
            {
                usage();
            }
            scope = argv[i + 1];
            i++;
        }
        else
        {
            fprintf(stderr, "Unrecognised option '%s'\n\n", argv[i]);
            usage();
        }
    }

    if (recipeFilename.empty() == true )
    {
        usage();
    }

    return std::make_tuple(recipeFilename, scope);
}

static void usage()
{
    std::cerr << "\n"
        << "usage: demo <options> -recipes <source>\n"
        << "\n"
        << "The <options> can be:\n"
        << "  -h                Print this usage statement\n"
        << "  -scope            scope within recipes file\n"
        << "A <source> can be one of the following:\n"
        << "  file.cfg          A file\n"
        << "  file#file.cfg     A file\n"
        << "  exec#<command>    Output from executing the specified command\n\n";
    exit(1);
}
<|endoftext|>


<commit_before>/***************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (directui@nokia.com)
**
** This file is part of mcompositor.
**
** If you have questions regarding the use of this file, please contact
** Nokia at directui@nokia.com.
**
** This library is free software; you can redistribute it and/or
** modify it under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation
** and appearing in the file LICENSE.LGPL included in the packaging
** of this file.
**
****************************************************************************/

/*!
  \class MCompositeWindowShaderEffect
  \brief MCompositeWindowShaderEffect is the base class for shader effects on windows

  Shader effects can change the appearance of composited windows by hooking
  into the rendering pipeline of the compositor. It allows manipulation
  of how a composited window is rendered by using custom GLSL fragment shaders
  and direct access to the texture rendering function.
  An effect can be disabled by calling setEnabled(false). If effects are
  disabled, the window texture is rendered directly.

  To add special effects to composited windows, subclass MCompositeWindowShaderEffect
  and reimplement the pure virtual function drawTexture()
*/

#include "mtexturepixmapitem.h"
#include "mcompositewindowshadereffect.h"
#include "mtexturepixmapitem_p.h"
#include <QByteArray>

static const char default_frag[] = "\
    lowp vec4 customShader(lowp sampler2D imageTexture, highp vec2 textureCoords) { \
        return texture2D(imageTexture, textureCoords); \
    }\n";

MCompositeWindowShaderEffectPrivate::MCompositeWindowShaderEffectPrivate(MCompositeWindowShaderEffect* e)
    :effect(e),
     priv_render(0),
     active_fragment(0)
{
}

void MCompositeWindowShaderEffectPrivate::drawTexture(MTexturePixmapPrivate* render, const QTransform &transform, const QRectF &drawRect, qreal opacity)
{
    priv_render = render;
    effect->drawTexture(transform, drawRect, opacity);
    enabled = false;
}

/*!
 * Creates a window effect object
 */
MCompositeWindowShaderEffect::MCompositeWindowShaderEffect(QObject* parent)
    :QObject(parent),
     d(new MCompositeWindowShaderEffectPrivate(this))
{
    // install default pixel shader
    QByteArray code = default_frag;
    d->active_fragment = installShaderFragment(code);
}

/*!
  Destroys the graphics effect and deletes GLSL fragment programs from
  the compositor's rendering engine if any are installed from this effect
*/
MCompositeWindowShaderEffect::~MCompositeWindowShaderEffect()
{
}

/*!
  Adds and installs the source code for a pixel shader fragment to \a code.

  The \a code must define a GLSL function with the signature
  \c{lowp vec4 customShader(lowp sampler2D imageTexture, highp vec2 textureCoords)}
  that returns the source pixel value to use in the paint engine's
  shader program.  The following is the default pixel shader fragment,
  which draws a texture with no effect applied:

  \code
  lowp vec4 customShader(lowp sampler2D imageTexture, highp vec2 textureCoords)
  {
      return texture2D(imageTexture, textureCoords);
  }
  \endcode

  \return The id of the fragment shader. If the fragment shader is invalid,
  return 0.

  \sa setUniforms()
*/
GLuint MCompositeWindowShaderEffect::installShaderFragment(const QByteArray& code)
{
    GLuint id = MTexturePixmapPrivate::installPixelShader(code);
    d->pixfrag_ids.push_back(id);
    return id;
}

 /*!
   \return Texture id of the currently rendered window
 */
GLuint MCompositeWindowShaderEffect::texture() const
{
    // TODO: This assumes we have always have hadware TFP support
    if (d->priv_render)
        return d->priv_render->textureId;
    return 0;
}

const QVector<GLuint>& MCompositeWindowShaderEffect::fragmentIds() const
{
    return d->pixfrag_ids;
}

/*!
  Sets the rendering pipeline to use shader fragment specified by \a id
*/
void MCompositeWindowShaderEffect::setActiveShaderFragment(GLuint id)
{
    d->active_fragment = id;
}

/*!
  \return The id of the currently active shader fragment
*/
GLuint MCompositeWindowShaderEffect::activeShaderFragment() const
{
    return d->active_fragment;
}

/*!
  \fn void MCompositeWindowShaderEffect::enabledChanged( bool enabled);
  Emmitted if this effect gets disabled or enabled
*/

/*!
  \fn virtual void MCompositeWindowShaderEffect::drawTexture(const QTransform &transform, const QRectF &drawRect, qreal opacity) = 0;

  This pure virtual function is called whenever the windows texture is
  rendered. Reimplement it to completely customize how the texture of this
  window is rendered using the given transformation
  matrix \a transform, texture geometry \a drawRect, and \a opacity.
*/

/*!
  Draws currently bound source window texture. Specify a transformation matrix to
  \a transform and texture geometry to \a drawRect. Opacity can be set
  by specifying \a opacity (0.0 - 1.0).
  This function should only be called inside drawTexture()
*/
void MCompositeWindowShaderEffect::drawSource(const QTransform &transform,
                                              const QRectF &drawRect,
                                              qreal opacity)
{
    if (d->priv_render)
        d->priv_render->q_drawTexture(transform, drawRect, opacity);
}

/*!
  Install this effect on a composite window object \a window. Note that
  we override QGraphicsItem::setGraphicsEffect() because
  we have a completely different painting engine.
  If a window has a previous effect, it will be overriden by the new one
*/
void MCompositeWindowShaderEffect::installEffect(MCompositeWindow* window)
{
    // only happens with GL. sorry n800 guys :p
#ifdef QT_OPENGL_LIB
    MTexturePixmapItem* item = (MTexturePixmapItem*) window;
    item->d->installEffect(this);
#endif
}

/*!
  \return Whether this effect is enabled or not
*/
bool MCompositeWindowShaderEffect::enabled() const
{
    return d->enabled;
}

/*!
  Enable or disable this effect
*/
void MCompositeWindowShaderEffect::setEnabled(bool enabled)
{
    d->enabled = enabled;
    emit enabledChanged(enabled);
}

/*!
  Set the uniform values on the currently active shader \a program.
  Default implementation does nothing. Reimplement this function to
  set values if you specified a custom pixel shader in your effects.
*/
void MCompositeWindowShaderEffect::setUniforms(QGLShaderProgram* program)
{
    Q_UNUSED(program);
}

<commit_msg>Changes: Fix crash on fake object tests RevBy: TrustMe<commit_after>/***************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (directui@nokia.com)
**
** This file is part of mcompositor.
**
** If you have questions regarding the use of this file, please contact
** Nokia at directui@nokia.com.
**
** This library is free software; you can redistribute it and/or
** modify it under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation
** and appearing in the file LICENSE.LGPL included in the packaging
** of this file.
**
****************************************************************************/

/*!
  \class MCompositeWindowShaderEffect
  \brief MCompositeWindowShaderEffect is the base class for shader effects on windows

  Shader effects can change the appearance of composited windows by hooking
  into the rendering pipeline of the compositor. It allows manipulation
  of how a composited window is rendered by using custom GLSL fragment shaders
  and direct access to the texture rendering function.
  An effect can be disabled by calling setEnabled(false). If effects are
  disabled, the window texture is rendered directly.

  To add special effects to composited windows, subclass MCompositeWindowShaderEffect
  and reimplement the pure virtual function drawTexture()
*/

#include "mtexturepixmapitem.h"
#include "mcompositewindowshadereffect.h"
#include "mtexturepixmapitem_p.h"
#include <QByteArray>

static const char default_frag[] = "\
    lowp vec4 customShader(lowp sampler2D imageTexture, highp vec2 textureCoords) { \
        return texture2D(imageTexture, textureCoords); \
    }\n";

MCompositeWindowShaderEffectPrivate::MCompositeWindowShaderEffectPrivate(MCompositeWindowShaderEffect* e)
    :effect(e),
     priv_render(0),
     active_fragment(0)
{
}

void MCompositeWindowShaderEffectPrivate::drawTexture(MTexturePixmapPrivate* render, const QTransform &transform, const QRectF &drawRect, qreal opacity)
{
    priv_render = render;
    effect->drawTexture(transform, drawRect, opacity);
    enabled = false;
}

/*!
 * Creates a window effect object
 */
MCompositeWindowShaderEffect::MCompositeWindowShaderEffect(QObject* parent)
    :QObject(parent),
     d(new MCompositeWindowShaderEffectPrivate(this))
{
    // install default pixel shader
    QByteArray code = default_frag;
    d->active_fragment = installShaderFragment(code);
}

/*!
  Destroys the graphics effect and deletes GLSL fragment programs from
  the compositor's rendering engine if any are installed from this effect
*/
MCompositeWindowShaderEffect::~MCompositeWindowShaderEffect()
{
}

/*!
  Adds and installs the source code for a pixel shader fragment to \a code.

  The \a code must define a GLSL function with the signature
  \c{lowp vec4 customShader(lowp sampler2D imageTexture, highp vec2 textureCoords)}
  that returns the source pixel value to use in the paint engine's
  shader program.  The following is the default pixel shader fragment,
  which draws a texture with no effect applied:

  \code
  lowp vec4 customShader(lowp sampler2D imageTexture, highp vec2 textureCoords)
  {
      return texture2D(imageTexture, textureCoords);
  }
  \endcode

  \return The id of the fragment shader. If the fragment shader is invalid,
  return 0.

  \sa setUniforms()
*/
GLuint MCompositeWindowShaderEffect::installShaderFragment(const QByteArray& code)
{
    GLuint id = MTexturePixmapPrivate::installPixelShader(code);
    d->pixfrag_ids.push_back(id);
    return id;
}

 /*!
   \return Texture id of the currently rendered window
 */
GLuint MCompositeWindowShaderEffect::texture() const
{
    // TODO: This assumes we have always have hadware TFP support
    if (d->priv_render)
        return d->priv_render->textureId;
    return 0;
}

const QVector<GLuint>& MCompositeWindowShaderEffect::fragmentIds() const
{
    return d->pixfrag_ids;
}

/*!
  Sets the rendering pipeline to use shader fragment specified by \a id
*/
void MCompositeWindowShaderEffect::setActiveShaderFragment(GLuint id)
{
    d->active_fragment = id;
}

/*!
  \return The id of the currently active shader fragment
*/
GLuint MCompositeWindowShaderEffect::activeShaderFragment() const
{
    return d->active_fragment;
}

/*!
  \fn void MCompositeWindowShaderEffect::enabledChanged( bool enabled);
  Emmitted if this effect gets disabled or enabled
*/

/*!
  \fn virtual void MCompositeWindowShaderEffect::drawTexture(const QTransform &transform, const QRectF &drawRect, qreal opacity) = 0;

  This pure virtual function is called whenever the windows texture is
  rendered. Reimplement it to completely customize how the texture of this
  window is rendered using the given transformation
  matrix \a transform, texture geometry \a drawRect, and \a opacity.
*/

/*!
  Draws currently bound source window texture. Specify a transformation matrix to
  \a transform and texture geometry to \a drawRect. Opacity can be set
  by specifying \a opacity (0.0 - 1.0).
  This function should only be called inside drawTexture()
*/
void MCompositeWindowShaderEffect::drawSource(const QTransform &transform,
                                              const QRectF &drawRect,
                                              qreal opacity)
{
    if (d->priv_render)
        d->priv_render->q_drawTexture(transform, drawRect, opacity);
}

/*!
  Install this effect on a composite window object \a window. Note that
  we override QGraphicsItem::setGraphicsEffect() because
  we have a completely different painting engine.
  If a window has a previous effect, it will be overriden by the new one
*/
void MCompositeWindowShaderEffect::installEffect(MCompositeWindow* window)
{
    if (!window->isValid())
        return;

    // only happens with GL. sorry n800 guys :p
#ifdef QT_OPENGL_LIB
    MTexturePixmapItem* item = (MTexturePixmapItem*) window;
    item->d->installEffect(this);
#endif
}

/*!
  \return Whether this effect is enabled or not
*/
bool MCompositeWindowShaderEffect::enabled() const
{
    return d->enabled;
}

/*!
  Enable or disable this effect
*/
void MCompositeWindowShaderEffect::setEnabled(bool enabled)
{
    d->enabled = enabled;
    emit enabledChanged(enabled);
}

/*!
  Set the uniform values on the currently active shader \a program.
  Default implementation does nothing. Reimplement this function to
  set values if you specified a custom pixel shader in your effects.
*/
void MCompositeWindowShaderEffect::setUniforms(QGLShaderProgram* program)
{
    Q_UNUSED(program);
}

<|endoftext|>


<commit_before>#include <nan.h>
#include <node.h>
#include <stdio.h>

#include <memory>
#include <string>
#include <vector>

#include "argon2/src/argon2.h"

namespace {

const auto ENCODED_LEN = 108u;
const auto HASH_LEN = 32u;
const auto SALT_LEN = 16u;

class EncryptAsyncWorker : public Nan::AsyncWorker {
public:
    EncryptAsyncWorker(Nan::Callback* callback,
        const std::string& plain, const std::string& salt);

    void Execute();

    void HandleOKCallback();

private:
    std::string plain;
    std::string salt;
    std::string error;
    std::string output;
};

EncryptAsyncWorker::EncryptAsyncWorker(Nan::Callback* callback,
    const std::string& plain, const std::string& salt) :
    Nan::AsyncWorker(callback), plain{plain},
    salt{salt}, error{}, output{}
{
    if (salt.size() < SALT_LEN) {
        this->salt.resize(SALT_LEN, 0x0);
    }
}

void EncryptAsyncWorker::Execute()
{
    char encoded[ENCODED_LEN];

    auto result = argon2i_hash_encoded(3, 4096, 1, plain.c_str(), plain.size(),
        salt.c_str(), salt.size(), HASH_LEN, encoded, ENCODED_LEN);
    if (result != ARGON2_OK) {
        return;
    }

    output = std::string{encoded};
}

void EncryptAsyncWorker::HandleOKCallback()
{
    using v8::Local;
    using v8::Value;

    Nan::HandleScope scope;

    Local <Value> argv[2];
    argv[0] = Nan::Undefined();
    argv[1] = Nan::Encode(output.c_str(), output.size(), Nan::BINARY);

    callback->Call(2, argv);
}

NAN_METHOD(Encrypt) {
    using v8::Function;
    using v8::Local;

    Nan::HandleScope scope;

    if (info.Length() < 3) {
        Nan::ThrowTypeError("3 arguments expected");
        return;
    }

    Nan::Utf8String plain{info[0]->ToString()};
    Nan::Utf8String salt{info[1]->ToString()};
    Local<Function> callback = Local<Function>::Cast(info[2]);

    auto worker = new EncryptAsyncWorker(new Nan::Callback(callback), *plain, *salt);

    Nan::AsyncQueueWorker(worker);
}

class VerifyAsyncWorker : public Nan::AsyncWorker {
public:
    VerifyAsyncWorker(Nan::Callback* callback,
        const std::string& encrypted, const std::string& plain);

    void Execute();

private:
    std::string encrypted;
    std::string plain;
    std::string error;
    bool output;
};

VerifyAsyncWorker::VerifyAsyncWorker(Nan::Callback* callback,
    const std::string& encrypted, const std::string& plain) :
    Nan::AsyncWorker(callback), encrypted{encrypted}, plain{plain},
    error{}, output{}
{ }

void VerifyAsyncWorker::Execute()
{
    auto result = argon2i_verify(encrypted.c_str(), plain.c_str(),
        plain.size());

    if (result != ARGON2_OK) {
        SetErrorMessage("The password did not match.");
    }
}

NAN_METHOD(Verify) {
    using v8::Function;
    using v8::Local;

    Nan::HandleScope scope;

    if (info.Length() < 3) {
        Nan::ThrowTypeError("3 arguments expected");
        return;
    }

    Nan::Utf8String encrypted{ info[0]->ToString() };
    Nan::Utf8String plain{ info[1]->ToString() };
    Local<Function> callback = Local<Function>::Cast(info[2]);

    auto worker = new VerifyAsyncWorker(new Nan::Callback(callback),
    *encrypted, *plain);

    Nan::AsyncQueueWorker(worker);
}

}

NAN_MODULE_INIT(init) {
    Nan::Export(target, "encrypt", Encrypt);
    Nan::Export(target, "verify", Verify);
};

NODE_MODULE(argon2_lib, init);
<commit_msg>Fix includes<commit_after>#include <nan.h>
#include <node.h>

#include <cstring>
#include <string>

#include "argon2/src/argon2.h"

namespace {

const auto ENCODED_LEN = 108u;
const auto HASH_LEN = 32u;
const auto SALT_LEN = 16u;

class EncryptAsyncWorker : public Nan::AsyncWorker {
public:
    EncryptAsyncWorker(Nan::Callback* callback,
        const std::string& plain, const std::string& salt);

    void Execute();

    void HandleOKCallback();

private:
    std::string plain;
    std::string salt;
    std::string error;
    std::string output;
};

EncryptAsyncWorker::EncryptAsyncWorker(Nan::Callback* callback,
    const std::string& plain, const std::string& salt) :
    Nan::AsyncWorker(callback), plain{plain},
    salt{salt}, error{}, output{}
{
    if (salt.size() < SALT_LEN) {
        this->salt.resize(SALT_LEN, 0x0);
    }
}

void EncryptAsyncWorker::Execute()
{
    char encoded[ENCODED_LEN];

    auto result = argon2i_hash_encoded(3, 4096, 1, plain.c_str(), plain.size(),
        salt.c_str(), salt.size(), HASH_LEN, encoded, ENCODED_LEN);
    if (result != ARGON2_OK) {
        return;
    }

    output = std::string{encoded};
}

void EncryptAsyncWorker::HandleOKCallback()
{
    using v8::Local;
    using v8::Value;

    Nan::HandleScope scope;

    Local <Value> argv[2];
    argv[0] = Nan::Undefined();
    argv[1] = Nan::Encode(output.c_str(), output.size(), Nan::BINARY);

    callback->Call(2, argv);
}

NAN_METHOD(Encrypt) {
    using v8::Function;
    using v8::Local;

    Nan::HandleScope scope;

    if (info.Length() < 3) {
        Nan::ThrowTypeError("3 arguments expected");
        return;
    }

    Nan::Utf8String plain{info[0]->ToString()};
    Nan::Utf8String salt{info[1]->ToString()};
    Local<Function> callback = Local<Function>::Cast(info[2]);

    auto worker = new EncryptAsyncWorker(new Nan::Callback(callback), *plain, *salt);

    Nan::AsyncQueueWorker(worker);
}

class VerifyAsyncWorker : public Nan::AsyncWorker {
public:
    VerifyAsyncWorker(Nan::Callback* callback,
        const std::string& encrypted, const std::string& plain);

    void Execute();

private:
    std::string encrypted;
    std::string plain;
    std::string error;
    bool output;
};

VerifyAsyncWorker::VerifyAsyncWorker(Nan::Callback* callback,
    const std::string& encrypted, const std::string& plain) :
    Nan::AsyncWorker(callback), encrypted{encrypted}, plain{plain},
    error{}, output{}
{ }

void VerifyAsyncWorker::Execute()
{
    auto result = argon2i_verify(encrypted.c_str(), plain.c_str(),
        plain.size());

    if (result != ARGON2_OK) {
        SetErrorMessage("The password did not match.");
    }
}

NAN_METHOD(Verify) {
    using v8::Function;
    using v8::Local;

    Nan::HandleScope scope;

    if (info.Length() < 3) {
        Nan::ThrowTypeError("3 arguments expected");
        return;
    }

    Nan::Utf8String encrypted{ info[0]->ToString() };
    Nan::Utf8String plain{ info[1]->ToString() };
    Local<Function> callback = Local<Function>::Cast(info[2]);

    auto worker = new VerifyAsyncWorker(new Nan::Callback(callback),
    *encrypted, *plain);

    Nan::AsyncQueueWorker(worker);
}

}

NAN_MODULE_INIT(init) {
    Nan::Export(target, "encrypt", Encrypt);
    Nan::Export(target, "verify", Verify);
};

NODE_MODULE(argon2_lib, init);
<|endoftext|>