<commit_before>#include <irrlicht.h>
#include <string>
#include <ctime>
#include <vector>
#include <boost/filesystem.hpp>

#include "globs.h"
#include "map.h"

#ifdef _IRR_WINDOWS_
#pragma comment(lib, "Irrlicht.lib")
#pragma comment(linker, "/subsystem:windows /ENTRY:mainCRTStartup")
#include <windows.h>
#define Pass(ms) Sleep(ms)
#else
#include <unistd.h>
#define Pass(ms) usleep(ms*1000)
#endif

#define FPS 68.0

using namespace irr;
using core::vector3df;
using video::SColor;
using core::rect;

EventReceiver receiver;
ConfigFile UserConfig;

video::IVideoDriver* driver;
scene::ISceneManager* smgr;

// I couldn't resist, alright? :D
void bork(std::string msg) {
#ifndef BE_POLITE
	printf("SHIT! %s!\n", msg.c_str());
#else
	printf("%s, aborting.\n", msg.c_str());
#endif
	exit(-1);
}

IrrlichtDevice *setupDevice(EventReceiver &receiver, ConfigFile *UserConfig) {
	SIrrlichtCreationParameters params = SIrrlichtCreationParameters();
	if (IrrlichtDevice::isDriverSupported(video::EDT_OPENGL)) {
		params.DriverType = video::EDT_OPENGL;
	}
	else if (IrrlichtDevice::isDriverSupported(video::EDT_DIRECT3D9)) {
		params.DriverType = video::EDT_DIRECT3D9;
	}
	else if (IrrlichtDevice::isDriverSupported(video::EDT_DIRECT3D8)) {
		params.DriverType = video::EDT_DIRECT3D8;
	}
	else {
		printf("No suitable video driver found.\n");
		return NULL;
	}

	params.WindowSize = core::dimension2d<u32>(UserConfig->read<int>("display.width", 800), UserConfig->read<int>("display.height", 600));
	params.Bits = 32;
	params.Fullscreen = UserConfig->read<bool>("display.fullscreen", false);
	params.Stencilbuffer = false;
	params.Doublebuffer = true;
	params.Vsync = true;
	params.EventReceiver = &receiver;
	return createDeviceEx(params);
}

struct controls {
	EKEY_CODE cam_up;
	EKEY_CODE cam_down;
	EKEY_CODE cam_left;
	EKEY_CODE cam_right;
	EKEY_CODE cam_raise;
	EKEY_CODE cam_lower;
};

std::string get_userdata_path() {
#ifdef __unix
	string result ( getenv("HOME") );
	result += "/.IrrRR/"; // TODO: Is this ok?
#else // __unix
#ifdef __WIN32__
	string result ( getenv("APPDATA") );
	result += "\\IrrRR\\";
#endif // __WIN32__
#endif // __unix
	return result;
}

int main() {
	try {
		UserConfig = ConfigFile(get_userdata_path() + "user.cfg");
	}
	catch (ConfigFile::file_not_found) {
		printf("No user config file found, creating...\n");
		boost::filesystem::create_directories(get_userdata_path());
		FILE *f;
		f = fopen((get_userdata_path() + "user.cfg").c_str(), "w");
		if (f == NULL) {
			printf("Could not create user config file. Aborting. Please check that the path to the user config file is available: %s", (get_userdata_path() + "user.cfg").c_str());
			exit(-1);
		}
		fclose(f);
		UserConfig = ConfigFile(get_userdata_path() + "user.cfg");
	}

	IrrlichtDevice *device = setupDevice(receiver, &UserConfig);
	if (!device) {
		printf("Could not create device.\n");
	}

	device->setWindowCaption(L"IrrRR");

	driver = device->getVideoDriver();
	smgr = device->getSceneManager();
	env = device->getGUIEnvironment();
	scene::ISceneCollisionManager* collMan = smgr->getSceneCollisionManager();

/* Set up GUI */
	gui::IGUISkin* skin = env->getSkin();
	setup_GUI();

/* Load controls */

	controls userControls;

	userControls.cam_up = (EKEY_CODE) UserConfig.read<int>("keys.camera_up", KEY_KEY_W);
	userControls.cam_down = (EKEY_CODE) UserConfig.read<int>("keys.camera_down", KEY_KEY_S);
	userControls.cam_left = (EKEY_CODE) UserConfig.read<int>("keys.camera_left", KEY_KEY_A);
	userControls.cam_right = (EKEY_CODE) UserConfig.read<int>("keys.camera_right", KEY_KEY_D);
	userControls.cam_raise = (EKEY_CODE) UserConfig.read<int>("keys.camera_raise", KEY_KEY_Q);
	userControls.cam_lower = (EKEY_CODE) UserConfig.read<int>("keys.camera_lower", KEY_KEY_E);

/* Set up camera */

	scene::ICameraSceneNode *cam = smgr->addCameraSceneNode(0, vector3df(0, 10, -2), vector3df(0, 0, 0));
//	scene::ICameraSceneNode *blehcam = smgr->addCameraSceneNode(0, vector3df(0, 50, -2), vector3df(0, 0, 0));
	cam->setPosition(core::vector3df(-5,18,0));
	cam->setTarget(core::vector3df(0,0,0));
	cam->setFarValue(42000.0f);

	vector3df camMove(0, 0, 0);
	vector3df camPos = cam->getPosition();
	vector3df camTarget = cam->getTarget();

/* Map */
	FILE *mapfile;
	mapfile = fopen("data/maps/test.map", "rb");
	if (mapfile == NULL) {
		bork("Could not open test map");
	}
	Map *map = new Map;
	map->load(mapfile);
	fclose(mapfile);

/* Set up lighting */
/*	std::vector<scene::ILightSceneNode*> lights;

#define asdf 3
#define asdfg asdf/2
	for (int i = 0; i<8; i++) {
		vector3df pos (
			(float)((i & 1) != 0)*asdf-asdfg,
			(float)((i & 2) != 0)*asdf-asdfg,
			(float)((i & 4) != 0)*asdf-asdfg
		);
		lights.push_back(smgr->addLightSceneNode(cam, pos));
	}*/
	smgr->setAmbientLight(SColor(0x000000));
	scene::ILightSceneNode *light = smgr->addLightSceneNode(cam);

/* Set up skybox */

	const io::path skyboxFilename ("data/textures/skybox/top.png");
	video::ITexture *sb_tex = driver->getTexture(skyboxFilename);
	smgr->addSkyBoxSceneNode(sb_tex, sb_tex, sb_tex, sb_tex, sb_tex, sb_tex);

/* T-Minus ten! */
	ITimer* timer = device->getTimer();
	timer->setTime(0);
	unsigned int now = 0;
	unsigned int lastUpdate = 0;
	int frame = 0;
	vector3df mousething;
	scene::IMesh *arrowMesh = smgr->addArrowMesh("ITSANARROW", 0xFFFFFF, 0xFF0000);
	scene::IMeshSceneNode *mouseNode = smgr->addMeshSceneNode(arrowMesh, 0);
//	scene::IMeshSceneNode *camPoint = smgr->addMeshSceneNode(arrowMesh, cam);
	mouseNode->setRotation(vector3df(0, 0, 180));
//	camPoint->setRotation(vector3df(0,0,180));

	core::line3df ray;
	scene::ISceneNode *dummyNode;
	core::triangle3df dummyTri;
/* We have liftoff! */
	while (device->run()) {
		now = timer->getTime();
		if (now >= lastUpdate + 1000.0/FPS) {
			frame++;
			lastUpdate = now;
			driver->beginScene(true, true, SColor(255, 0, 0, 0));

			smgr->drawAll();
			env->drawAll();
			driver->draw3DLine(cam->getAbsolutePosition(), vector3df(0,0,0), 0x0000ff);
			driver->draw3DLine(cam->getAbsolutePosition(), ray.start, 0xff0000);
			driver->draw3DLine(ray.end, vector3df(0,0,0), 0x00ff00);

			driver->endScene();

			camMove.set(0, 0, 0);
			if (receiver.IsKeyPressed(userControls.cam_up)) {
				camMove.X = 0.1;
			}
			if (receiver.IsKeyPressed(userControls.cam_down)) {
				camMove.X = -0.1;
			}
			if (receiver.IsKeyPressed(userControls.cam_left)) {
				camMove.Z = 0.1;
			}
			if (receiver.IsKeyPressed(userControls.cam_right)) {
				camMove.Z = -0.1;
			}
			if (receiver.IsKeyPressed(userControls.cam_raise)) {
				camMove.Y = 0.1;
			}
			if (receiver.IsKeyPressed(userControls.cam_lower)) {
				camMove.Y = -0.1;
			}
			camPos = cam->getPosition();
			camTarget = cam->getTarget();
			camPos += camMove;
			camMove.Y = 0;
			camTarget += camMove;
			cam->setPosition(camPos);
			cam->setTarget(camTarget);

			ray = collMan->getRayFromScreenCoordinates(receiver.MousePosition, cam);
			ray.start = cam->getAbsolutePosition();
			if (collMan->getSceneNodeAndCollisionPointFromRay(ray, mousething, dummyTri)) {
				mouseNode->setPosition(mousething);
			}

			if(receiver.IsKeyPressed(KEY_ESCAPE)) break;
			if(frame % 100 == 0) printf("%i FPS\n", driver->getFPS());
		}
		else {
			Pass(10);
		}
	}
	device->drop();
	return 0;
}
<commit_msg>Totally messed up the lighting :)<commit_after>#include <irrlicht.h>
#include <string>
#include <ctime>
#include <vector>
#include <boost/filesystem.hpp>

#include "globs.h"
#include "map.h"

#ifdef _IRR_WINDOWS_
#pragma comment(lib, "Irrlicht.lib")
#pragma comment(linker, "/subsystem:windows /ENTRY:mainCRTStartup")
#include <windows.h>
#define Pass(ms) Sleep(ms)
#else
#include <unistd.h>
#define Pass(ms) usleep(ms*1000)
#endif

#define FPS 68.0

using namespace irr;
using core::vector3df;
using video::SColor;
using core::rect;

EventReceiver receiver;
ConfigFile UserConfig;

video::IVideoDriver* driver;
scene::ISceneManager* smgr;

// I couldn't resist, alright? :D
void bork(std::string msg) {
#ifndef BE_POLITE
	printf("SHIT! %s!\n", msg.c_str());
#else
	printf("%s, aborting.\n", msg.c_str());
#endif
	exit(-1);
}

IrrlichtDevice *setupDevice(EventReceiver &receiver, ConfigFile *UserConfig) {
	SIrrlichtCreationParameters params = SIrrlichtCreationParameters();
	if (IrrlichtDevice::isDriverSupported(video::EDT_OPENGL)) {
		params.DriverType = video::EDT_OPENGL;
	}
	else if (IrrlichtDevice::isDriverSupported(video::EDT_DIRECT3D9)) {
		params.DriverType = video::EDT_DIRECT3D9;
	}
	else if (IrrlichtDevice::isDriverSupported(video::EDT_DIRECT3D8)) {
		params.DriverType = video::EDT_DIRECT3D8;
	}
	else {
		printf("No suitable video driver found.\n");
		return NULL;
	}

	params.WindowSize = core::dimension2d<u32>(UserConfig->read<int>("display.width", 800), UserConfig->read<int>("display.height", 600));
	params.Bits = 32;
	params.Fullscreen = UserConfig->read<bool>("display.fullscreen", false);
	params.Stencilbuffer = false;
	params.Doublebuffer = true;
	params.Vsync = true;
	params.EventReceiver = &receiver;
	return createDeviceEx(params);
}

struct controls {
	EKEY_CODE cam_up;
	EKEY_CODE cam_down;
	EKEY_CODE cam_left;
	EKEY_CODE cam_right;
	EKEY_CODE cam_raise;
	EKEY_CODE cam_lower;
};

std::string get_userdata_path() {
#ifdef __unix
	string result ( getenv("HOME") );
	result += "/.IrrRR/"; // TODO: Is this ok?
#else // __unix
#ifdef __WIN32__
	string result ( getenv("APPDATA") );
	result += "\\IrrRR\\";
#endif // __WIN32__
#endif // __unix
	return result;
}

int main() {
	try {
		UserConfig = ConfigFile(get_userdata_path() + "user.cfg");
	}
	catch (ConfigFile::file_not_found) {
		printf("No user config file found, creating...\n");
		boost::filesystem::create_directories(get_userdata_path());
		FILE *f;
		f = fopen((get_userdata_path() + "user.cfg").c_str(), "w");
		if (f == NULL) {
			printf("Could not create user config file. Aborting. Please check that the path to the user config file is available: %s", (get_userdata_path() + "user.cfg").c_str());
			exit(-1);
		}
		fclose(f);
		UserConfig = ConfigFile(get_userdata_path() + "user.cfg");
	}

	IrrlichtDevice *device = setupDevice(receiver, &UserConfig);
	if (!device) {
		printf("Could not create device.\n");
	}

	device->setWindowCaption(L"IrrRR");

	driver = device->getVideoDriver();
	smgr = device->getSceneManager();
	env = device->getGUIEnvironment();
	scene::ISceneCollisionManager* collMan = smgr->getSceneCollisionManager();

/* Set up GUI */
	gui::IGUISkin* skin = env->getSkin();
	setup_GUI();

/* Load controls */

	controls userControls;

	userControls.cam_up = (EKEY_CODE) UserConfig.read<int>("keys.camera_up", KEY_KEY_W);
	userControls.cam_down = (EKEY_CODE) UserConfig.read<int>("keys.camera_down", KEY_KEY_S);
	userControls.cam_left = (EKEY_CODE) UserConfig.read<int>("keys.camera_left", KEY_KEY_A);
	userControls.cam_right = (EKEY_CODE) UserConfig.read<int>("keys.camera_right", KEY_KEY_D);
	userControls.cam_raise = (EKEY_CODE) UserConfig.read<int>("keys.camera_raise", KEY_KEY_Q);
	userControls.cam_lower = (EKEY_CODE) UserConfig.read<int>("keys.camera_lower", KEY_KEY_E);

/* Set up camera */

	scene::ICameraSceneNode *cam = smgr->addCameraSceneNode(0, vector3df(0, 10, -2), vector3df(0, 0, 0));
//	scene::ICameraSceneNode *blehcam = smgr->addCameraSceneNode(0, vector3df(0, 50, -2), vector3df(0, 0, 0));
	cam->setPosition(core::vector3df(-5,18,0));
	cam->setTarget(core::vector3df(0,0,0));
	cam->setFarValue(42000.0f);

	vector3df camMove(0, 0, 0);
	vector3df camPos = cam->getPosition();
	vector3df camTarget = cam->getTarget();

/* Map */
	FILE *mapfile;
	mapfile = fopen("data/maps/test.map", "rb");
	if (mapfile == NULL) {
		bork("Could not open test map");
	}
	Map *map = new Map;
	map->load(mapfile);
	fclose(mapfile);

/* Set up lighting */

	smgr->setAmbientLight(SColor(0x000000));
	scene::ILightSceneNode *groundLight = smgr->addLightSceneNode(0, vector3df(0,0,0), SColor(0xffffff), 10.0f);
	scene::ILightSceneNode *raisedLight = smgr->addLightSceneNode(groundLight, vector3df(0,5,0), SColor(0xffffff), 10.0f);

/* Set up skybox */

	const io::path skyboxFilename ("data/textures/skybox/top.png");
	video::ITexture *sb_tex = driver->getTexture(skyboxFilename);
	//smgr->addSkyBoxSceneNode(sb_tex, sb_tex, sb_tex, sb_tex, sb_tex, sb_tex); XXX REACTIVATE

/* T-Minus ten! */
	ITimer* timer = device->getTimer();
	timer->setTime(0);
	unsigned int now = 0;
	unsigned int lastUpdate = 0;
	int frame = 0;
	vector3df mousething;
	scene::IMesh *arrowMesh = smgr->addArrowMesh("ITSANARROW", 0xFFFFFF, 0xFF0000);
	scene::IMeshSceneNode *mouseNode = smgr->addMeshSceneNode(arrowMesh, 0);
//	scene::IMeshSceneNode *camPoint = smgr->addMeshSceneNode(arrowMesh, cam);
	mouseNode->setRotation(vector3df(0, 0, 180));
//	camPoint->setRotation(vector3df(0,0,180));

	core::line3df ray;
	scene::ISceneNode *dummyNode;
	core::triangle3df dummyTri;
/* We have liftoff! */
	while (device->run()) {
		now = timer->getTime();
		if (now >= lastUpdate + 1000.0/FPS) {
			frame++;
			lastUpdate = now;
			driver->beginScene(true, true, SColor(255, 255, 0, 255));
			driver->draw3DLine(ray.end, vector3df(0,0,0), 0x00ff00);
			driver->draw3DLine(cam->getAbsolutePosition(), vector3df(0,0,0), 0x0000ff);
			driver->draw3DLine(cam->getAbsolutePosition(), ray.start, 0xff0000);
			smgr->drawAll();
			env->drawAll();
			driver->endScene();

			camMove.set(0, 0, 0);
			if (receiver.IsKeyPressed(userControls.cam_up)) {
				camMove.X = 0.1;
			}
			if (receiver.IsKeyPressed(userControls.cam_down)) {
				camMove.X = -0.1;
			}
			if (receiver.IsKeyPressed(userControls.cam_left)) {
				camMove.Z = 0.1;
			}
			if (receiver.IsKeyPressed(userControls.cam_right)) {
				camMove.Z = -0.1;
			}
			if (receiver.IsKeyPressed(userControls.cam_raise)) {
				camMove.Y = 0.1;
			}
			if (receiver.IsKeyPressed(userControls.cam_lower)) {
				camMove.Y = -0.1;
			}
			camPos = cam->getPosition();
			camTarget = cam->getTarget();
			camPos += camMove;
			camMove.Y = 0;
			camTarget += camMove;
			cam->setPosition(camPos);
			cam->setTarget(camTarget);
			groundLight->setPosition(camTarget);

			ray = collMan->getRayFromScreenCoordinates(receiver.MousePosition, cam);
			ray.start = cam->getAbsolutePosition();
			if (collMan->getSceneNodeAndCollisionPointFromRay(ray, mousething, dummyTri)) {
				mouseNode->setPosition(mousething);
			}

			if(receiver.IsKeyPressed(KEY_ESCAPE)) break;
			if(frame % 100 == 0) printf("%i FPS\n", driver->getFPS());
		}
		else {
			Pass(10);
		}
	}
	device->drop();
	return 0;
}
<|endoftext|>


<commit_before>/**
 * Copyright (c) Sjors Gielen, 2010
 * See LICENSE for license.
 */

#include "dazeus.h"
#include "dazeusglobal.h"

#include <libircclient.h>

int main(int argc, char *argv[])
{
    fprintf(stderr, "DaZeus version: %s", DAZEUS_VERSION_STR);
    unsigned int high, low;
    irc_get_version(&high, &low);
    fprintf(stdout, "IRC library version: %d.%02d\n", high, low);

    // TODO parse command-line options
    DaZeus d( "./dazeus.conf" );

    // find and initialise plugins
    d.initPlugins();

    // connect to servers marked as "autoconnect"
    d.autoConnect();

    // start the event loop
    d.run();
    return 0;
}
<commit_msg>Fix startup output<commit_after>/**
 * Copyright (c) Sjors Gielen, 2010
 * See LICENSE for license.
 */

#include "dazeus.h"
#include "dazeusglobal.h"

#include <libircclient.h>

int main(int argc, char *argv[])
{
    fprintf(stderr, "DaZeus version: %s\n", DAZEUS_VERSION_STR);
    unsigned int high, low;
    irc_get_version(&high, &low);
    fprintf(stdout, "IRC library version: %d.%02d\n", high, low);

    // TODO parse command-line options
    DaZeus d( "./dazeus.conf" );

    // find and initialise plugins
    d.initPlugins();

    // connect to servers marked as "autoconnect"
    d.autoConnect();

    // start the event loop
    d.run();
    return 0;
}
<|endoftext|>


<commit_before>#include <gtest/gtest.h>
#include <stdexcept>

class Models_BasicDistributions_InvWishart : public ::testing::Test {
protected:
  virtual void SetUp() {
    FILE *in;
    if(!(in = popen("make path_separator --no-print-directory", "r")))
      throw std::runtime_error("\"make path_separator\" has failed.");
    path_separator += fgetc(in);
    pclose(in);

    model.append("models").append(path_separator);
    model.append("basic_distributions").append(path_separator);
    model.append("inv_wishart");

    output1 = model + "1.csv";
    output2 = model + "2.csv";
  }
  std::string path_separator;
  std::string model;
  std::string output1;
  std::string output2;
};

TEST_F(Models_BasicDistributions_InvWishart,RunModel) {
  std::string command;
  command = model;
  command += " --samples=";
  command += output1;
  EXPECT_EQ(0, system(command.c_str()))
    << "Can not execute command: " << command << std::endl;

  command = model;
  command += " --samples=";
  command += output2;
  EXPECT_EQ(0, system(command.c_str()))
    << "Can not execute command: " << command << std::endl;
}
<commit_msg>test-models: updated test/models/basic_distributions/inv_wishart<commit_after>#include <gtest/gtest.h>
#include <test/models/model_test_fixture.hpp>

class Models_BasicDistributions_InvWishart :
  public ::testing::Model_Test_Fixture<Models_BasicDistributions_InvWishart,
                                       false> {
protected:
  virtual void SetUp() {
  }
public:
  static std::vector<std::string> get_model_path() {
    std::vector<std::string> model_path;
    model_path.push_back("models");
    model_path.push_back("basic_distributions");
    model_path.push_back("inv_wishart");
    return model_path;
  }

};

TEST_F(Models_BasicDistributions_InvWishart,RunModel) {
  run_model();
}
<|endoftext|>


<commit_before>// Copyright (c) 2013 John Sullivan
// Copyright (c) 2013 Other contributers as noted in the CONTRIBUTERS file
//
// This file is part of Irish Light Show
//
// 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 "graphics/primitives/ColorRGB.hpp"
#include "graphics/primitives/RGBSurface.hpp"
#include "graphics/files/ImageFile.hpp"
#include "common/SDLException.hpp"

#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>

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

typedef uint32_t color_t;

// Other options at http://stackoverflow.com/a/596243/1989056
unsigned get_luminence(graphics::ColorRGB const & color) {
    return static_cast<unsigned>(
        0.299 * color.red +
        0.587 * color.green +
        0.114 * color.blue);
}

// Blends b atop a. Returns b if lumincence of b is greater than a, unless b's
// luminence is greater than cap, in which case a is returned.
void light_blend_surfaces(graphics::RGBSurface const & a,
        graphics::RGBSurface const & b, graphics::RGBSurface & out,
        unsigned cap) {
    unsigned width = std::min(a.width(), b.width());
    unsigned height = std::min(a.height(), b.height());

    if (width > out.width() || height > out.height()) {
        throw std::invalid_argument("out must not be smaller than a or b");
    }

    for (unsigned x = 0; x < width; ++x) {
        for (unsigned y = 0; y < height; ++y) {
            graphics::ColorRGB * chosen_color;

            graphics::ColorRGB a_color = a.get_pixel(x, y);
            graphics::ColorRGB b_color = b.get_pixel(x, y);
            unsigned b_lumincence = get_luminence(b_color);
            if (b_lumincence > cap) {
                chosen_color = &a_color;
            } else {
                unsigned a_lumincence = get_luminence(a_color);

                chosen_color =
                    b_lumincence > a_lumincence ? &b_color : &a_color;
            }

            out.set_pixel(x, y, *chosen_color);
        }
    }
}

int main(int argc, char * argv[]) {
    if (argc < 3) {
        std::cout << "usage: " << argv[0] << " image0 image1 ..." << std::endl;
        return 1;
    }

    if (SDL_Init(SDL_INIT_VIDEO) != 0) {
        std::cerr << "Failed to initialize SDL_video." << std::endl;
        return 1;
    }

    // Open all the image files and load them into memory
    std::vector<graphics::ImageFile> files;
    unsigned max_width = 0, max_height = 0;
    for (int i = 1; i < argc; ++i) {
        files.emplace_back(argv[i]);

        max_width = std::max(max_width,
            files[files.size() - 1].surface().width());
        max_height = std::max(max_height,
            files[files.size() - 1].surface().height());
    }

    // Create an off-screen buffer we'll draw to
    graphics::RGBSurface buffer(max_width, max_height);

    // Blend the images from left to right
    light_blend_surfaces(files.at(0).surface(), files.at(1).surface(), buffer,
        255);
    for (size_t i = 2; i < files.size(); ++i) {
        light_blend_surfaces(buffer, files.at(i).surface(), buffer, 255);
    }

    // Get a window up
    SDL_Window * win = SDL_CreateWindow(
        "Irish Light Show", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
        max_width, max_height, SDL_WINDOW_SHOWN);
    if (win == nullptr){
       std::cerr << "Failed to create window. " << SDL_GetError() << std::endl;
       return 1;
    }
    SDL_Surface * screen = SDL_GetWindowSurface(win);

    SDL_BlitSurface(buffer.sdl_surface(), nullptr, screen, nullptr);
    SDL_UpdateWindowSurface(win);

    SDL_Delay(2000);

    SDL_DestroyWindow(win);

    IMG_Quit();
    SDL_Quit();

    return 0;
}
<commit_msg>Functionally it's all working. Bed time.<commit_after>// Copyright (c) 2013 John Sullivan
// Copyright (c) 2013 Other contributers as noted in the CONTRIBUTERS file
//
// This file is part of Irish Light Show
//
// 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 "graphics/primitives/ColorRGB.hpp"
#include "graphics/primitives/RGBSurface.hpp"
#include "graphics/files/ImageFile.hpp"
#include "common/SDLException.hpp"

#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>

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

typedef uint32_t color_t;

// Other options at http://stackoverflow.com/a/596243/1989056
unsigned get_luminence(graphics::ColorRGB const & color) {
    return static_cast<unsigned>(
        0.299 * color.red +
        0.587 * color.green +
        0.114 * color.blue);
}

// Blends b atop a. Returns b if lumincence of b is greater than a, unless b's
// luminence is greater than cap, in which case a is returned.
void light_blend_surfaces(graphics::RGBSurface const & a,
        graphics::RGBSurface const & b, graphics::RGBSurface & out,
        unsigned cap) {
    unsigned width = std::min(a.width(), b.width());
    unsigned height = std::min(a.height(), b.height());

    if (width > out.width() || height > out.height()) {
        throw std::invalid_argument("out must not be smaller than a or b");
    }

    for (unsigned x = 0; x < width; ++x) {
        for (unsigned y = 0; y < height; ++y) {
            graphics::ColorRGB * chosen_color;

            graphics::ColorRGB a_color = a.get_pixel(x, y);
            graphics::ColorRGB b_color = b.get_pixel(x, y);
            unsigned b_lumincence = get_luminence(b_color);
            if (b_lumincence > cap) {
                chosen_color = &a_color;
            } else {
                unsigned a_lumincence = get_luminence(a_color);

                chosen_color =
                    b_lumincence > a_lumincence ? &b_color : &a_color;
            }

            out.set_pixel(x, y, *chosen_color);
        }
    }
}

int main(int argc, char * argv[]) {
    if (argc < 3) {
        std::cout << "usage: " << argv[0] << " image0 image1 ..." << std::endl;
        return 1;
    }

    if (SDL_Init(SDL_INIT_VIDEO) != 0) {
        std::cerr << "Failed to initialize SDL_video." << std::endl;
        return 1;
    }

    // Open all the image files and load them into memory
    std::vector<graphics::ImageFile> files;
    unsigned max_width = 0, max_height = 0;
    for (int i = 1; i < argc; ++i) {
        files.emplace_back(argv[i]);

        max_width = std::max(max_width,
            files[files.size() - 1].surface().width());
        max_height = std::max(max_height,
            files[files.size() - 1].surface().height());
    }

    // Create an off-screen buffer we'll draw to
    graphics::RGBSurface buffer(max_width, max_height);

    // Get a window up
    SDL_Window * win = SDL_CreateWindow(
        "Irish Light Show", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
        max_width, max_height, SDL_WINDOW_SHOWN);
    if (win == nullptr){
       std::cerr << "Failed to create window. " << SDL_GetError() << std::endl;
       return 1;
    }
    SDL_Surface * screen = SDL_GetWindowSurface(win);

    unsigned const LIGHTNESS_CAP_MAX = 255;
    unsigned const LIGHTNESS_CAP_MIN = 0;
    unsigned const LIGHTNESS_CAP_BIG_STEP = 30;
    unsigned lightness_cap = LIGHTNESS_CAP_MAX;

    bool refresh_screen = false;
    SDL_Event event;
    while (SDL_WaitEvent(&event) == 1)
    {
        switch(event.type)
        {
            case SDL_KEYDOWN:
                refresh_screen = true;
                if (event.key.keysym.sym == SDLK_UP &&
                        lightness_cap < LIGHTNESS_CAP_MAX) {
                    ++lightness_cap;
                } else if (event.key.keysym.sym == SDLK_DOWN &&
                        lightness_cap > LIGHTNESS_CAP_MIN) {
                    --lightness_cap;
                } else if (event.key.keysym.sym == SDLK_PAGEUP) {
                    lightness_cap = std::min(
                        lightness_cap + LIGHTNESS_CAP_BIG_STEP,
                        LIGHTNESS_CAP_MAX);
                } else if (event.key.keysym.sym == SDLK_PAGEDOWN) {
                    if (LIGHTNESS_CAP_MIN + LIGHTNESS_CAP_BIG_STEP >
                            lightness_cap) {
                        lightness_cap = 0;
                    } else {
                        lightness_cap -= LIGHTNESS_CAP_BIG_STEP;
                    }
                } else {
                    refresh_screen = false;
                }
                break;

            case SDL_QUIT:
                goto cleanup;
                break;
        }

        if (refresh_screen) {
            std::cout << "cap: " << lightness_cap << std::endl;
            // Blend the images from left to right
            light_blend_surfaces(files.at(0).surface(), files.at(1).surface(),
                buffer, lightness_cap);
            for (size_t i = 2; i < files.size(); ++i) {
                light_blend_surfaces(buffer, files.at(i).surface(), buffer,
                    lightness_cap);
            }

            SDL_BlitSurface(buffer.sdl_surface(), nullptr, screen, nullptr);
            SDL_UpdateWindowSurface(win);

            refresh_screen = false;
        }
    }
cleanup:

    IMG_Quit();
    SDL_Quit();

    return 0;
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2015 Juniper Networks, Inc. All rights reserved.
 */
#include <pkt/flow_proto.h>
#include "ksync_flow_index_manager.h"
#include "flowtable_ksync.h"
#include "ksync_init.h"

//////////////////////////////////////////////////////////////////////////////
// KSyncFlowIndexEntry routines
//////////////////////////////////////////////////////////////////////////////
KSyncFlowIndexEntry::KSyncFlowIndexEntry() :
    state_(INIT), index_(FlowEntry::kInvalidFlowHandle), ksync_entry_(NULL),
    index_owner_(NULL), evict_count_(0), delete_in_progress_(false) {
}

KSyncFlowIndexEntry::~KSyncFlowIndexEntry() {
    assert(index_owner_.get() == NULL);
    assert(ksync_entry_ == NULL);
}

bool KSyncFlowIndexEntry::IsEvicted() const {
    return (state_ == INDEX_EVICT || state_ == INDEX_CHANGE);
}

void KSyncFlowIndexEntry::Reset() {
    index_ = FlowEntry::kInvalidFlowHandle;
    state_ = INIT;
    ksync_entry_ = NULL;
    delete_in_progress_ = false;
}

//////////////////////////////////////////////////////////////////////////////
// KSyncFlowIndexManager routines
//////////////////////////////////////////////////////////////////////////////
KSyncFlowIndexManager::KSyncFlowIndexManager(KSync *ksync) :
    ksync_(ksync), proto_(NULL), count_(0), index_list_() {
}

KSyncFlowIndexManager::~KSyncFlowIndexManager() {
}

void KSyncFlowIndexManager::InitDone(uint32_t count) {
    proto_ = ksync_->agent()->pkt()->get_flow_proto();
    count_ = count;
    index_list_.resize(count);
}

//////////////////////////////////////////////////////////////////////////////
// KSyncFlowIndexManager APIs
//////////////////////////////////////////////////////////////////////////////
void KSyncFlowIndexManager::RetryIndexAcquireRequest(FlowEntry *flow,
                                                     uint32_t flow_handle) {
    if (flow == NULL)
        return;
    proto_->RetryIndexAcquireRequest(flow, flow_handle);
}

void KSyncFlowIndexManager::ReleaseRequest(FlowEntry *flow) {
    Release(flow);
}

// Handle add of a flow
void KSyncFlowIndexManager::Add(FlowEntry *flow) {
    FlowTableKSyncObject *object = GetKSyncObject(flow);
    KSyncFlowIndexEntry *index_entry = flow->ksync_index_entry();

    if (index_entry->state_ == KSyncFlowIndexEntry::INDEX_UNASSIGNED) {
        UpdateFlowHandle(flow);
        return;
    }

    // If flow already has a KSync entry, it means old flow was evicted.
    // Delete the old KSync entry. Once the KSync entry is freed, we will
    // get callback to "Release". New KSync entry will be allocated from
    // "Release" method
    if (index_entry->ksync_entry()) {
        EvictFlow(flow);
        return;
    }

    FlowEntryPtr old_flow = SafeAcquireIndex(flow);
    if (old_flow.get() != NULL) {
        // If index cannot be acquired, put flow into wait list of old_flow
        // (flow holding the index)
        EvictFlow(old_flow.get(), flow);
        return;
    }

    assert(index_entry->ksync_entry_ == NULL);
    if (index_entry->index_ == FlowEntry::kInvalidFlowHandle &&
        flow->flow_handle() == FlowEntry::kInvalidFlowHandle) {
        index_entry->state_ = KSyncFlowIndexEntry::INDEX_UNASSIGNED;
    } else {
        index_entry->state_ = KSyncFlowIndexEntry::INDEX_SET;
    }
    FlowTableKSyncEntry key(object, flow, flow->flow_handle());
    index_entry->ksync_entry_ =
        (static_cast<FlowTableKSyncEntry *>(object->Create(&key, true)));

    // Add called for deleted flow. This happens when Reverse flow is
    // deleted before getting ACK from vrouter.
    // Create and delete KSync Entry
    if (flow->deleted()) {
        Delete(flow);
    }
}

void KSyncFlowIndexManager::Change(FlowEntry *flow) {
    KSyncFlowIndexEntry *index_entry = flow->ksync_index_entry();
    if (flow->deleted() ||
        (index_entry->state_ != KSyncFlowIndexEntry::INDEX_SET)) {
        return;
    }

    // If index not yet assigned for flow, the flow will be written when later
    if (index_entry->state_ == KSyncFlowIndexEntry::INDEX_UNASSIGNED) {
        return;
    }

    FlowTableKSyncObject *object = GetKSyncObject(flow);
    object->Change(index_entry->ksync_entry_);
}

bool KSyncFlowIndexManager::Delete(FlowEntry *flow) {
    FlowTableKSyncObject *object = GetKSyncObject(flow);
    KSyncFlowIndexEntry *index_entry = flow->ksync_index_entry();
    if (index_entry->delete_in_progress_) {
        return false;
    }

    if (index_entry->state_ == KSyncFlowIndexEntry::INDEX_UNASSIGNED)
        return false;

    if (index_entry->ksync_entry_ == NULL) {
        assert(index_entry->index_ == FlowEntry::kInvalidFlowHandle);
        return false;
    }

    index_entry->delete_in_progress_ = true;
    // Hold reference to ksync-entry till this function call is over
    KSyncEntry::KSyncEntryPtr ksync_ptr = index_entry->ksync_entry_;
    object->Delete(index_entry->ksync_entry_);
    return true;
}

// Flow was written with -1 as index and vrouter allocated an index.
void KSyncFlowIndexManager::UpdateFlowHandle(FlowEntry *flow) {
    KSyncFlowIndexEntry *index_entry = flow->ksync_index_entry();

    if (index_entry->index_ == flow->flow_handle())
        return;

    // Ensure that flow is not evicted
    // A flow with index -1 will always have a flow with HOLD state as reverse
    // flow. VRouter does not evict flows in HOLD state. As a result, we dont
    // expect the flow to be evicted.
    assert(index_entry->state_ == KSyncFlowIndexEntry::INDEX_UNASSIGNED);
    assert(index_entry->index_ == FlowEntry::kInvalidFlowHandle);

    assert(index_entry->ksync_entry());
    FlowEntryPtr old_flow = SafeAcquireIndex(flow);
    if (old_flow.get() != NULL) {
        // If index cannot be acquired, put flow into wait list of old_flow
        // (flow holding the index)
        EvictFlow(old_flow.get(), flow);
        return;
    }

    flow->ksync_index_entry()->state_ = KSyncFlowIndexEntry::INDEX_SET;
    FlowTableKSyncObject *object = GetKSyncObject(flow);
    object->UpdateFlowHandle(index_entry->ksync_entry_, index_entry->index_);

    // If flow is deleted in the meanwhile, delete the flow entry
    if (flow->deleted()) {
        Delete(flow);
    }
}

void KSyncFlowIndexManager::Release(FlowEntry *flow) {
    FlowEntryPtr wait_flow = ReleaseIndex(flow);

    // Make a copy of values needed for subsequent processing before reset
    KSyncFlowIndexEntry::State state = flow->ksync_index_entry()->state_;
    FlowEntryPtr owner_entry = flow->ksync_index_entry()->index_owner_;
    uint32_t evict_index = flow->ksync_index_entry()->index_;

    // Reset the old index entry
    flow->ksync_index_entry()->Reset();

    switch (state) {

    // Entry has index set and no further transitions necessary
    case KSyncFlowIndexEntry::INDEX_SET:
        break;

    // Entry deleted when waiting for index.
    // Invoke Add() again so that the HOLD entry entry is deleted from VRouter
    case KSyncFlowIndexEntry::INDEX_WAIT: {
        RemoveWaitList(owner_entry.get(), flow);
        Add(flow);
        break;
    }

    // Index changed for flow and old index freed. Try acquring new index
    case KSyncFlowIndexEntry::INDEX_CHANGE: {
        RetryIndexAcquireRequest(wait_flow.get(), evict_index);
        Add(flow);
        break;
    }

    // Flow evicted. Now activate entry waiting for on the index
    case KSyncFlowIndexEntry::INDEX_EVICT: {
        RetryIndexAcquireRequest(wait_flow.get(), evict_index);
        break;
    }

    default:
        assert(0);
    }
    return;
}

// Release the index and return flow in wait list
FlowEntryPtr KSyncFlowIndexManager::ReleaseIndex(FlowEntry *flow) {
    FlowEntryPtr wait_flow = NULL;
    uint32_t index = flow->ksync_index_entry()->index_;
    if (index == FlowEntry::kInvalidFlowHandle) {
        return wait_flow;
    }

    tbb::mutex::scoped_lock lock(index_list_[index].mutex_);
    assert(index_list_[index].owner_.get() == flow);
    // Release the index_list_ entry
    index_list_[index].owner_ = NULL;
    wait_flow.swap(index_list_[index].wait_entry_);
    return wait_flow;
}

FlowEntryPtr KSyncFlowIndexManager::FindByIndex(uint32_t idx) {
    tbb::mutex::scoped_lock lock(index_list_[idx].mutex_);
    if (index_list_[idx].owner_.get() != NULL)
        return index_list_[idx].owner_;
    return FlowEntryPtr(NULL);
}

FlowEntryPtr KSyncFlowIndexManager::AcquireIndex(FlowEntry *flow) {
    FlowEntryPtr ret(NULL);
    // Sanity checks for a new flow
    assert(flow->ksync_index_entry()->index_ == FlowEntry::kInvalidFlowHandle);

    // Ignore entries with invalid index
    uint32_t index = flow->flow_handle();
    if (index == FlowEntry::kInvalidFlowHandle) {
        return ret;
    }

    tbb::mutex::scoped_lock lock(index_list_[index].mutex_);
    if (index_list_[index].owner_.get() != NULL)
        return index_list_[index].owner_;

    flow->ksync_index_entry()->index_ = index;
    index_list_[index].owner_ = flow;
    return ret;
}

FlowEntryPtr KSyncFlowIndexManager::SafeAcquireIndex(FlowEntry *flow) {
    if (flow->ksync_index_entry()->ksync_entry_ != NULL) {
        assert(flow->ksync_index_entry()->index_ ==
               FlowEntry::kInvalidFlowHandle);
    }
    return AcquireIndex(flow);
}

void KSyncFlowIndexManager::AddWaitList(FlowEntry *old_flow, FlowEntry *flow) {
    uint32_t index = old_flow->ksync_index_entry()->index_;
    tbb::mutex::scoped_lock lock(index_list_[index].mutex_);
    assert((index_list_[index].wait_entry_.get() == NULL) ||
           (index_list_[index].wait_entry_.get() == flow));
    index_list_[index].wait_entry_ = flow;
}

void KSyncFlowIndexManager::RemoveWaitList(FlowEntry *old_flow,
                                           FlowEntry *flow) {
    uint32_t index = old_flow->ksync_index_entry()->index_;
    tbb::mutex::scoped_lock lock(index_list_[index].mutex_);
    assert(index_list_[index].wait_entry_.get() == flow);
    index_list_[index].wait_entry_ = NULL;
}

void KSyncFlowIndexManager::EvictFlow(FlowEntry *flow) {
    KSyncFlowIndexEntry *index_entry = flow->ksync_index_entry();
    index_entry->evict_count_++;
    index_entry->state_ = KSyncFlowIndexEntry::INDEX_CHANGE;
    Delete(flow);
}

void KSyncFlowIndexManager::EvictFlow(FlowEntry *old_flow, FlowEntry *flow) {
    old_flow->ksync_index_entry()->evict_count_++;
    old_flow->ksync_index_entry()->state_ = KSyncFlowIndexEntry::INDEX_EVICT;
    KSyncFlowIndexEntry *index_entry = flow->ksync_index_entry();
    if (index_entry->state_ == KSyncFlowIndexEntry::INDEX_UNASSIGNED) {
        assert(index_entry->index_ == FlowEntry::kInvalidFlowHandle);
    } else {
        flow->ksync_index_entry()->state_ = KSyncFlowIndexEntry::INDEX_WAIT;
    }
    AddWaitList(old_flow, flow);
    proto_->EvictFlowRequest(old_flow, flow->flow_handle());
}

FlowTableKSyncObject *KSyncFlowIndexManager::GetKSyncObject(FlowEntry *flow) {
    return flow->flow_table()->ksync_object();
}
<commit_msg>Flows not deleted resulting in vrf del pending.<commit_after>/*
 * Copyright (c) 2015 Juniper Networks, Inc. All rights reserved.
 */
#include <pkt/flow_proto.h>
#include "ksync_flow_index_manager.h"
#include "flowtable_ksync.h"
#include "ksync_init.h"

//////////////////////////////////////////////////////////////////////////////
// KSyncFlowIndexEntry routines
//////////////////////////////////////////////////////////////////////////////
KSyncFlowIndexEntry::KSyncFlowIndexEntry() :
    state_(INIT), index_(FlowEntry::kInvalidFlowHandle), ksync_entry_(NULL),
    index_owner_(NULL), evict_count_(0), delete_in_progress_(false) {
}

KSyncFlowIndexEntry::~KSyncFlowIndexEntry() {
    assert(index_owner_.get() == NULL);
    assert(ksync_entry_ == NULL);
}

bool KSyncFlowIndexEntry::IsEvicted() const {
    return (state_ == INDEX_EVICT || state_ == INDEX_CHANGE);
}

void KSyncFlowIndexEntry::Reset() {
    index_ = FlowEntry::kInvalidFlowHandle;
    state_ = INIT;
    ksync_entry_ = NULL;
    delete_in_progress_ = false;
}

//////////////////////////////////////////////////////////////////////////////
// KSyncFlowIndexManager routines
//////////////////////////////////////////////////////////////////////////////
KSyncFlowIndexManager::KSyncFlowIndexManager(KSync *ksync) :
    ksync_(ksync), proto_(NULL), count_(0), index_list_() {
}

KSyncFlowIndexManager::~KSyncFlowIndexManager() {
}

void KSyncFlowIndexManager::InitDone(uint32_t count) {
    proto_ = ksync_->agent()->pkt()->get_flow_proto();
    count_ = count;
    index_list_.resize(count);
}

//////////////////////////////////////////////////////////////////////////////
// KSyncFlowIndexManager APIs
//////////////////////////////////////////////////////////////////////////////
void KSyncFlowIndexManager::RetryIndexAcquireRequest(FlowEntry *flow,
                                                     uint32_t flow_handle) {
    if (flow == NULL)
        return;
    proto_->RetryIndexAcquireRequest(flow, flow_handle);
}

void KSyncFlowIndexManager::ReleaseRequest(FlowEntry *flow) {
    Release(flow);
}

// Handle add of a flow
void KSyncFlowIndexManager::Add(FlowEntry *flow) {
    FlowTableKSyncObject *object = GetKSyncObject(flow);
    KSyncFlowIndexEntry *index_entry = flow->ksync_index_entry();

    if (index_entry->state_ == KSyncFlowIndexEntry::INDEX_UNASSIGNED) {
        UpdateFlowHandle(flow);
        return;
    }

    // If flow already has a KSync entry, it means old flow was evicted.
    // Delete the old KSync entry. Once the KSync entry is freed, we will
    // get callback to "Release". New KSync entry will be allocated from
    // "Release" method
    if (index_entry->ksync_entry()) {
        EvictFlow(flow);
        return;
    }

    FlowEntryPtr old_flow = SafeAcquireIndex(flow);
    if (old_flow.get() != NULL) {
        // If index cannot be acquired, put flow into wait list of old_flow
        // (flow holding the index)
        EvictFlow(old_flow.get(), flow);
        return;
    }

    assert(index_entry->ksync_entry_ == NULL);
    if (index_entry->index_ == FlowEntry::kInvalidFlowHandle &&
        flow->flow_handle() == FlowEntry::kInvalidFlowHandle) {
        index_entry->state_ = KSyncFlowIndexEntry::INDEX_UNASSIGNED;
    } else {
        index_entry->state_ = KSyncFlowIndexEntry::INDEX_SET;
    }
    FlowTableKSyncEntry key(object, flow, flow->flow_handle());
    index_entry->ksync_entry_ =
        (static_cast<FlowTableKSyncEntry *>(object->Create(&key, true)));

    // Add called for deleted flow. This happens when Reverse flow is
    // deleted before getting ACK from vrouter.
    // Create and delete KSync Entry
    if (flow->deleted()) {
        Delete(flow);
    }
}

void KSyncFlowIndexManager::Change(FlowEntry *flow) {
    KSyncFlowIndexEntry *index_entry = flow->ksync_index_entry();
    if (flow->deleted() ||
        (index_entry->state_ != KSyncFlowIndexEntry::INDEX_SET)) {
        return;
    }

    // If index not yet assigned for flow, the flow will be written when later
    if (index_entry->state_ == KSyncFlowIndexEntry::INDEX_UNASSIGNED) {
        return;
    }

    FlowTableKSyncObject *object = GetKSyncObject(flow);
    object->Change(index_entry->ksync_entry_);
}

bool KSyncFlowIndexManager::Delete(FlowEntry *flow) {
    FlowTableKSyncObject *object = GetKSyncObject(flow);
    KSyncFlowIndexEntry *index_entry = flow->ksync_index_entry();
    if (index_entry->delete_in_progress_) {
        return false;
    }

    bool force_delete = false;
    //Flow index allocation had failed from kernel, so dont wait for
    //index allocation and delete flow. Note: Because of failed index allocation
    //flow was marked as short flow with reason SHORT_FAILED_VROUTER_INSTALL
    force_delete |= (flow->is_flags_set(FlowEntry::ShortFlow) &&
                     (flow->short_flow_reason() ==
                      ((uint16_t) FlowEntry::SHORT_FAILED_VROUTER_INSTALL)));

    if (!force_delete) {
        if (index_entry->state_ == KSyncFlowIndexEntry::INDEX_UNASSIGNED)
            return false;

        if (index_entry->ksync_entry_ == NULL) {
            assert(index_entry->index_ == FlowEntry::kInvalidFlowHandle);
            return false;
        }
    }

    index_entry->delete_in_progress_ = true;
    // Hold reference to ksync-entry till this function call is over
    KSyncEntry::KSyncEntryPtr ksync_ptr = index_entry->ksync_entry_;
    object->Delete(index_entry->ksync_entry_);
    return true;
}

// Flow was written with -1 as index and vrouter allocated an index.
void KSyncFlowIndexManager::UpdateFlowHandle(FlowEntry *flow) {
    KSyncFlowIndexEntry *index_entry = flow->ksync_index_entry();

    if (index_entry->index_ == flow->flow_handle())
        return;

    // Ensure that flow is not evicted
    // A flow with index -1 will always have a flow with HOLD state as reverse
    // flow. VRouter does not evict flows in HOLD state. As a result, we dont
    // expect the flow to be evicted.
    assert(index_entry->state_ == KSyncFlowIndexEntry::INDEX_UNASSIGNED);
    assert(index_entry->index_ == FlowEntry::kInvalidFlowHandle);

    assert(index_entry->ksync_entry());
    FlowEntryPtr old_flow = SafeAcquireIndex(flow);
    if (old_flow.get() != NULL) {
        // If index cannot be acquired, put flow into wait list of old_flow
        // (flow holding the index)
        EvictFlow(old_flow.get(), flow);
        return;
    }

    flow->ksync_index_entry()->state_ = KSyncFlowIndexEntry::INDEX_SET;
    FlowTableKSyncObject *object = GetKSyncObject(flow);
    object->UpdateFlowHandle(index_entry->ksync_entry_, index_entry->index_);

    // If flow is deleted in the meanwhile, delete the flow entry
    if (flow->deleted()) {
        Delete(flow);
    }
}

void KSyncFlowIndexManager::Release(FlowEntry *flow) {
    FlowEntryPtr wait_flow = ReleaseIndex(flow);

    // Make a copy of values needed for subsequent processing before reset
    KSyncFlowIndexEntry::State state = flow->ksync_index_entry()->state_;
    FlowEntryPtr owner_entry = flow->ksync_index_entry()->index_owner_;
    uint32_t evict_index = flow->ksync_index_entry()->index_;

    // Reset the old index entry
    flow->ksync_index_entry()->Reset();

    switch (state) {

    // Entry has index set and no further transitions necessary
    case KSyncFlowIndexEntry::INDEX_SET:
        break;

    // Entry deleted when waiting for index.
    // Invoke Add() again so that the HOLD entry entry is deleted from VRouter
    case KSyncFlowIndexEntry::INDEX_WAIT: {
        RemoveWaitList(owner_entry.get(), flow);
        Add(flow);
        break;
    }

    // Index changed for flow and old index freed. Try acquring new index
    case KSyncFlowIndexEntry::INDEX_CHANGE: {
        RetryIndexAcquireRequest(wait_flow.get(), evict_index);
        Add(flow);
        break;
    }

    // Flow evicted. Now activate entry waiting for on the index
    case KSyncFlowIndexEntry::INDEX_EVICT: {
        RetryIndexAcquireRequest(wait_flow.get(), evict_index);
        break;
    }

    default:
        assert(0);
    }
    return;
}

// Release the index and return flow in wait list
FlowEntryPtr KSyncFlowIndexManager::ReleaseIndex(FlowEntry *flow) {
    FlowEntryPtr wait_flow = NULL;
    uint32_t index = flow->ksync_index_entry()->index_;
    if (index == FlowEntry::kInvalidFlowHandle) {
        return wait_flow;
    }

    tbb::mutex::scoped_lock lock(index_list_[index].mutex_);
    assert(index_list_[index].owner_.get() == flow);
    // Release the index_list_ entry
    index_list_[index].owner_ = NULL;
    wait_flow.swap(index_list_[index].wait_entry_);
    return wait_flow;
}

FlowEntryPtr KSyncFlowIndexManager::FindByIndex(uint32_t idx) {
    tbb::mutex::scoped_lock lock(index_list_[idx].mutex_);
    if (index_list_[idx].owner_.get() != NULL)
        return index_list_[idx].owner_;
    return FlowEntryPtr(NULL);
}

FlowEntryPtr KSyncFlowIndexManager::AcquireIndex(FlowEntry *flow) {
    FlowEntryPtr ret(NULL);
    // Sanity checks for a new flow
    assert(flow->ksync_index_entry()->index_ == FlowEntry::kInvalidFlowHandle);

    // Ignore entries with invalid index
    uint32_t index = flow->flow_handle();
    if (index == FlowEntry::kInvalidFlowHandle) {
        return ret;
    }

    tbb::mutex::scoped_lock lock(index_list_[index].mutex_);
    if (index_list_[index].owner_.get() != NULL)
        return index_list_[index].owner_;

    flow->ksync_index_entry()->index_ = index;
    index_list_[index].owner_ = flow;
    return ret;
}

FlowEntryPtr KSyncFlowIndexManager::SafeAcquireIndex(FlowEntry *flow) {
    if (flow->ksync_index_entry()->ksync_entry_ != NULL) {
        assert(flow->ksync_index_entry()->index_ ==
               FlowEntry::kInvalidFlowHandle);
    }
    return AcquireIndex(flow);
}

void KSyncFlowIndexManager::AddWaitList(FlowEntry *old_flow, FlowEntry *flow) {
    uint32_t index = old_flow->ksync_index_entry()->index_;
    tbb::mutex::scoped_lock lock(index_list_[index].mutex_);
    assert((index_list_[index].wait_entry_.get() == NULL) ||
           (index_list_[index].wait_entry_.get() == flow));
    index_list_[index].wait_entry_ = flow;
}

void KSyncFlowIndexManager::RemoveWaitList(FlowEntry *old_flow,
                                           FlowEntry *flow) {
    uint32_t index = old_flow->ksync_index_entry()->index_;
    tbb::mutex::scoped_lock lock(index_list_[index].mutex_);
    assert(index_list_[index].wait_entry_.get() == flow);
    index_list_[index].wait_entry_ = NULL;
}

void KSyncFlowIndexManager::EvictFlow(FlowEntry *flow) {
    KSyncFlowIndexEntry *index_entry = flow->ksync_index_entry();
    index_entry->evict_count_++;
    index_entry->state_ = KSyncFlowIndexEntry::INDEX_CHANGE;
    Delete(flow);
}

void KSyncFlowIndexManager::EvictFlow(FlowEntry *old_flow, FlowEntry *flow) {
    old_flow->ksync_index_entry()->evict_count_++;
    old_flow->ksync_index_entry()->state_ = KSyncFlowIndexEntry::INDEX_EVICT;
    KSyncFlowIndexEntry *index_entry = flow->ksync_index_entry();
    if (index_entry->state_ == KSyncFlowIndexEntry::INDEX_UNASSIGNED) {
        assert(index_entry->index_ == FlowEntry::kInvalidFlowHandle);
    } else {
        flow->ksync_index_entry()->state_ = KSyncFlowIndexEntry::INDEX_WAIT;
    }
    AddWaitList(old_flow, flow);
    proto_->EvictFlowRequest(old_flow, flow->flow_handle());
}

FlowTableKSyncObject *KSyncFlowIndexManager::GetKSyncObject(FlowEntry *flow) {
    return flow->flow_table()->ksync_object();
}
<|endoftext|>


<commit_before>#include <cstdio>
#include <cstdlib>
#include <cctype>
#include <cstring>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <vector>
#include <string>
#include <iostream>

#include "functions.h"

int main(int argc, char** argv)
{
  // print welcome message and prompt
  printf("Welcome to rshell!\n");

  bool ext = false;

  while (!ext)
  {
    // holds a single command and its arguments
    Command cmd;
    // holds multiple commands
    std::vector<Command> cmds;
    // hold a raw line of input
    std::string line;

    // print prompt and get a line of text (done in condition)
    printf("$ ");
    getline(std::cin, line);

    // look for comments
    if (line.find("#") != std::string::npos)
    {
      // remove them if necessary (they're useless)
      line = line.substr(0, line.find("#"));
    }

    // remove leading whitespace
    while (line.size() > 0 && (line[0] == ' ' || line[0] == ';'))
    {
      line = line.substr(1, line.size() - 1);
    }

    // adding this makes parsing easier
    line += "; ";

    if (std::cin.fail())
    {
      printf("\nGoodbye!\n");
      exit(0);
    }

    int mode = GETWORD;
    unsigned begin = 0;

    // prepare cmd
    cmd.connector = NONE;

    // syntax error flag
    bool se = false;

    // starts with a connector? I don't think so
    if (line.size() > 0 && isConn(line[0]) && line[0] != ';')
    {
      se = true;
    }

    // handle the input
    for(unsigned i = 0; i < line.size() && !se; ++i)
    {
      bool con   = isConn(line[i]);
      bool space = isspace(line[i]);

      // if we're getting a word and there's a whitespace or connector here
      if (mode == GETWORD && (space || con))
      {
        // chunk the last term and throw it into the vector
        char* c = stocstr(line.substr(begin, i - begin));
        if (strlen(c) > 0)
        {
          cmd.args.push_back(c);
        }
        else
        {
          // only happens when nothing is entered. breaks so nothing more happens
          break;
        }

        if (space)
        {
          mode = TRIMSPACE;
        }
        else // it's a connector
        {
          handleCon(cmds, cmd, line, mode, begin, i, se);
        }
      }
      else if (mode == TRIMSPACE && (!space || con))
      {
        if (con && cmd.args.empty())
        {
          if (line[i] != ';')
          {
            se = true;
          }
        }
        else if (con)
        {
          handleCon(cmds, cmd, line, mode, begin, i, se);
        }
        else
        {
          mode = GETWORD;
          begin = i;
        }
      }
      else if (mode == HANDLESEMI && line[i] != ';')
      {
        if (isConn(line[i]))
        {
          se = true;
        }
        else if (isspace(line[i]))
        {
          mode = TRIMSPACE;
        }
        else // it's a word
        {
          mode = GETWORD;
          begin = i;
        }
      }
    }

    // if the last command has a continuation connector, syntax error
    if (cmds.size() > 0 && (cmds[cmds.size() - 1].connector == AND
                        ||  cmds[cmds.size() - 1].connector == OR))
    {
      se = true;
    }

    // if there was a syntax error
    if (se)
    {
      printf("Syntax error\n");
      continue;
    }

    // now to execute all the commands
    for(unsigned i = 0; i < cmds.size(); ++i)
    {
      int exitStatus = 0;
      char* arg = cmds[i].args[0];
      if (strcmp(arg, "exit") == 0)
      {
        ext = true;
        break;
      }
      char** argv = new char*[cmds[i].args.size()];
      for(unsigned j = 0; j < cmds[i].args.size(); ++j)
      {
        argv[j] = cmds[i].args[j];
      }

      // arg and argv are now prepared
      pid_t pid = fork();
      if (pid == -1)
      {
        perror("fork");
        exit(1);
      }
      else if (pid == 0) // child process
      {
        if (execvp(arg, argv) == -1)
        {
          // if there's a return value, there was a problem
          // -1 indicates a problem, specifically
          perror("execvp");
          exit(1);
        }
      }
      else // parent process
      {
        if (waitpid(pid, &exitStatus, 0) == -1)
        {
          perror("waitpid");
          exit(1);
        }
      }
      if (!exitStatus) // all is good (0)
      {
        while (i < cmds.size() && cmds[i].connector == OR)
        {
          ++i;
        }
      }
      else // last command failed
      {
        while (i < cmds.size() && cmds[i].connector == AND)
        {
          ++i;
        }
      }
    }

    /* debugging code
    for(unsigned i = 0; i < cmds.size(); ++i)
    {
      printf("Command %u:\n", i);
      for(unsigned j = 0; j < cmds[i].args.size(); ++j)
      {
        printf("\t\"%s\"\n", cmds[i].args[j]);
      }
      switch(cmds[i].connector)
      {
        case AND:
          printf("\t&&\n");
          break;
        case OR:
          printf("\t||\n");
          break;
        case SEMI:
          printf("\t;\n");
          break;
        case NONE:
          printf("\tNo connector\n");
          break;
        default:
          printf("\tERROR: no valid connector specified\n");
      }
    }
    */

    // deallocate allocated memory
    for(unsigned i = 0; i < cmds.size(); ++i)
    {
      for(unsigned j = 0; j < cmds[i].args.size(); ++j)
      {
        delete[] cmds[i].args[j];
      }
    }
  }
  return 0;
}

<commit_msg>added goodbye message<commit_after>#include <cstdio>
#include <cstdlib>
#include <cctype>
#include <cstring>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <vector>
#include <string>
#include <iostream>

#include "functions.h"

int main(int argc, char** argv)
{
  // print welcome message and prompt
  printf("Welcome to rshell!\n");

  bool ext = false;

  while (!ext)
  {
    // holds a single command and its arguments
    Command cmd;
    // holds multiple commands
    std::vector<Command> cmds;
    // hold a raw line of input
    std::string line;

    // print prompt and get a line of text (done in condition)
    printf("$ ");
    getline(std::cin, line);

    // look for comments
    if (line.find("#") != std::string::npos)
    {
      // remove them if necessary (they're useless)
      line = line.substr(0, line.find("#"));
    }

    // remove leading whitespace
    while (line.size() > 0 && (line[0] == ' ' || line[0] == ';'))
    {
      line = line.substr(1, line.size() - 1);
    }

    // adding this makes parsing easier
    line += "; ";

    if (std::cin.fail())
    {
      printf("\nGoodbye!\n");
      exit(0);
    }

    int mode = GETWORD;
    unsigned begin = 0;

    // prepare cmd
    cmd.connector = NONE;

    // syntax error flag
    bool se = false;

    // starts with a connector? I don't think so
    if (line.size() > 0 && isConn(line[0]) && line[0] != ';')
    {
      se = true;
    }

    // handle the input
    for(unsigned i = 0; i < line.size() && !se; ++i)
    {
      bool con   = isConn(line[i]);
      bool space = isspace(line[i]);

      // if we're getting a word and there's a whitespace or connector here
      if (mode == GETWORD && (space || con))
      {
        // chunk the last term and throw it into the vector
        char* c = stocstr(line.substr(begin, i - begin));
        if (strlen(c) > 0)
        {
          cmd.args.push_back(c);
        }
        else
        {
          // only happens when nothing is entered. breaks so nothing more happens
          break;
        }

        if (space)
        {
          mode = TRIMSPACE;
        }
        else // it's a connector
        {
          handleCon(cmds, cmd, line, mode, begin, i, se);
        }
      }
      else if (mode == TRIMSPACE && (!space || con))
      {
        if (con && cmd.args.empty())
        {
          if (line[i] != ';')
          {
            se = true;
          }
        }
        else if (con)
        {
          handleCon(cmds, cmd, line, mode, begin, i, se);
        }
        else
        {
          mode = GETWORD;
          begin = i;
        }
      }
      else if (mode == HANDLESEMI && line[i] != ';')
      {
        if (isConn(line[i]))
        {
          se = true;
        }
        else if (isspace(line[i]))
        {
          mode = TRIMSPACE;
        }
        else // it's a word
        {
          mode = GETWORD;
          begin = i;
        }
      }
    }

    // if the last command has a continuation connector, syntax error
    if (cmds.size() > 0 && (cmds[cmds.size() - 1].connector == AND
                        ||  cmds[cmds.size() - 1].connector == OR))
    {
      se = true;
    }

    // if there was a syntax error
    if (se)
    {
      printf("Syntax error\n");
      continue;
    }

    // now to execute all the commands
    for(unsigned i = 0; i < cmds.size(); ++i)
    {
      int exitStatus = 0;
      char* arg = cmds[i].args[0];
      if (strcmp(arg, "exit") == 0)
      {
        ext = true;
        break;
      }
      char** argv = new char*[cmds[i].args.size()];
      for(unsigned j = 0; j < cmds[i].args.size(); ++j)
      {
        argv[j] = cmds[i].args[j];
      }

      // arg and argv are now prepared
      pid_t pid = fork();
      if (pid == -1)
      {
        perror("fork");
        exit(1);
      }
      else if (pid == 0) // child process
      {
        if (execvp(arg, argv) == -1)
        {
          // if there's a return value, there was a problem
          // -1 indicates a problem, specifically
          perror("execvp");
          exit(1);
        }
      }
      else // parent process
      {
        if (waitpid(pid, &exitStatus, 0) == -1)
        {
          perror("waitpid");
          exit(1);
        }
      }
      if (!exitStatus) // all is good (0)
      {
        while (i < cmds.size() && cmds[i].connector == OR)
        {
          ++i;
        }
      }
      else // last command failed
      {
        while (i < cmds.size() && cmds[i].connector == AND)
        {
          ++i;
        }
      }
    }

    /* debugging code
    for(unsigned i = 0; i < cmds.size(); ++i)
    {
      printf("Command %u:\n", i);
      for(unsigned j = 0; j < cmds[i].args.size(); ++j)
      {
        printf("\t\"%s\"\n", cmds[i].args[j]);
      }
      switch(cmds[i].connector)
      {
        case AND:
          printf("\t&&\n");
          break;
        case OR:
          printf("\t||\n");
          break;
        case SEMI:
          printf("\t;\n");
          break;
        case NONE:
          printf("\tNo connector\n");
          break;
        default:
          printf("\tERROR: no valid connector specified\n");
      }
    }
    */

    // deallocate allocated memory
    for(unsigned i = 0; i < cmds.size(); ++i)
    {
      for(unsigned j = 0; j < cmds[i].args.size(); ++j)
      {
        delete[] cmds[i].args[j];
      }
    }
  }
  printf("Goodbye!\n");
  return 0;
}

<|endoftext|>


<commit_before>#define DEBUG 1
/**
 * File    : C.cpp
 * Author  : Kazune Takahashi
 * Created : 6/15/2019, 9:15:16 PM
 * Powered by Visual Studio Code
 */
#include <iostream>
#include <iomanip>
#include <algorithm>
#include <vector>
#include <string>
#include <complex>
#include <tuple>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <bitset>
#include <functional>
#include <random>
#include <chrono>
#include <cctype>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
using namespace std;
#define maxs(x, y) (x = max(x, y))
#define mins(x, y) (x = min(x, y))
typedef long long ll;
void Yes()
{
  cout << "Yes" << endl;
  exit(0);
}
void No()
{
  cout << "No" << endl;
  exit(0);
}
const int MAX_SIZE = 1000010;
class mint
{
public:
  static ll MOD;
  ll x;
  mint() : x(0) {}
  mint(ll x) : x(x % MOD) {}
  mint operator-() const { return mint(0) - *this; }
  mint &operator+=(const mint &a)
  {
    if ((x += a.x) >= MOD)
    {
      x -= MOD;
    }
    return *this;
  }
  mint &operator-=(const mint &a) { return *this += -a; }
  mint &operator*=(const mint &a)
  {
    (x *= a.x) %= MOD;
    return *this;
  }
  mint &operator/=(const mint &a) { return (*this *= power(MOD - 2)); }
  mint operator+(const mint &a) const { return mint(*this) += a; }
  mint operator-(const mint &a) const { return mint(*this) -= a; }
  mint operator*(const mint &a) const { return mint(*this) *= a; }
  mint operator/(const mint &a) const { return mint(*this) /= a; }
  bool operator<(const mint &a) const { return x < a.x; }
  bool operator==(const mint &a) const { return x == a.x; }
  const mint power(ll N)
  {
    if (N == 0)
    {
      return 1;
    }
    else if (N % 2 == 1)
    {
      return *this * power(N - 1);
    }
    else
    {
      mint half = power(N / 2);
      return half * half;
    }
  }
};
ll mint::MOD = 1e9 + 7;
istream &operator>>(istream &stream, mint &a) { return stream >> a.x; }
ostream &operator<<(ostream &stream, const mint &a) { return stream << a.x; }
mint inv[MAX_SIZE];
mint fact[MAX_SIZE];
mint factinv[MAX_SIZE];
void init()
{
  inv[1] = 1;
  for (int i = 2; i < MAX_SIZE; i++)
  {
    inv[i] = (-inv[mint::MOD % i]) * (mint::MOD / i);
  }
  fact[0] = factinv[0] = 1;
  for (int i = 1; i < MAX_SIZE; i++)
  {
    fact[i] = mint(i) * fact[i - 1];
    factinv[i] = inv[i] * factinv[i - 1];
  }
}
mint choose(int n, int k)
{
  if (n >= 0 && k >= 0 && n - k >= 0)
  {
    return fact[n] * factinv[k] * factinv[n - k];
  }
  return 0;
}
ll gcd(ll x, ll y) { return y ? gcd(y, x % y) : x; }
// const double epsilon = 1e-10;
// const ll infty = 1000000000000000LL;
// const int dx[4] = {1, 0, -1, 0};
// const int dy[4] = {0, 1, 0, -1};

int N;
ll A[100010];

void solve()
{
  int ind = 0;
  for (auto i = 0; i < N; i++)
  {
    if (A[i] > 0)
    {
      ind = i;
      break;
    }
  }
  ll ans = 0;
  for (auto i = 0; i < N; i++)
  {
    ans += abs(A[i]);
  }
  cout << ans << endl;
  ll now = A[0];
  for (auto i = ind; i < N - 1; i++)
  {
    cout << now << " " << A[i] << endl;
    now -= A[i];
  }
  ll now2 = A[N - 1];
  for (auto i = 1; i < ind; i++)
  {
    cout << now2 << " " << A[i] << endl;
    now2 -= A[i];
  }
  cout << now2 << " " << now << endl;
  assert(now2 - now == ans);
}

void solve_plus()
{
  ll ans = -A[0];
  for (auto i = 1; i < N; i++)
  {
    ans += abs(A[i]);
  }
  cout << ans << endl;
  ll now = A[0];
  for (auto i = 1; i < N - 1; i++)
  {
    cout << now << " " << A[i] << endl;
    now -= A[i];
  }
  cout << A[N - 1] << " " << now << endl;
  assert(A[N - 1] - now == ans);
}

void solve_minus()
{
  ll ans = A[N - 1];
  for (auto i = 0; i < N - 1; i++)
  {
    ans += abs(A[i]);
  }
  cout << ans << endl;
  ll now = A[N - 1];
  for (auto i = 0; i < N - 1; i++)
  {
    cout << now << " " << A[i] << endl;
    now -= A[i];
  }
  assert(now == ans);
}

int main()
{
  // init();
  cin >> N;
  for (auto i = 0; i < N; i++)
  {
    cin >> A[i];
  }
  sort(A, A + N);
  if (A[0] > 0)
  {
    solve_plus();
  }
  else if (A[N - 1] < 0)
  {
    solve_minus();
  }
  else
  {
    solve();
  }
}<commit_msg>submit C.cpp to 'C - Successive Subtraction' (diverta2019-2) [C++14 (GCC 5.4.1)]<commit_after>#define DEBUG 1
/**
 * File    : C.cpp
 * Author  : Kazune Takahashi
 * Created : 6/15/2019, 9:15:16 PM
 * Powered by Visual Studio Code
 */
#include <iostream>
#include <iomanip>
#include <algorithm>
#include <vector>
#include <string>
#include <complex>
#include <tuple>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <bitset>
#include <functional>
#include <random>
#include <chrono>
#include <cctype>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
using namespace std;
#define maxs(x, y) (x = max(x, y))
#define mins(x, y) (x = min(x, y))
typedef long long ll;
void Yes()
{
  cout << "Yes" << endl;
  exit(0);
}
void No()
{
  cout << "No" << endl;
  exit(0);
}
const int MAX_SIZE = 1000010;
class mint
{
public:
  static ll MOD;
  ll x;
  mint() : x(0) {}
  mint(ll x) : x(x % MOD) {}
  mint operator-() const { return mint(0) - *this; }
  mint &operator+=(const mint &a)
  {
    if ((x += a.x) >= MOD)
    {
      x -= MOD;
    }
    return *this;
  }
  mint &operator-=(const mint &a) { return *this += -a; }
  mint &operator*=(const mint &a)
  {
    (x *= a.x) %= MOD;
    return *this;
  }
  mint &operator/=(const mint &a) { return (*this *= power(MOD - 2)); }
  mint operator+(const mint &a) const { return mint(*this) += a; }
  mint operator-(const mint &a) const { return mint(*this) -= a; }
  mint operator*(const mint &a) const { return mint(*this) *= a; }
  mint operator/(const mint &a) const { return mint(*this) /= a; }
  bool operator<(const mint &a) const { return x < a.x; }
  bool operator==(const mint &a) const { return x == a.x; }
  const mint power(ll N)
  {
    if (N == 0)
    {
      return 1;
    }
    else if (N % 2 == 1)
    {
      return *this * power(N - 1);
    }
    else
    {
      mint half = power(N / 2);
      return half * half;
    }
  }
};
ll mint::MOD = 1e9 + 7;
istream &operator>>(istream &stream, mint &a) { return stream >> a.x; }
ostream &operator<<(ostream &stream, const mint &a) { return stream << a.x; }
mint inv[MAX_SIZE];
mint fact[MAX_SIZE];
mint factinv[MAX_SIZE];
void init()
{
  inv[1] = 1;
  for (int i = 2; i < MAX_SIZE; i++)
  {
    inv[i] = (-inv[mint::MOD % i]) * (mint::MOD / i);
  }
  fact[0] = factinv[0] = 1;
  for (int i = 1; i < MAX_SIZE; i++)
  {
    fact[i] = mint(i) * fact[i - 1];
    factinv[i] = inv[i] * factinv[i - 1];
  }
}
mint choose(int n, int k)
{
  if (n >= 0 && k >= 0 && n - k >= 0)
  {
    return fact[n] * factinv[k] * factinv[n - k];
  }
  return 0;
}
ll gcd(ll x, ll y) { return y ? gcd(y, x % y) : x; }
// const double epsilon = 1e-10;
// const ll infty = 1000000000000000LL;
// const int dx[4] = {1, 0, -1, 0};
// const int dy[4] = {0, 1, 0, -1};

int N;
ll A[100010];

void solve()
{
  int ind = 0;
  for (auto i = 0; i < N; i++)
  {
    if (A[i] > 0)
    {
      ind = i;
      break;
    }
  }
  ll ans = 0;
  for (auto i = 0; i < N; i++)
  {
    ans += abs(A[i]);
  }
  cout << ans << endl;
  ll now = A[0];
  for (auto i = ind; i < N - 1; i++)
  {
    cout << now << " " << A[i] << endl;
    now -= A[i];
  }
  ll now2 = A[N - 1];
  for (auto i = 1; i < ind; i++)
  {
    cout << now2 << " " << A[i] << endl;
    now2 -= A[i];
  }
  cout << now2 << " " << now << endl;
  assert(now2 - now == ans);
}

void solve_plus()
{
  ll ans = -A[0];
  for (auto i = 1; i < N; i++)
  {
    ans += abs(A[i]);
  }
  cout << ans << endl;
  ll now = A[0];
  for (auto i = 1; i < N - 1; i++)
  {
    cout << now << " " << A[i] << endl;
    now -= A[i];
  }
  cout << A[N - 1] << " " << now << endl;
  assert(A[N - 1] - now == ans);
}

void solve_minus()
{
  ll ans = A[N - 1];
  for (auto i = 0; i < N - 1; i++)
  {
    ans += abs(A[i]);
  }
  cout << ans << endl;
  ll now = A[N - 1];
  for (auto i = 0; i < N - 1; i++)
  {
    cout << now << " " << A[i] << endl;
    now -= A[i];
  }
  assert(now == ans);
}

int main()
{
  // init();
  cin >> N;
  for (auto i = 0; i < N; i++)
  {
    cin >> A[i];
  }
  sort(A, A + N);
  if (A[0] >= 0)
  {
    solve_plus();
  }
  else if (A[N - 1] <= 0)
  {
    solve_minus();
  }
  else
  {
    solve();
  }
}<|endoftext|>


<commit_before>// Given an integer n, count the total number of digit 1 appearing in all
// non-negative integers less than or equal to n.
// For example:
// Given n = 13,
// Return 6, because digit 1 occurred in the following numbers: 1, 10, 11, 12,
// 13.

class Solution {
  public:
    int countDigitOne(int n) {
        if (n < 0)
            return 0;

        int cnt = 0;

        for (int i = 1; i <= n; i *= 10) {
            // at each loop, add contribution of this digit
            // e.g. for 1124
            // 1st loop, we add 1 + 1 * (n/10) (0001, 0011, 0021...1111)
            // 2nd loop, we add 10 + 10 * (n/100) (010-019, 110-119...1010-1019)
            // 3rd loop, we add 25 + 100 (100-199) for 100 digit contribution
            // 4th loop, we add 125 for 1000 digit contribution
            int digit = (n / i) % 10;
            if (digit == 1)
                cnt += n % i + 1;
            else if (digit > 1)
                cnt += i;
            cnt += i * (n / i / 10);
            if (INT_MAX / i < 10)
                break;
        }

        return cnt;
    }
};<commit_msg>new version<commit_after>// Given an integer n, count the total number of digit 1 appearing in all
// non-negative integers less than or equal to n.
// For example:
// Given n = 13,
// Return 6, because digit 1 occurred in the following numbers: 1, 10, 11, 12,
// 13.

class Solution {
  public:
    int countDigitOne(int n) {
        if (n < 0)
            return 0;

        int cnt = 0;

        for (int i = 1; i <= n; i *= 10) {
            // at each loop, add contribution of this digit
            // e.g. for 1124
            // 1st loop, we add 1 + 1 * (n/10) (0001, 0011, 0021...1111)
            // 2nd loop, we add 10 + 10 * (n/100) (010-019, 110-119...1010-1019)
            // 3rd loop, we add 25 + 100 (100-199) for 100 digit contribution
            // 4th loop, we add 125 for 1000 digit contribution
            int digit = (n / i) % 10;
            if (digit == 1)
                cnt += n % i + 1;
            else if (digit > 1)
                cnt += i;
            cnt += i * (n / i / 10);

            if (INT_MAX / i < 10)
                break;
        }

        return cnt;
    }
};<|endoftext|>


<commit_before>#include <gtest/gtest.h>
#include <ROOT/TVec.hxx>
#include <vector>
#include <sstream>

template <typename T, typename V>
void CheckEqual(const T &a, const V &b, std::string_view msg = "")
{
   const auto asize = a.size();
   const auto bsize = b.size();
   EXPECT_EQ(asize, bsize);
   for (unsigned int i = 0; i < asize; ++i) {
      EXPECT_EQ(a[i], b[i]) << msg;
   }
}

TEST(VecOps, DefaultCtor)
{
   ROOT::Experimental::VecOps::TVec<int> v;
   EXPECT_EQ(v.size(), 0u);
}

TEST(VecOps, InitListCtor)
{
   ROOT::Experimental::VecOps::TVec<int> v{1, 2, 3};
   EXPECT_EQ(v.size(), 3u);
   EXPECT_EQ(v[0], 1);
   EXPECT_EQ(v[1], 2);
   EXPECT_EQ(v[2], 3);
}

TEST(VecOps, CopyCtor)
{
   ROOT::Experimental::VecOps::TVec<int> v1{1, 2, 3};
   ROOT::Experimental::VecOps::TVec<int> v2(v1);
   EXPECT_EQ(v1.size(), 3u);
   EXPECT_EQ(v2.size(), 3u);
   EXPECT_EQ(v2[0], 1);
   EXPECT_EQ(v2[1], 2);
   EXPECT_EQ(v2[2], 3);
}

TEST(VecOps, MoveCtor)
{
   ROOT::Experimental::VecOps::TVec<int> v1{1, 2, 3};
   ROOT::Experimental::VecOps::TVec<int> v2(std::move(v1));
   EXPECT_EQ(v1.size(), 0u);
   EXPECT_EQ(v2.size(), 3u);
}

TEST(VecOps, MathScalar)
{
   using namespace ROOT::Experimental::VecOps;
   TVec<double> ref{1, 2, 3};
   TVec<double> v(ref);
   int scalar = 3;
   auto plus = v + scalar;
   auto minus = v - scalar;
   auto mult = v * scalar;
   auto div = v / scalar;

   CheckEqual(plus, ref + scalar);
   CheckEqual(minus, ref - scalar);
   CheckEqual(mult, ref * scalar);
   CheckEqual(div, ref / scalar);

   // The same with views
   ROOT::Experimental::VecOps::TVec<double> w(ref.data(), ref.size());
   plus = w + scalar;
   minus = w - scalar;
   mult = w * scalar;
   div = w / scalar;

   CheckEqual(plus, ref + scalar);
   CheckEqual(minus, ref - scalar);
   CheckEqual(mult, ref * scalar);
   CheckEqual(div, ref / scalar);
}

TEST(VecOps, MathScalarInPlace)
{
   using namespace ROOT::Experimental::VecOps;
   TVec<double> ref{1, 2, 3};
   const TVec<double> v(ref);
   int scalar = 3;
   auto plus = v;
   plus += scalar;
   auto minus = v;
   minus -= scalar;
   auto mult = v;
   mult *= scalar;
   auto div = v;
   div /= scalar;

   CheckEqual(plus, ref + scalar);
   CheckEqual(minus, ref - scalar);
   CheckEqual(mult, ref * scalar);
   CheckEqual(div, ref / scalar);
}

TEST(VecOps, MathVector)
{
   using namespace ROOT::Experimental::VecOps;
   TVec<double> ref{1, 2, 3};
   TVec<double> vec{3, 4, 5};
   TVec<double> v(ref);
   auto plus = v + vec;
   auto minus = v - vec;
   auto mult = v * vec;
   auto div = v / vec;

   CheckEqual(plus, ref + vec);
   CheckEqual(minus, ref - vec);
   CheckEqual(mult, ref * vec);
   CheckEqual(div, ref / vec);

   // The same with 1 view
   ROOT::Experimental::VecOps::TVec<double> w(ref.data(), ref.size());
   plus = w + vec;
   minus = w - vec;
   mult = w * vec;
   div = w / vec;

   CheckEqual(plus, ref + vec);
   CheckEqual(minus, ref - vec);
   CheckEqual(mult, ref * vec);
   CheckEqual(div, ref / vec);

   // The same with 2 views
   ROOT::Experimental::VecOps::TVec<double> w2(ref.data(), ref.size());
   plus = w + w2;
   minus = w - w2;
   mult = w * w2;
   div = w / w2;

   CheckEqual(plus, ref + w2);
   CheckEqual(minus, ref - w2);
   CheckEqual(mult, ref * w2);
   CheckEqual(div, ref / w2);
}

TEST(VecOps, MathVectorInPlace)
{
   using namespace ROOT::Experimental::VecOps;
   TVec<double> ref{1, 2, 3};
   TVec<double> vec{3, 4, 5};
   TVec<double> v(ref);
   auto plus = v;
   plus += vec;
   auto minus = v;
   minus -= vec;
   auto mult = v;
   mult *= vec;
   auto div = v;
   div /= vec;

   CheckEqual(plus, ref + vec);
   CheckEqual(minus, ref - vec);
   CheckEqual(mult, ref * vec);
   CheckEqual(div, ref / vec);
}

TEST(VecOps, Filter)
{
   using namespace ROOT::Experimental::VecOps;
   TVec<int> v{0, 1, 2, 3, 4, 5};
   const std::vector<int> vEvenRef{0, 2, 4};
   const std::vector<int> vOddRef{1, 3, 5};
   auto vEven = v[v % 2 == 0];
   auto vOdd = v[v % 2 == 1];
   CheckEqual(vEven, vEvenRef, "Even check");
   CheckEqual(vOdd, vOddRef, "Odd check");

   // now with the helper function
   vEven = Filter(v, [](int i) { return 0 == i % 2; });
   vOdd = Filter(v, [](int i) { return 1 == i % 2; });
   CheckEqual(vEven, vEvenRef, "Even check");
   CheckEqual(vOdd, vOddRef, "Odd check");
}

template <typename T, typename V>
std::string PrintTVec(ROOT::Experimental::VecOps::TVec<T> v, V w)
{
   using namespace ROOT::Experimental::VecOps;
   std::stringstream ss;
   ss << v << " " << w << std::endl;
   ss << v + w << std::endl;
   ss << v - w << std::endl;
   ss << v * w << std::endl;
   ss << v / w << std::endl;
   ss << (v > w) << std::endl;
   ss << (v >= w) << std::endl;
   ss << (v == w) << std::endl;
   ss << (v <= w) << std::endl;
   ss << (v < w) << std::endl;
   return ss.str();
}

TEST(VecOps, PrintOps)
{
   using namespace ROOT::Experimental::VecOps;
   TVec<int> ref{1, 2, 3};
   TVec<int> v(ref);

   auto ref0 = R"ref0({ 1, 2, 3 } 2
{ 3, 4, 5 }
{ -1, 0, 1 }
{ 2, 4, 6 }
{ 0.5, 1, 1.5 }
{ 0, 0, 1 }
{ 0, 1, 1 }
{ 0, 1, 0 }
{ 1, 1, 0 }
{ 1, 0, 0 }
)ref0";
   auto t0 = PrintTVec(v, 2.);
   EXPECT_STREQ(t0.c_str(), ref0);
   auto ref1 = R"ref1({ 1, 2, 3 } { 3, 4, 5 }
{ 4, 6, 8 }
{ -2, -2, -2 }
{ 3, 8, 15 }
{ 0, 0, 0 }
{ 0, 0, 0 }
{ 0, 0, 0 }
{ 0, 0, 0 }
{ 1, 1, 1 }
{ 1, 1, 1 }
)ref1";
   auto t1 = PrintTVec(v, ref + 2);
   EXPECT_STREQ(t1.c_str(), ref1);

   ROOT::Experimental::VecOps::TVec<int> w(ref.data(), ref.size());

   auto ref2 = R"ref2({ 1, 2, 3 } 2
{ 3, 4, 5 }
{ -1, 0, 1 }
{ 2, 4, 6 }
{ 0.5, 1, 1.5 }
{ 0, 0, 1 }
{ 0, 1, 1 }
{ 0, 1, 0 }
{ 1, 1, 0 }
{ 1, 0, 0 }
)ref2";
   auto t2 = PrintTVec(v, 2.);
   EXPECT_STREQ(t2.c_str(), ref2);

   auto ref3 = R"ref3({ 1, 2, 3 } { 3, 4, 5 }
{ 4, 6, 8 }
{ -2, -2, -2 }
{ 3, 8, 15 }
{ 0, 0, 0 }
{ 0, 0, 0 }
{ 0, 0, 0 }
{ 0, 0, 0 }
{ 1, 1, 1 }
{ 1, 1, 1 }
)ref3";
   auto t3 = PrintTVec(v, ref + 2);
   EXPECT_STREQ(t3.c_str(), ref3);
}

TEST(VecOps, MathFuncs)
{
   using namespace ROOT::Experimental::VecOps;
   TVec<double> v{1, 2, 3};
   CheckEqual(sqrt(v), Map(v, [](double x) { return std::sqrt(x); }), " error checking math function sqrt");
   CheckEqual(log(v), Map(v, [](double x) { return std::log(x); }), " error checking math function log");
   CheckEqual(sin(v), Map(v, [](double x) { return std::sin(x); }), " error checking math function sin");
   CheckEqual(cos(v), Map(v, [](double x) { return std::cos(x); }), " error checking math function cos");
   CheckEqual(tan(v), Map(v, [](double x) { return std::tan(x); }), " error checking math function tan");
   CheckEqual(atan(v), Map(v, [](double x) { return std::atan(x); }), " error checking math function atan");
   CheckEqual(sinh(v), Map(v, [](double x) { return std::sinh(x); }), " error checking math function sinh");
   CheckEqual(cosh(v), Map(v, [](double x) { return std::cosh(x); }), " error checking math function cosh");
   CheckEqual(tanh(v), Map(v, [](double x) { return std::tanh(x); }), " error checking math function tanh");
   CheckEqual(asinh(v), Map(v, [](double x) { return std::asinh(x); }), " error checking math function asinh");
   CheckEqual(acosh(v), Map(v, [](double x) { return std::acosh(x); }), " error checking math function acosh");
   v /= 10.;
   CheckEqual(asin(v), Map(v, [](double x) { return std::asin(x); }), " error checking math function asin");
   CheckEqual(acos(v), Map(v, [](double x) { return std::acos(x); }), " error checking math function acos");
   CheckEqual(atanh(v), Map(v, [](double x) { return std::atanh(x); }), " error checking math function atanh");
}

TEST(VecOps, PhysicsSelections)
{
   // We emulate 8 muons
   ROOT::Experimental::VecOps::TVec<short> mu_charge{1, 1, -1, -1, -1, 1, 1, -1};
   ROOT::Experimental::VecOps::TVec<float> mu_pt{56, 45, 32, 24, 12, 8, 7, 6.2};
   ROOT::Experimental::VecOps::TVec<float> mu_eta{3.1, -.2, -1.1, 1, 4.1, 1.6, 2.4, -.5};

   // Pick the pt of the muons with a pt greater than 10, an eta between -2 and 2 and a negative charge
   // or the ones with a pt > 20, outside the eta range -2:2 and with positive charge
   auto goodMuons_pt = mu_pt[(mu_pt > 10.f && abs(mu_eta) <= 2.f && mu_charge == -1) ||
                             (mu_pt > 15.f && abs(mu_eta) > 2.f && mu_charge == 1)];
   ROOT::Experimental::VecOps::TVec<float> goodMuons_pt_ref = {56, 32, 24};
   CheckEqual(goodMuons_pt, goodMuons_pt_ref, "Muons quality cut");
}
<commit_msg>[VecOps] Fix vector initialisation on windows<commit_after>#include <gtest/gtest.h>
#include <ROOT/TVec.hxx>
#include <vector>
#include <sstream>

template <typename T, typename V>
void CheckEqual(const T &a, const V &b, std::string_view msg = "")
{
   const auto asize = a.size();
   const auto bsize = b.size();
   EXPECT_EQ(asize, bsize);
   for (unsigned int i = 0; i < asize; ++i) {
      EXPECT_EQ(a[i], b[i]) << msg;
   }
}

TEST(VecOps, DefaultCtor)
{
   ROOT::Experimental::VecOps::TVec<int> v;
   EXPECT_EQ(v.size(), 0u);
}

TEST(VecOps, InitListCtor)
{
   ROOT::Experimental::VecOps::TVec<int> v{1, 2, 3};
   EXPECT_EQ(v.size(), 3u);
   EXPECT_EQ(v[0], 1);
   EXPECT_EQ(v[1], 2);
   EXPECT_EQ(v[2], 3);
}

TEST(VecOps, CopyCtor)
{
   ROOT::Experimental::VecOps::TVec<int> v1{1, 2, 3};
   ROOT::Experimental::VecOps::TVec<int> v2(v1);
   EXPECT_EQ(v1.size(), 3u);
   EXPECT_EQ(v2.size(), 3u);
   EXPECT_EQ(v2[0], 1);
   EXPECT_EQ(v2[1], 2);
   EXPECT_EQ(v2[2], 3);
}

TEST(VecOps, MoveCtor)
{
   ROOT::Experimental::VecOps::TVec<int> v1{1, 2, 3};
   ROOT::Experimental::VecOps::TVec<int> v2(std::move(v1));
   EXPECT_EQ(v1.size(), 0u);
   EXPECT_EQ(v2.size(), 3u);
}

TEST(VecOps, MathScalar)
{
   using namespace ROOT::Experimental::VecOps;
   TVec<double> ref{1, 2, 3};
   TVec<double> v(ref);
   int scalar = 3;
   auto plus = v + scalar;
   auto minus = v - scalar;
   auto mult = v * scalar;
   auto div = v / scalar;

   CheckEqual(plus, ref + scalar);
   CheckEqual(minus, ref - scalar);
   CheckEqual(mult, ref * scalar);
   CheckEqual(div, ref / scalar);

   // The same with views
   ROOT::Experimental::VecOps::TVec<double> w(ref.data(), ref.size());
   plus = w + scalar;
   minus = w - scalar;
   mult = w * scalar;
   div = w / scalar;

   CheckEqual(plus, ref + scalar);
   CheckEqual(minus, ref - scalar);
   CheckEqual(mult, ref * scalar);
   CheckEqual(div, ref / scalar);
}

TEST(VecOps, MathScalarInPlace)
{
   using namespace ROOT::Experimental::VecOps;
   TVec<double> ref{1, 2, 3};
   const TVec<double> v(ref);
   int scalar = 3;
   auto plus = v;
   plus += scalar;
   auto minus = v;
   minus -= scalar;
   auto mult = v;
   mult *= scalar;
   auto div = v;
   div /= scalar;

   CheckEqual(plus, ref + scalar);
   CheckEqual(minus, ref - scalar);
   CheckEqual(mult, ref * scalar);
   CheckEqual(div, ref / scalar);
}

TEST(VecOps, MathVector)
{
   using namespace ROOT::Experimental::VecOps;
   TVec<double> ref{1, 2, 3};
   TVec<double> vec{3, 4, 5};
   TVec<double> v(ref);
   auto plus = v + vec;
   auto minus = v - vec;
   auto mult = v * vec;
   auto div = v / vec;

   CheckEqual(plus, ref + vec);
   CheckEqual(minus, ref - vec);
   CheckEqual(mult, ref * vec);
   CheckEqual(div, ref / vec);

   // The same with 1 view
   ROOT::Experimental::VecOps::TVec<double> w(ref.data(), ref.size());
   plus = w + vec;
   minus = w - vec;
   mult = w * vec;
   div = w / vec;

   CheckEqual(plus, ref + vec);
   CheckEqual(minus, ref - vec);
   CheckEqual(mult, ref * vec);
   CheckEqual(div, ref / vec);

   // The same with 2 views
   ROOT::Experimental::VecOps::TVec<double> w2(ref.data(), ref.size());
   plus = w + w2;
   minus = w - w2;
   mult = w * w2;
   div = w / w2;

   CheckEqual(plus, ref + w2);
   CheckEqual(minus, ref - w2);
   CheckEqual(mult, ref * w2);
   CheckEqual(div, ref / w2);
}

TEST(VecOps, MathVectorInPlace)
{
   using namespace ROOT::Experimental::VecOps;
   TVec<double> ref{1, 2, 3};
   TVec<double> vec{3, 4, 5};
   TVec<double> v(ref);
   auto plus = v;
   plus += vec;
   auto minus = v;
   minus -= vec;
   auto mult = v;
   mult *= vec;
   auto div = v;
   div /= vec;

   CheckEqual(plus, ref + vec);
   CheckEqual(minus, ref - vec);
   CheckEqual(mult, ref * vec);
   CheckEqual(div, ref / vec);
}

TEST(VecOps, Filter)
{
   using namespace ROOT::Experimental::VecOps;
   TVec<int> v{0, 1, 2, 3, 4, 5};
   const std::vector<int> vEvenRef{0, 2, 4};
   const std::vector<int> vOddRef{1, 3, 5};
   auto vEven = v[v % 2 == 0];
   auto vOdd = v[v % 2 == 1];
   CheckEqual(vEven, vEvenRef, "Even check");
   CheckEqual(vOdd, vOddRef, "Odd check");

   // now with the helper function
   vEven = Filter(v, [](int i) { return 0 == i % 2; });
   vOdd = Filter(v, [](int i) { return 1 == i % 2; });
   CheckEqual(vEven, vEvenRef, "Even check");
   CheckEqual(vOdd, vOddRef, "Odd check");
}

template <typename T, typename V>
std::string PrintTVec(ROOT::Experimental::VecOps::TVec<T> v, V w)
{
   using namespace ROOT::Experimental::VecOps;
   std::stringstream ss;
   ss << v << " " << w << std::endl;
   ss << v + w << std::endl;
   ss << v - w << std::endl;
   ss << v * w << std::endl;
   ss << v / w << std::endl;
   ss << (v > w) << std::endl;
   ss << (v >= w) << std::endl;
   ss << (v == w) << std::endl;
   ss << (v <= w) << std::endl;
   ss << (v < w) << std::endl;
   return ss.str();
}

TEST(VecOps, PrintOps)
{
   using namespace ROOT::Experimental::VecOps;
   TVec<int> ref{1, 2, 3};
   TVec<int> v(ref);

   auto ref0 = R"ref0({ 1, 2, 3 } 2
{ 3, 4, 5 }
{ -1, 0, 1 }
{ 2, 4, 6 }
{ 0.5, 1, 1.5 }
{ 0, 0, 1 }
{ 0, 1, 1 }
{ 0, 1, 0 }
{ 1, 1, 0 }
{ 1, 0, 0 }
)ref0";
   auto t0 = PrintTVec(v, 2.);
   EXPECT_STREQ(t0.c_str(), ref0);
   auto ref1 = R"ref1({ 1, 2, 3 } { 3, 4, 5 }
{ 4, 6, 8 }
{ -2, -2, -2 }
{ 3, 8, 15 }
{ 0, 0, 0 }
{ 0, 0, 0 }
{ 0, 0, 0 }
{ 0, 0, 0 }
{ 1, 1, 1 }
{ 1, 1, 1 }
)ref1";
   auto t1 = PrintTVec(v, ref + 2);
   EXPECT_STREQ(t1.c_str(), ref1);

   ROOT::Experimental::VecOps::TVec<int> w(ref.data(), ref.size());

   auto ref2 = R"ref2({ 1, 2, 3 } 2
{ 3, 4, 5 }
{ -1, 0, 1 }
{ 2, 4, 6 }
{ 0.5, 1, 1.5 }
{ 0, 0, 1 }
{ 0, 1, 1 }
{ 0, 1, 0 }
{ 1, 1, 0 }
{ 1, 0, 0 }
)ref2";
   auto t2 = PrintTVec(v, 2.);
   EXPECT_STREQ(t2.c_str(), ref2);

   auto ref3 = R"ref3({ 1, 2, 3 } { 3, 4, 5 }
{ 4, 6, 8 }
{ -2, -2, -2 }
{ 3, 8, 15 }
{ 0, 0, 0 }
{ 0, 0, 0 }
{ 0, 0, 0 }
{ 0, 0, 0 }
{ 1, 1, 1 }
{ 1, 1, 1 }
)ref3";
   auto t3 = PrintTVec(v, ref + 2);
   EXPECT_STREQ(t3.c_str(), ref3);
}

TEST(VecOps, MathFuncs)
{
   using namespace ROOT::Experimental::VecOps;
   TVec<double> v{1, 2, 3};
   CheckEqual(sqrt(v), Map(v, [](double x) { return std::sqrt(x); }), " error checking math function sqrt");
   CheckEqual(log(v), Map(v, [](double x) { return std::log(x); }), " error checking math function log");
   CheckEqual(sin(v), Map(v, [](double x) { return std::sin(x); }), " error checking math function sin");
   CheckEqual(cos(v), Map(v, [](double x) { return std::cos(x); }), " error checking math function cos");
   CheckEqual(tan(v), Map(v, [](double x) { return std::tan(x); }), " error checking math function tan");
   CheckEqual(atan(v), Map(v, [](double x) { return std::atan(x); }), " error checking math function atan");
   CheckEqual(sinh(v), Map(v, [](double x) { return std::sinh(x); }), " error checking math function sinh");
   CheckEqual(cosh(v), Map(v, [](double x) { return std::cosh(x); }), " error checking math function cosh");
   CheckEqual(tanh(v), Map(v, [](double x) { return std::tanh(x); }), " error checking math function tanh");
   CheckEqual(asinh(v), Map(v, [](double x) { return std::asinh(x); }), " error checking math function asinh");
   CheckEqual(acosh(v), Map(v, [](double x) { return std::acosh(x); }), " error checking math function acosh");
   v /= 10.;
   CheckEqual(asin(v), Map(v, [](double x) { return std::asin(x); }), " error checking math function asin");
   CheckEqual(acos(v), Map(v, [](double x) { return std::acos(x); }), " error checking math function acos");
   CheckEqual(atanh(v), Map(v, [](double x) { return std::atanh(x); }), " error checking math function atanh");
}

TEST(VecOps, PhysicsSelections)
{
   // We emulate 8 muons
   ROOT::Experimental::VecOps::TVec<short> mu_charge{1, 1, -1, -1, -1, 1, 1, -1};
   ROOT::Experimental::VecOps::TVec<float> mu_pt{56.f, 45.f, 32.f, 24.f, 12.f, 8.f, 7.f, 6.2f};
   ROOT::Experimental::VecOps::TVec<float> mu_eta{3.1f, -.2f, -1.1f, 1.f, 4.1f, 1.6f, 2.4f, -.5f};

   // Pick the pt of the muons with a pt greater than 10, an eta between -2 and 2 and a negative charge
   // or the ones with a pt > 20, outside the eta range -2:2 and with positive charge
   auto goodMuons_pt = mu_pt[(mu_pt > 10.f && abs(mu_eta) <= 2.f && mu_charge == -1) ||
                             (mu_pt > 15.f && abs(mu_eta) > 2.f && mu_charge == 1)];
   ROOT::Experimental::VecOps::TVec<float> goodMuons_pt_ref = {56.f, 32.f, 24.f};
   CheckEqual(goodMuons_pt, goodMuons_pt_ref, "Muons quality cut");
}
<|endoftext|>