<commit_before>/*
The MIT License (MIT)

Copyright (c) 2015 Marko Zivanovic

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 "stdafx.h"

#include <algorithm>
#include <functional>
#include <map>
#include "semver200.h"

using namespace std;

namespace version {

	namespace {

		// Compare normal version identifiers.
		int compare_normal(const Version_data& l, const Version_data& r) {
			if (l.major > r.major) return 1;
			if (l.major < r.major) return -1;
			if (l.minor > r.minor) return 1;
			if (l.minor < r.minor) return -1;
			if (l.patch > r.patch) return 1;
			if (l.patch < r.patch) return -1;
			return 0;
		}

		// Compare alphanumeric prerelease identifiers.
		inline int cmp_alnum_prerel_ids(const string& l, const string& r) {
			auto cmp = l.compare(r);
			if (cmp == 0) {
				return cmp;
			} else {
				return cmp > 0 ? 1 : -1;
			}
		}

		// Compare numeric prerelease identifiers.
		inline int cmp_num_prerel_ids(const string& l, const string& r) {
			long long li = stoll(l);
			long long ri = stoll(r);
			if (li == ri) return 0;
			return li > ri ? 1 : -1;
		}

		using Prerel_type_pair = pair<Id_type, Id_type>;
		using Prerel_id_comparator = function<int(const string&, const string&)>;
		const map<Prerel_type_pair, Prerel_id_comparator> comparators = {
			{ { Id_type::alnum, Id_type::alnum }, cmp_alnum_prerel_ids },
			{ { Id_type::alnum, Id_type::num }, [](const string&, const string&) {return 1;} },
			{ { Id_type::num, Id_type::alnum }, [](const string&, const string&) {return -1;} },
			{ { Id_type::num, Id_type::num }, cmp_num_prerel_ids }
		};

		// Compare prerelease identifiers based on their types.
		inline int compare_prerel_identifiers(const Prerelease_identifier& l, const Prerelease_identifier& r) {
			auto cmp = comparators.at({ l.second, r.second });
			return cmp(l.first, r.first);
		}

		inline int cmp_rel_prerel(const Prerelease_identifiers& l, const Prerelease_identifiers& r) {
			if (l.empty() && !r.empty()) return 1;
			if (r.empty() && !l.empty()) return -1;
			return 0;
		}
	}

	int Semver200_comparator::compare(const Version_data& l, const Version_data& r) const {
		// Compare normal version components.
		int cmp = compare_normal(l, r);
		if (cmp != 0) return cmp;

		// Compare if one version is release and the other prerelease - release is always higher.
		cmp = cmp_rel_prerel(l.prerelease_ids, r.prerelease_ids);
		if (cmp != 0) return cmp;

		// Compare prerelease by looking at each identifier: numeric ones are compared as numbers,
		// alphanum as ASCII strings.
		auto shorter = min(l.prerelease_ids.size(), r.prerelease_ids.size());
		for (size_t i = 0; i < shorter; i++) {
			cmp = compare_prerel_identifiers(l.prerelease_ids[i], r.prerelease_ids[i]);
			if (cmp != 0) return cmp;
		}

		// Prerelease identifiers are the same, to the length of the shorter version string;
		// if they are the same length, then versions are equal, otherwise, longer one wins.
		if (l.prerelease_ids.size() == r.prerelease_ids.size()) return 0;
		return l.prerelease_ids.size() > r.prerelease_ids.size() ? 1 : -1;
	}

}
<commit_msg>Compared based on the digits' numeric order If both versions have a prerelease section with the same prefix<commit_after>/*
The MIT License (MIT)

Copyright (c) 2015 Marko Zivanovic

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 "stdafx.h"

#include <algorithm>
#include <functional>
#include <map>
#include "semver200.h"

using namespace std;

namespace version {

	namespace {

		// Compare normal version identifiers.
		int compare_normal(const Version_data& l, const Version_data& r) {
			if (l.major > r.major) return 1;
			if (l.major < r.major) return -1;
			if (l.minor > r.minor) return 1;
			if (l.minor < r.minor) return -1;
			if (l.patch > r.patch) return 1;
			if (l.patch < r.patch) return -1;
			return 0;
		}

		// Compare alphanumeric prerelease identifiers.
		inline int cmp_alnum_prerel_ids(const string& l, const string& r) {
			// If both versions have a prerelease section with the same prefix
			// and end with digits, compare based on the digits' numeric order
			auto index_l = l.find_last_not_of("0123456789");
			auto index_r = r.find_last_not_of("0123456789");

			if (index_l != string::npos && index_r != string::npos) {
				string name_l = l.substr(0, index_l + 1);
				string name_r = r.substr(0, index_r + 1);

				if (name_l == name_r) {
					int il = stoi(l.substr(index_l + 1));
					int ir = stoi(r.substr(index_r + 1));

					return il > ir ? 1 : -1;
				}
			}

			auto cmp = l.compare(r);

			if (cmp == 0) {
				return cmp;
			} else {
				return cmp > 0 ? 1 : -1;
			}
		}

		// Compare numeric prerelease identifiers.
		inline int cmp_num_prerel_ids(const string& l, const string& r) {
			long long li = stoll(l);
			long long ri = stoll(r);
			if (li == ri) return 0;
			return li > ri ? 1 : -1;
		}

		using Prerel_type_pair = pair<Id_type, Id_type>;
		using Prerel_id_comparator = function<int(const string&, const string&)>;
		const map<Prerel_type_pair, Prerel_id_comparator> comparators = {
			{ { Id_type::alnum, Id_type::alnum }, cmp_alnum_prerel_ids },
			{ { Id_type::alnum, Id_type::num }, [](const string&, const string&) {return 1;} },
			{ { Id_type::num, Id_type::alnum }, [](const string&, const string&) {return -1;} },
			{ { Id_type::num, Id_type::num }, cmp_num_prerel_ids }
		};

		// Compare prerelease identifiers based on their types.
		inline int compare_prerel_identifiers(const Prerelease_identifier& l, const Prerelease_identifier& r) {
			auto cmp = comparators.at({ l.second, r.second });
			return cmp(l.first, r.first);
		}

		inline int cmp_rel_prerel(const Prerelease_identifiers& l, const Prerelease_identifiers& r) {
			if (l.empty() && !r.empty()) return 1;
			if (r.empty() && !l.empty()) return -1;
			return 0;
		}
	}

	int Semver200_comparator::compare(const Version_data& l, const Version_data& r) const {
		// Compare normal version components.
		int cmp = compare_normal(l, r);
		if (cmp != 0) return cmp;

		// Compare if one version is release and the other prerelease - release is always higher.
		cmp = cmp_rel_prerel(l.prerelease_ids, r.prerelease_ids);
		if (cmp != 0) return cmp;

		// Compare prerelease by looking at each identifier: numeric ones are compared as numbers,
		// alphanum as ASCII strings.
		auto shorter = min(l.prerelease_ids.size(), r.prerelease_ids.size());
		for (size_t i = 0; i < shorter; i++) {
			cmp = compare_prerel_identifiers(l.prerelease_ids[i], r.prerelease_ids[i]);
			if (cmp != 0) return cmp;
		}

		// Prerelease identifiers are the same, to the length of the shorter version string;
		// if they are the same length, then versions are equal, otherwise, longer one wins.
		if (l.prerelease_ids.size() == r.prerelease_ids.size()) return 0;
		return l.prerelease_ids.size() > r.prerelease_ids.size() ? 1 : -1;
	}

}
<|endoftext|>


<commit_before>#include <iostream>
#include <cmath>

using std::cin;
using std::cout;
using std::endl;

template<uint N>
struct Capacity
{
	enum
	{
		value = N - 1 + Capacity<N-1>::value
	};
};

template<>
struct Capacity<0>
{
	enum
	{
		value = 0
	};
};

uint f(uint n, uint base)
{
	switch(n)
	{
	case 0:
	case 1:
	case 2:
		return 1;
	case 3:
		return (base > 3) ? 2 : 1;
	default:
		uint k = ceil(-0.5+sqrt(1+8*n)/2);
		uint res = 0;
		for (uint i = k; i <= n; ++i)
			res += f(n-i, i);
		return res;
	}

	return n;
}

int main()
{
	cout << "Емкость блока " << Capacity<11>::value << endl;
	return 0;
}
<commit_msg>implementation fradmentation count with error<commit_after>#include <iostream>
#include <cmath>

using std::cin;
using std::cout;
using std::endl;

template<uint N, uint Base>
struct FragImpl;

template<uint N>
struct Capacity
{
	enum
	{
		value = N - 1 + Capacity<N-1>::value
	};
};

template<>
struct Capacity<0>
{
	enum
	{
		value = 0
	};
};

template<uint N, uint Step>
struct Loop
{
	enum
	{
		value = FragImpl<N-Step, Step>::value + Loop<N, Step-1>::value
	};
};

template<uint N>
struct Loop<N, 0>
{
	enum
	{
		value = FragImpl<N, 0>::value
	};
};

template<uint A, uint B>
struct MIN
{
	enum
	{
		value = (A < B) ? A : B
	};
};

template<uint N, uint Base, bool Condition>
struct Check
{
	enum
	{
		value = 0
	};
};

template<uint N, uint Base>
struct Check<N, Base, true>
{
	enum
	{
		value = Loop<N, MIN<N, Base-1>::value>::value
	};
};

template<uint N, uint Base>
struct FragImpl
{
	enum
	{
		value = Check<N, Base, N < Capacity<Base>::value>::value
	};
};

template<>
struct FragImpl<0, 0>
{
	enum
	{
		value = 1
	};
};

template<>
struct FragImpl<0, 1>
{
	enum
	{
		value = 1
	};
};

template<uint N>
struct Frag
{
	enum
	{
		value = FragImpl<N, N+1>::value
	};
};

uint f(uint n, uint base)
{
	switch(n)
	{
	case 0:
	case 1:
	case 2:
		return 1;
	case 3:
		return (base > 3) ? 2 : 1;
	default:
		uint k = ceil(-0.5+sqrt(1+8*n)/2);
		uint res = 0;
		for (uint i = k; i <= n; ++i)
			res += f(n-i, i);
		return res;
	}

	return n;
}

int main()
{
	cout << "Количество вариантов: " << Frag<1>::value << endl;
	return 0;
}
<|endoftext|>


<commit_before>/***************************************************************************************************
*                                                                                *
*                                           Fireplace                                              *
*                                                                                *
*   File:      main.cpp                                                                            *
*   Author:    Wyatt Sheffield and GitHub contributors                                             *
*                                                                                *
*   Lights a cozy fire in your terminal. Goes well with coffee.                                    *
*                                                                                *
*                   Copyright (c) 2017 Wyatt Sheffield and GitHub contributors                     *
*                                                                                *
***************************************************************************************************/

#include <ctime>
#include <iostream>
#include <ncurses.h>
#include <signal.h>
#include <stdlib.h> //random
#include <unistd.h> //usleep, getopt

#define MIN(X, Y)  ((X) < (Y) ? (X) : (Y))
#define MAX(X, Y)  ((X) > (Y) ? (X) : (Y))

//----------------------------------------[Global variables]----------------------------------------

static char dispch;        //the character used to draw the flames
static int WIDTH, HEIGHT;  //Set by ncurses
static int framerate;      //framerate
static int heightrecord;   //max height reached by the flames
static int maxtemp;        //maximum flame temperature
static int wolfrule;       //rule for wolfram eca

static volatile sig_atomic_t sig_caught = 0;

//--------------------------------------------[Structs]---------------------------------------------

struct color_val{ short r,g,b; };

//------------------------------[Memory Management and Initialization]------------------------------

int** init(int y, int x){
    int** out = new int*[y];
    for(int i = 0; i < y; i++){
        out[i] = new int[x];
    }

    for(int i = 0; i < y; i++){
        for(int j = 0; j < x; j++){
            out[i][j] = 0;
        }
    }
    return out;
}

void deallocate(int** in, int rows){
    for(int i = 0; i < rows; i++){
        delete[] in[i];
    }
    delete[] in;
}

void start_ncurses(color_val* colors){
    initscr();
    start_color();

    for(int i = 0; i < 8; i++){
        color_content(i, &colors[i].r, &colors[i].g, &colors[i].b);
    }

    init_color(COLOR_BLACK,    100,   100,   100);
    init_color(COLOR_RED,      300,   0,     0);
    init_color(COLOR_GREEN,    500,   0,     0);
    init_color(COLOR_BLUE,     700,   100,   0);
    init_color(COLOR_YELLOW,   900,   300,   0);
    init_color(COLOR_MAGENTA,  1000,  500,   100);
    init_color(COLOR_CYAN,     1000,  800,   500);
    init_color(COLOR_WHITE,    1000,  1000,  1000);

    init_pair(1,  COLOR_RED,      COLOR_BLACK);
    init_pair(2,  COLOR_GREEN,    COLOR_BLACK);
    init_pair(3,  COLOR_BLUE,     COLOR_BLACK);
    init_pair(4,  COLOR_YELLOW,   COLOR_BLACK);
    init_pair(5,  COLOR_MAGENTA,  COLOR_BLACK);
    init_pair(6,  COLOR_CYAN,     COLOR_BLACK);
    init_pair(7,  COLOR_WHITE,    COLOR_BLACK);
    curs_set(0);    //invisible cursor
    timeout(0);     //make getch() non-blocking
    cbreak();
    noecho();
    keypad(stdscr, TRUE);
    getmaxyx(stdscr, HEIGHT, WIDTH);
    heightrecord = HEIGHT;
}

void restore_colors(color_val* colors){
    for(int i = 0; i < 8; i++){
        init_color(i, colors[i].r, colors[i].g, colors[i].b);
    }
}

//-----------------------------------[Cellular Automata Helpers]------------------------------------

//As a cell cools it has a higher chance of cooling again on the next frame.
int cooldown(int heat){
    if(heat == 0) return 0;
    int r = (rand() % heat);
    if(r == 0) heat--;
    return heat;
}

void cleargrid(int** grid, int h){
    for(int i = h; i < HEIGHT; i++){
        for(int j = 0; j < WIDTH; j++){
            grid[i][j] = 0;
        }
    }
}

void warm(int* heater, int* hotplate){
    for(int i = 0; i < WIDTH; i++){
        hotplate[i] /= 2;
    }
    for(int i = 0; i < WIDTH; i++){
        hotplate[i] += heater[i] * maxtemp;
    }
}

//---------------------------------------[Cellular Automata]----------------------------------------

void nextframe(int** field, int** count, int* hotplate){
    cleargrid(count, heightrecord);
    int rowsum = 0;
    int h = heightrecord - 3;
    h = MAX(h, 1);  //we can ignore the vast majority of cold cells
                    //and skip down to the bottom of the window
    for(int i = h; i <= HEIGHT; i++){
        for(int j = 0; j < WIDTH; j++){
            float avg = 0;
            //int temp = rand() % maxtemp * 4;
            int counter = 0;

            //the search space around the current cell is as follows
            //    .......
            //    ...X...
            //    .......
            //    .......
            //    .......
            for(int xoff = -3; xoff <= 3; xoff++){
                for(int yoff = -1; yoff <= 3; yoff++){
                    int y = i + yoff;
                    y = MAX(y,0); //if y is less than zero, clamp it to zero.
                    int x = j + xoff;
                    //if the search has gon beyond the left or right, no heat is added
                    if(x < 0 || x >= WIDTH) avg += 0;
                    //if the search goes below the screen, add the hotplate value.
                    //the hotplate has infinite depth.
                    else if(y >= HEIGHT)  avg += hotplate[x];
                    else avg += field[y][x];
                    counter++;
                }
            }
            avg /= counter;
            //see if the cell cools or not
            //we add the value at (i-1) so that an upward motion will be created.
            count[i - 1][j] = cooldown(avg);
            rowsum += count[i-1][j];
        }
        if(rowsum > 0 && i < heightrecord) heightrecord = i;
        rowsum = 0;
    }

    for(int i = 0; i < HEIGHT; i++){
        for(int j = 0; j < WIDTH; j++){
            field[i][j] = count[i][j];
        }
    }
}

//Wolfram's Elementary cellular atomaton
//https://en.wikipedia.org/wiki/Elementary_cellular_automaton
void wolfram(int* world, const int rule){
    int* next = new int[WIDTH];
    int l,c,r;
    int lidx, ridx;
    int current;
    for(int i = 0; i < WIDTH; i++){
        lidx = i > 0 ? i - 1 : WIDTH - 1;
        ridx = (i + 1) % WIDTH;
        l = world[lidx];
        c = world[i];
        r = world[ridx];
        current = (l<<2) | (c<<1) | r;
        next[i] = ((1<<current) & rule) > 0 ? 1 : 0;
    }

    for(int i = 0; i < WIDTH; i++){
        world[i] = next[i];
    }
    delete[] next;
}

//----------------------------------------[Draw and Animate]----------------------------------------

void printframe(int** field, int** count, int* hotplate){
    char disp;
    for(int i = 0; i < HEIGHT; i++){
        for(int j = 0; j < WIDTH; j++){

            move(i,j);
            //if the cell is cold, print a space, otherwise print [dispch]
            int color = (7 * field[i][j] / maxtemp) + 1;
            color = MIN(color,7);
            disp = field[i][j] == 0 ? ' ' : dispch;
            attron(COLOR_PAIR(color));
            addch(disp);
            attroff(COLOR_PAIR(color));
        }
    }
    refresh();
}

void flames(){
    int** field = init(HEIGHT, WIDTH); //The cells that will be displayed
    int** count = init(HEIGHT, WIDTH); //A grid of cells used to tally neighbors for CA purposes
    int* heater = new int[WIDTH]; //these special cells provide "heat" at the bottom of the screen.
    int* hotplate = new int[WIDTH]; //The heater heats the hotplate. The hotplate will cool without heat.

    for(int i = 0; i < WIDTH; i++){
        heater[i] = rand() % 2;
        hotplate[i] = 0;
    }

    char c = 0;

    while(sig_caught == 0){
        //Use Rule 60 to make flames flicker nicely.
        wolfram(heater, wolfrule);
        warm(heater, hotplate);
        printframe(field, count, hotplate);
        nextframe(field, count, hotplate);
        usleep(framerate);
    }

    refresh();
    delete[] hotplate;
    delete[] heater;
    deallocate(field, HEIGHT);
    deallocate(count, HEIGHT);
}

//----------------------------------------------[Help]----------------------------------------------

void printhelp(char progname[]){
    std::cout << "\nUsage: " << progname << " [options]\n"
        << "\t-c character\tAn ASCII character to draw the flames. Default is '@'.\n"
        << "\t-h\t\tPrint this message.\n"
        << "\t-f framerate\tSet the framerate in frames/sec. Default is 20.\n"
        << "\t\t\tA framerate of zero will make frames spit out as soon as they are ready.\n"
        << "\t-t temp\t\tSet the maximum temperature of the flames. Default is 10.\n"
        << "\t\t\tA higher temp means taller flames.\n"
        << "\n"
        << "Press ^C at any time to douse the flames.\n\n";
}

//--------------------------------------------[Signals]---------------------------------------------

void sigint_handler(int signum){
    if(signum == SIGINT){
        sig_caught = 1;
    }
}

void sigwinch_handler(int signum){
    if(signum == SIGWINCH){
        sig_caught = 2;
    }
}

//----------------------------------------------[Main]----------------------------------------------

int main(int argc, char** argv){
    signal(SIGINT, sigint_handler);
    signal(SIGWINCH, sigwinch_handler);

    int persecond = 1000000;
    srand(time(NULL));
    framerate = persecond / 20;
    maxtemp = 10;
    dispch = '@';
    wolfrule = 60;

    int c;
    opterr = 0;
    while((c = getopt(argc, argv, "c:hf:t:w:")) != -1){
        switch (c){
            case 'c':
                dispch = optarg[0];
                break;
            case 'h':
                printhelp(argv[0]);
                std::cout << COLORS <<std::endl;
                return 0;
            case 'f':
                if(atoi(optarg) < 1) framerate = 0;
                else framerate = persecond / atoi(optarg);
                break;
            case 't':
                maxtemp = atoi(optarg);
                break;
            case 'w':
                wolfrule = atoi(optarg);
                break;
            case '?':
                std::cout << "\nYou've really bunged this one up. Here, this may help:\n";
                printhelp(argv[0]);
                return 1;
            default:
                std::cerr << "What the hell?!";
                return 2;
        }
    }
    color_val* colors = new color_val[8];
    start_ncurses(colors);
    while(sig_caught != 1){
        sig_caught = 0;
        getmaxyx(stdscr, HEIGHT, WIDTH);
        flames();
        endwin();
        clear();
        refresh();
    }
    restore_colors(colors);
    delete[] colors;
    clear();
    refresh();
    endwin();
    return 0;
}
<commit_msg>fixed sleep function on cygwin, added quit key and refactored the code<commit_after>/***************************************************************************************************
*                                                                                *
*                                           Fireplace                                              *
*                                                                                *
*   File:      main.cpp                                                                            *
*   Author:    Wyatt Sheffield and GitHub contributors                                             *
*                                                                                *
*   Lights a cozy fire in your terminal. Goes well with coffee.                                    *
*                                                                                *
*                   Copyright (c) 2017 Wyatt Sheffield and GitHub contributors                     *
*                                                                                *
***************************************************************************************************/

#include <ctime>
#include <iostream>
#include <ncurses.h>
#include <signal.h>
#include <stdlib.h> //random
#include <unistd.h> //usleep, getopt

#ifdef _WIN32
#include <windows.h> //Sleep
#endif

#define MIN(X, Y)  ((X) < (Y) ? (X) : (Y))
#define MAX(X, Y)  ((X) > (Y) ? (X) : (Y))

//----------------------------------------[Global variables]----------------------------------------

static char dispch;        //the character used to draw the flames
static int WIDTH, HEIGHT;  //Set by ncurses
static int framerate;      //framerate
static int heightrecord;   //max height reached by the flames
static int maxtemp;        //maximum flame temperature
static int wolfrule;       //rule for wolfram eca

static volatile sig_atomic_t sig_caught = 0;
static volatile sig_atomic_t cease_flames = 0;

//--------------------------------------------[Structs]---------------------------------------------

struct color_val{ short r,g,b; };

//------------------------------[Memory Management and Initialization]------------------------------

int** init(int y, int x) {
    int** out = new int*[y];
    for (int i = 0; i < y; i++) {
        out[i] = new int[x];
    }

    for (int i = 0; i < y; i++) {
        for (int j = 0; j < x; j++) {
            out[i][j] = 0;
        }
    }
    return out;
}

void deallocate(int** in, int rows)
{
    for (int i = 0; i < rows; i++) {
        delete[] in[i];
    }
    delete[] in;
}

void start_ncurses(color_val* colors)
{
    initscr();
    start_color();

    for (int i = 0; i < 8; i++) {
        color_content(i, &colors[i].r, &colors[i].g, &colors[i].b);
    }

    init_color(COLOR_BLACK,    100,   100,   100);
    init_color(COLOR_RED,      300,   0,     0);
    init_color(COLOR_GREEN,    500,   0,     0);
    init_color(COLOR_BLUE,     700,   100,   0);
    init_color(COLOR_YELLOW,   900,   300,   0);
    init_color(COLOR_MAGENTA,  1000,  500,   100);
    init_color(COLOR_CYAN,     1000,  800,   500);
    init_color(COLOR_WHITE,    1000,  1000,  1000);

    init_pair(1,  COLOR_RED,      COLOR_BLACK);
    init_pair(2,  COLOR_GREEN,    COLOR_BLACK);
    init_pair(3,  COLOR_BLUE,     COLOR_BLACK);
    init_pair(4,  COLOR_YELLOW,   COLOR_BLACK);
    init_pair(5,  COLOR_MAGENTA,  COLOR_BLACK);
    init_pair(6,  COLOR_CYAN,     COLOR_BLACK);
    init_pair(7,  COLOR_WHITE,    COLOR_BLACK);
    curs_set(0);    //invisible cursor
    timeout(0);     //make getch() non-blocking

    cbreak();
    noecho();
    keypad(stdscr, TRUE);
    getmaxyx(stdscr, HEIGHT, WIDTH);
    heightrecord = HEIGHT;
}

void restore_colors(color_val* colors)
{
    for (int i = 0; i < 8; i++) {
        init_color(i, colors[i].r, colors[i].g, colors[i].b);
    }
}

//-----------------------------------[Cellular Automata Helpers]------------------------------------

//As a cell cools it has a higher chance of cooling again on the next frame.
int cooldown(int heat) {
    if (heat == 0) return 0;
    int r = (rand() % heat);
    if (r == 0) heat--;
    return heat;
}

void cleargrid(int** grid, int h)
{
    for (int i = h; i < HEIGHT; i++) {
        for (int j = 0; j < WIDTH; j++) {
            grid[i][j] = 0;
        }
    }
}

void warm(int* heater, int* hotplate)
{
    for (int i = 0; i < WIDTH; i++) {
        hotplate[i] /= 2;
    }
    for (int i = 0; i < WIDTH; i++) {
        hotplate[i] += heater[i] * maxtemp;
    }
}

//---------------------------------------[Cellular Automata]----------------------------------------

void nextframe(int** field, int** count, int* hotplate)
{
    cleargrid(count, heightrecord);
    int rowsum = 0;
    int h = heightrecord - 3;
    h = MAX(h, 1);  //we can ignore the vast majority of cold cells
                    //and skip down to the bottom of the window
    for (int i = h; i <= HEIGHT; i++) {
        for (int j = 0; j < WIDTH; j++) {
            float avg = 0;
            //int temp = rand() % maxtemp * 4;
            int counter = 0;

            //the search space around the current cell is as follows
            //    .......
            //    ...X...
            //    .......
            //    .......
            //    .......
            for (int xoff = -3; xoff <= 3; xoff++) {
                for (int yoff = -1; yoff <= 3; yoff++) {
                    int y = i + yoff;
                    y = MAX(y,0); //if y is less than zero, clamp it to zero.
                    int x = j + xoff;
                    //if the search has gon beyond the left or right, no heat is added
                    if (x < 0 || x >= WIDTH) avg += 0;
                    //if the search goes below the screen, add the hotplate value.
                    //the hotplate has infinite depth.
                    else if (y >= HEIGHT)  avg += hotplate[x];
                    else avg += field[y][x];
                    counter++;
                }
            }
            avg /= counter;
            //see if the cell cools or not
            //we add the value at (i-1) so that an upward motion will be created.
            count[i - 1][j] = cooldown(avg);
            rowsum += count[i-1][j];
        }
        if (rowsum > 0 && i < heightrecord) heightrecord = i;
        rowsum = 0;
    }

    for (int i = 0; i < HEIGHT; i++) {
        for (int j = 0; j < WIDTH; j++) {
            field[i][j] = count[i][j];
        }
    }
}

//Wolfram's Elementary cellular atomaton
//https://en.wikipedia.org/wiki/Elementary_cellular_automaton
void wolfram(int* world, const int rule)
{
    int* next = new int[WIDTH];
    int l,c,r;
    int lidx, ridx;
    int current;
    for (int i = 0; i < WIDTH; i++) {
        lidx = i > 0 ? i - 1 : WIDTH - 1;
        ridx = (i + 1) % WIDTH;
        l = world[lidx];
        c = world[i];
        r = world[ridx];
        current = (l<<2) | (c<<1) | r;
        next[i] = ((1<<current) & rule) > 0 ? 1 : 0;
    }

    for (int i = 0; i < WIDTH; i++) {
        world[i] = next[i];
    }
    delete[] next;
}

//----------------------------------------[Draw and Animate]----------------------------------------

void printframe(int** field, int** count, int* hotplate)
{
    char disp;
    for (int i = 0; i < HEIGHT; i++) {
        for (int j = 0; j < WIDTH; j++) {

            move(i,j);
            //if the cell is cold, print a space, otherwise print [dispch]
            int color = (7 * field[i][j] / maxtemp) + 1;
            color = MIN(color,7);
            disp = field[i][j] == 0 ? ' ' : dispch;
            attron(COLOR_PAIR(color));
            addch(disp);
            attroff(COLOR_PAIR(color));
        }
    }
    refresh();
}

void flames()
{
    int** field = init(HEIGHT, WIDTH); //The cells that will be displayed
    int** count = init(HEIGHT, WIDTH); //A grid of cells used to tally neighbors for CA purposes
    int* heater = new int[WIDTH]; //these special cells provide "heat" at the bottom of the screen.
    int* hotplate = new int[WIDTH]; //The heater heats the hotplate. The hotplate will cool without heat.

    for (int i = 0; i < WIDTH; i++) {
        heater[i] = rand() % 2;
        hotplate[i] = 0;
    }

    char c = 0;

    while (sig_caught == 0 && (c = getch()) != 'q') {
        if (c == 'q') sig_caught = 1;
        //Use Rule 60 to make flames flicker nicely.
        wolfram(heater, wolfrule);
        warm(heater, hotplate);
        printframe(field, count, hotplate);
        nextframe(field, count, hotplate);
        #ifdef _WIN32
            Sleep(framerate);
        #elif __linux__
            usleep(framerate);
        #endif
    }

    refresh();
    delete[] hotplate;
    delete[] heater;
    deallocate(field, HEIGHT);
    deallocate(count, HEIGHT);
}

//----------------------------------------------[Help]----------------------------------------------

void printhelp(char progname[])
{
    std::cout << "\nUsage: " << progname << " [options]\n"
        << "\t-c character\tAn ASCII character to draw the flames. Default is '@'.\n"
        << "\t-h\t\tPrint this message.\n"
        << "\t-f framerate\tSet the framerate in frames/sec. Default is 20.\n"
        << "\t\t\tA framerate of zero will make frames spit out as soon as they are ready.\n"
        << "\t-t temp\t\tSet the maximum temperature of the flames. Default is 10.\n"
        << "\t\t\tA higher temp means taller flames.\n"
        << "\n"
        << "Press ^C at any time to douse the flames.\n\n";
}

//--------------------------------------------[Signals]---------------------------------------------

void sigint_handler(int signum)
{
    if (signum == SIGINT) {
        sig_caught = 1;
    }
}

void sigwinch_handler(int signum)
{
    if (signum == SIGWINCH) {
        sig_caught = 2;
    }
}

//----------------------------------------------[Main]----------------------------------------------

int main(int argc, char** argv)
{
    signal(SIGINT, sigint_handler);
    signal(SIGWINCH, sigwinch_handler);

    int persecond = 1000000;
    srand(time(NULL));
    framerate = persecond / 20;
    maxtemp = 10;
    dispch = '@';
    wolfrule = 60;

    int c;
    opterr = 0;
    while ((c = getopt(argc, argv, "c:hf:t:w:")) != -1) {
        switch (c) {
            case 'c':
                dispch = optarg[0];
                break;
            case 'h':
                printhelp(argv[0]);
                std::cout << COLORS <<std::endl;
                return 0;
            case 'f':
                if (atoi(optarg) < 1) framerate = 0;
                else framerate = persecond / atoi(optarg);
                break;
            case 't':
                maxtemp = atoi(optarg);
                break;
            case 'w':
                wolfrule = atoi(optarg);
                break;
            case '?':
                std::cout << "\nYou've really bunged this one up. Here, this may help:\n";
                printhelp(argv[0]);
                return 1;
            default:
                std::cerr << "What the hell?!";
                return 2;
        }
    }
    color_val* colors = new color_val[8];
    start_ncurses(colors);
    while (sig_caught != 1) {
        getmaxyx(stdscr, HEIGHT, WIDTH);
        flames();
        endwin();
        clear();
        refresh();
        if (sig_caught == 0) break;
    }
    restore_colors(colors);
    delete[] colors;
    clear();
    refresh();
    endwin();
    return 0;
}
<|endoftext|>


<commit_before><commit_msg>refactor Parser.cpp<commit_after><|endoftext|>


<commit_before><commit_msg>re enc<commit_after><|endoftext|>


<commit_before>/**
 * Copyright 2017 Google Inc.
 *
 * 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 "config.h"

#include "build/buildjson.hpp"
#include "conf.hpp"
#include "dbus/dbusconfiguration.hpp"
#include "interfaces.hpp"
#include "pid/builder.hpp"
#include "pid/buildjson.hpp"
#include "pid/pidloop.hpp"
#include "pid/tuning.hpp"
#include "pid/zone.hpp"
#include "sensors/builder.hpp"
#include "sensors/buildjson.hpp"
#include "sensors/manager.hpp"
#include "util.hpp"

#include <CLI/CLI.hpp>
#include <boost/asio/io_context.hpp>
#include <boost/asio/steady_timer.hpp>
#include <sdbusplus/asio/connection.hpp>
#include <sdbusplus/bus.hpp>

#include <chrono>
#include <filesystem>
#include <iostream>
#include <list>
#include <map>
#include <memory>
#include <thread>
#include <unordered_map>
#include <utility>
#include <vector>

namespace pid_control
{

/* The configuration converted sensor list. */
std::map<std::string, struct conf::SensorConfig> sensorConfig = {};
/* The configuration converted PID list. */
std::map<int64_t, conf::PIDConf> zoneConfig = {};
/* The configuration converted Zone configuration. */
std::map<int64_t, struct conf::ZoneConfig> zoneDetailsConfig = {};

} // namespace pid_control

/** the swampd daemon will check for the existence of this file. */
constexpr auto jsonConfigurationPath = "/usr/share/swampd/config.json";
std::string configPath = "";

/* async io context for operation */
boost::asio::io_context io;

/* buses for system control */
static sdbusplus::asio::connection modeControlBus(io);
static sdbusplus::asio::connection
    hostBus(io, sdbusplus::bus::new_system().release());
static sdbusplus::asio::connection
    passiveBus(io, sdbusplus::bus::new_system().release());

namespace pid_control
{

void restartControlLoops()
{
    static SensorManager mgmr;
    static std::unordered_map<int64_t, std::shared_ptr<ZoneInterface>> zones;
    static std::vector<std::shared_ptr<boost::asio::steady_timer>> timers;

    for (const auto timer : timers)
    {
        timer->cancel();
    }
    timers.clear();
    zones.clear();

    const std::string& path =
        (configPath.length() > 0) ? configPath : jsonConfigurationPath;

    if (std::filesystem::exists(path))
    {
        /*
         * When building the sensors, if any of the dbus passive ones aren't on
         * the bus, it'll fail immediately.
         */
        try
        {
            auto jsonData = parseValidateJson(path);
            sensorConfig = buildSensorsFromJson(jsonData);
            std::tie(zoneConfig, zoneDetailsConfig) =
                buildPIDsFromJson(jsonData);
        }
        catch (const std::exception& e)
        {
            std::cerr << "Failed during building: " << e.what() << "\n";
            exit(EXIT_FAILURE); /* fatal error. */
        }
    }
    else
    {
        static boost::asio::steady_timer reloadTimer(io);
        if (!dbus_configuration::init(modeControlBus, reloadTimer))
        {
            return; // configuration not ready
        }
    }

    mgmr = buildSensors(sensorConfig, passiveBus, hostBus);
    zones = buildZones(zoneConfig, zoneDetailsConfig, mgmr, modeControlBus);

    if (0 == zones.size())
    {
        std::cerr << "No zones defined, exiting.\n";
        std::exit(EXIT_FAILURE);
    }

    for (const auto& i : zones)
    {
        std::shared_ptr<boost::asio::steady_timer> timer = timers.emplace_back(
            std::make_shared<boost::asio::steady_timer>(io));
        std::cerr << "pushing zone " << i.first << "\n";
        pidControlLoop(i.second, timer);
    }
}

void tryRestartControlLoops()
{
    int count = 0;
    for (count = 0; count <= 5; count++)
    {
        try
        {
            restartControlLoops();
            break;
        }
        catch (const std::exception& e)
        {
            std::cerr << count
                      << " Failed during restartControlLoops, try again: "
                      << e.what() << "\n";
            if (count >= 5)
            {
                throw std::runtime_error(e.what());
            }
        }
        std::this_thread::sleep_for(std::chrono::seconds(10));
    }

    return;
}

} // namespace pid_control

int main(int argc, char* argv[])
{
    loggingPath = "";
    loggingEnabled = false;
    tuningEnabled = false;

    CLI::App app{"OpenBMC Fan Control Daemon"};

    app.add_option("-c,--conf", configPath,
                   "Optional parameter to specify configuration at run-time")
        ->check(CLI::ExistingFile);
    app.add_option("-l,--log", loggingPath,
                   "Optional parameter to specify logging folder")
        ->check(CLI::ExistingDirectory);
    app.add_flag("-t,--tuning", tuningEnabled, "Enable or disable tuning");

    CLI11_PARSE(app, argc, argv);

    loggingEnabled = (!loggingPath.empty());

    static constexpr auto modeRoot = "/xyz/openbmc_project/settings/fanctrl";
    // Create a manager for the ModeBus because we own it.
    sdbusplus::server::manager::manager(
        static_cast<sdbusplus::bus::bus&>(modeControlBus), modeRoot);
    hostBus.request_name("xyz.openbmc_project.Hwmon.external");
    modeControlBus.request_name("xyz.openbmc_project.State.FanCtrl");

    /*
     * All sensors are managed by one manager, but each zone has a pointer to
     * it.
     */

    pid_control::tryRestartControlLoops();

    io.run();
    return 0;
}
<commit_msg>main: Allowing logging and tuning to also be enabled by files<commit_after>/**
 * Copyright 2017 Google Inc.
 *
 * 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 "config.h"

#include "build/buildjson.hpp"
#include "conf.hpp"
#include "dbus/dbusconfiguration.hpp"
#include "interfaces.hpp"
#include "pid/builder.hpp"
#include "pid/buildjson.hpp"
#include "pid/pidloop.hpp"
#include "pid/tuning.hpp"
#include "pid/zone.hpp"
#include "sensors/builder.hpp"
#include "sensors/buildjson.hpp"
#include "sensors/manager.hpp"
#include "util.hpp"

#include <CLI/CLI.hpp>
#include <boost/asio/io_context.hpp>
#include <boost/asio/steady_timer.hpp>
#include <sdbusplus/asio/connection.hpp>
#include <sdbusplus/bus.hpp>

#include <chrono>
#include <filesystem>
#include <iostream>
#include <list>
#include <map>
#include <memory>
#include <thread>
#include <unordered_map>
#include <utility>
#include <vector>

namespace pid_control
{

/* The configuration converted sensor list. */
std::map<std::string, struct conf::SensorConfig> sensorConfig = {};
/* The configuration converted PID list. */
std::map<int64_t, conf::PIDConf> zoneConfig = {};
/* The configuration converted Zone configuration. */
std::map<int64_t, struct conf::ZoneConfig> zoneDetailsConfig = {};

} // namespace pid_control

/** the swampd daemon will check for the existence of this file. */
constexpr auto jsonConfigurationPath = "/usr/share/swampd/config.json";
std::string configPath = "";

/* async io context for operation */
boost::asio::io_context io;

/* buses for system control */
static sdbusplus::asio::connection modeControlBus(io);
static sdbusplus::asio::connection
    hostBus(io, sdbusplus::bus::new_system().release());
static sdbusplus::asio::connection
    passiveBus(io, sdbusplus::bus::new_system().release());

namespace pid_control
{

void restartControlLoops()
{
    static SensorManager mgmr;
    static std::unordered_map<int64_t, std::shared_ptr<ZoneInterface>> zones;
    static std::vector<std::shared_ptr<boost::asio::steady_timer>> timers;

    for (const auto timer : timers)
    {
        timer->cancel();
    }
    timers.clear();
    zones.clear();

    const std::string& path =
        (configPath.length() > 0) ? configPath : jsonConfigurationPath;

    if (std::filesystem::exists(path))
    {
        /*
         * When building the sensors, if any of the dbus passive ones aren't on
         * the bus, it'll fail immediately.
         */
        try
        {
            auto jsonData = parseValidateJson(path);
            sensorConfig = buildSensorsFromJson(jsonData);
            std::tie(zoneConfig, zoneDetailsConfig) =
                buildPIDsFromJson(jsonData);
        }
        catch (const std::exception& e)
        {
            std::cerr << "Failed during building: " << e.what() << "\n";
            exit(EXIT_FAILURE); /* fatal error. */
        }
    }
    else
    {
        static boost::asio::steady_timer reloadTimer(io);
        if (!dbus_configuration::init(modeControlBus, reloadTimer))
        {
            return; // configuration not ready
        }
    }

    mgmr = buildSensors(sensorConfig, passiveBus, hostBus);
    zones = buildZones(zoneConfig, zoneDetailsConfig, mgmr, modeControlBus);

    if (0 == zones.size())
    {
        std::cerr << "No zones defined, exiting.\n";
        std::exit(EXIT_FAILURE);
    }

    for (const auto& i : zones)
    {
        std::shared_ptr<boost::asio::steady_timer> timer = timers.emplace_back(
            std::make_shared<boost::asio::steady_timer>(io));
        std::cerr << "pushing zone " << i.first << "\n";
        pidControlLoop(i.second, timer);
    }
}

void tryRestartControlLoops()
{
    int count = 0;
    for (count = 0; count <= 5; count++)
    {
        try
        {
            restartControlLoops();
            break;
        }
        catch (const std::exception& e)
        {
            std::cerr << count
                      << " Failed during restartControlLoops, try again: "
                      << e.what() << "\n";
            if (count >= 5)
            {
                throw std::runtime_error(e.what());
            }
        }
        std::this_thread::sleep_for(std::chrono::seconds(10));
    }

    return;
}

} // namespace pid_control

int main(int argc, char* argv[])
{
    loggingPath = "";
    loggingEnabled = false;
    tuningEnabled = false;

    CLI::App app{"OpenBMC Fan Control Daemon"};

    app.add_option("-c,--conf", configPath,
                   "Optional parameter to specify configuration at run-time")
        ->check(CLI::ExistingFile);
    app.add_option("-l,--log", loggingPath,
                   "Optional parameter to specify logging folder")
        ->check(CLI::ExistingDirectory);
    app.add_flag("-t,--tuning", tuningEnabled, "Enable or disable tuning");

    CLI11_PARSE(app, argc, argv);

    static constexpr auto loggingEnablePath = "/etc/thermal.d/logging";
    static constexpr auto tuningEnablePath = "/etc/thermal.d/tuning";

    // If this file exists, enable logging at runtime
    std::ifstream fsLogging(loggingEnablePath);
    if (fsLogging)
    {
        // Unless file contents are a valid directory path, use system default
        std::getline(fsLogging, loggingPath);
        if (!(std::filesystem::exists(loggingPath)))
        {
            loggingPath = std::filesystem::temp_directory_path();
        }
        fsLogging.close();

        loggingEnabled = true;
        std::cerr << "Logging enabled: " << loggingPath << "\n";
    }

    // If this file exists, enable tuning at runtime
    if (std::filesystem::exists(tuningEnablePath))
    {
        tuningEnabled = true;
        std::cerr << "Tuning enabled\n";
    }

    static constexpr auto modeRoot = "/xyz/openbmc_project/settings/fanctrl";
    // Create a manager for the ModeBus because we own it.
    sdbusplus::server::manager::manager(
        static_cast<sdbusplus::bus::bus&>(modeControlBus), modeRoot);
    hostBus.request_name("xyz.openbmc_project.Hwmon.external");
    modeControlBus.request_name("xyz.openbmc_project.State.FanCtrl");

    /*
     * All sensors are managed by one manager, but each zone has a pointer to
     * it.
     */

    pid_control::tryRestartControlLoops();

    io.run();
    return 0;
}
<|endoftext|>


<commit_before>28cb2d2b-ad58-11e7-a4fc-ac87a332f658<commit_msg>#BUG723 uncommitted code found on my computer Monday morning<commit_after>2924e391-ad58-11e7-887e-ac87a332f658<|endoftext|>


<commit_before>a2caa417-ad5a-11e7-ae08-ac87a332f658<commit_msg>Made changes so it will hopefully compile by the next commit<commit_after>a35a30ae-ad5a-11e7-adaf-ac87a332f658<|endoftext|>


<commit_before>#include <iostream>
#include "graph.h"

int main() {
    std::cout << "Graph test" << std::endl;

    graph<> g;

    // add some vertices to g
    for (int i = 0; i < 5; ++i) {
        g.add_vertex(i);
    }

    // add some edges
    g.add_edge(0, 1);
    g.add_edge(0, 3);
    g.add_edge(1, 2);
    g.add_edge(1, 3);
    g.add_edge(2, 3);
    g.add_edge(2, 5); // 5 is not in the graph, so this won't add anything
    g.add_edge(4, 1);
    g.add_edge(4, 3);

    // print out some adjacency lists
    for (int i = 0; i < 5; ++i) {
        std::cout << "Vertex v_" << i << "'s adjacency list:" << std::endl;
        std::cout << "( ";
        for (auto v : g.adj_list_of(i)) {
            std::cout << v.vertex << " ";
        }
        std::cout << ")" << std::endl;
    }

    std::cout << "Number of edges in g: " << g.edges() << std::endl;
    std::cout << "Number of vertices in g: " << g.vertices() << std::endl;
    std::cout << "Max degree of g: " << g.max_degree() << std::endl;
    std::cout << "Min degree of g: " << g.min_degree() << std::endl;
    std::cout << "Average degree of g: " << g.avg_degree() << std::endl;

    // try to remove some edges
    g.remove_edge(0, 1);

    std::cout << g.edges() << std::endl;
    std::cout << "( ";
    for (auto v : g.adj_list_of(0)) {
        std::cout << v.vertex << " ";
    }
    std::cout << ")";
}<commit_msg>Updating the testing code.<commit_after>#include <iostream>
#include "graph.h"

int main() {
    std::cout << "Graph test" << std::endl;

    graph<int, int> g;

    // add some vertices to g
    for (int i = 0; i < 5; ++i) {
        g.add_vertex(i);
    }

    // add some edges
    g.add_edge(0, 1);
    g.add_edge(0, 3);
    g.add_edge(1, 2);
    g.add_edge(1, 3);
    g.add_edge(2, 3);
    g.add_edge(2, 5); // 5 is not in the graph, so this won't add anything
    g.add_edge(4, 1);
    g.add_edge(4, 3);

    // print out some adjacency lists
    for (int i = 0; i < 5; ++i) {
        std::cout << "Vertex v_" << i << "'s adjacency list:" << std::endl;
        std::cout << "( ";
        for (auto v : g.adj_list_of(i)) {
            std::cout << v.vertex << " ";
        }
        std::cout << ")" << std::endl;
    }

    std::cout << "Number of edges in g: " << g.edges() << std::endl;
    std::cout << "Number of vertices in g: " << g.vertices() << std::endl;
    std::cout << "Max degree of g: " << g.max_degree() << std::endl;
    std::cout << "Min degree of g: " << g.min_degree() << std::endl;
    std::cout << "Average degree of g: " << g.avg_degree() << std::endl;

    // try to remove some edges
    g.remove_edge(0, 1);

    std::cout << g.edges() << std::endl;
    std::cout << "( ";
    for (auto v : g.adj_list_of(0)) {
        std::cout << v.vertex << " ";
    }
    std::cout << ")";

    // try to remove a vertex
    g.remove_vertex(1);

    std::cout << "Number of vertices in g: " << g.vertices() << std::endl;
    std::cout << "Number of edges in g: " << g.edges() << std::endl;
}<|endoftext|>


<commit_before>d9f130fa-4b02-11e5-b1ac-28cfe9171a43<commit_msg>We apologise for the previous fix. Those responsible have been sacked<commit_after>d9fe416e-4b02-11e5-b8a3-28cfe9171a43<|endoftext|>


<commit_before>/*****************************************************************************
 * standardpanel.cpp : The "standard" playlist panel : just a treeview
 ****************************************************************************
 * Copyright (C) 2000-2005 the VideoLAN team
 * $Id$
 *
 * Authors: Clément Stenac <zorglub@videolan.org>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

#include "qt4.hpp"
#include "dialogs_provider.hpp"

#include "components/playlist/playlist_model.hpp"
#include "components/playlist/panels.hpp"
#include "util/customwidgets.hpp"

#include <vlc_intf_strings.h>

#include <QPushButton>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QHeaderView>
#include <QKeyEvent>
#include <QModelIndexList>
#include <QLabel>
#include <QSpacerItem>
#include <QMenu>
#include <QSignalMapper>
#include <assert.h>

#include "sorting.h"

StandardPLPanel::StandardPLPanel( PlaylistWidget *_parent,
                                  intf_thread_t *_p_intf,
                                  playlist_t *p_playlist,
                                  playlist_item_t *p_root ):
                                  PLPanel( _parent, _p_intf )
{
    model = new PLModel( p_playlist, p_intf, p_root, this );

    QVBoxLayout *layout = new QVBoxLayout();
    layout->setSpacing( 0 ); layout->setMargin( 0 );

    /* Create and configure the QTreeView */
    view = new QVLCTreeView;
    view->setModel( model );
    view->setIconSize( QSize( 20, 20 ) );
    view->setAlternatingRowColors( true );
    view->setAnimated( true );
    view->setSelectionBehavior( QAbstractItemView::SelectRows );
    view->setSelectionMode( QAbstractItemView::ExtendedSelection );
    view->setDragEnabled( true );
    view->setAcceptDrops( true );
    view->setDropIndicatorShown( true );
    view->header()->setSortIndicator( -1 , Qt::AscendingOrder );
    view->setUniformRowHeights( true );
    view->setSortingEnabled( true );

    getSettings()->beginGroup("Playlist");
    if( getSettings()->contains( "headerState" ) )
    {
        view->header()->restoreState(
                getSettings()->value( "headerState" ).toByteArray() );
    }
    else
    {
        int m, c;
        for( m = 1, c = 0; m != COLUMN_END; m <<= 1, c++ )
        {
            view->setColumnHidden( c, !( m & COLUMN_DEFAULT ) );
            if( m == COLUMN_TITLE ) view->header()->resizeSection( c, 200 );
            else if( m == COLUMN_DURATION ) view->header()->resizeSection( c, 80 );
        }
    }
    view->header()->setSortIndicatorShown( true );
    view->header()->setClickable( true );
    view->header()->setContextMenuPolicy( Qt::CustomContextMenu );
    getSettings()->endGroup();

    /* Connections for the TreeView */
    CONNECT( view, activated( const QModelIndex& ) ,
             model,activateItem( const QModelIndex& ) );
    CONNECT( view, rightClicked( QModelIndex , QPoint ),
             this, doPopup( QModelIndex, QPoint ) );
    CONNECT( view->header(), customContextMenuRequested( const QPoint & ),
             this, popupSelectColumn( QPoint ) );
    CONNECT( model, currentChanged( const QModelIndex& ),
             this, handleExpansion( const QModelIndex& ) );

    currentRootId = -1;

    /* Buttons configuration */
    QHBoxLayout *buttons = new QHBoxLayout;

    /* Add item to the playlist button */
    addButton = new QPushButton;
    addButton->setIcon( QIcon( ":/buttons/playlist/playlist_add" ) );
    addButton->setMaximumWidth( 30 );
    BUTTONACT( addButton, popupAdd() );
    buttons->addWidget( addButton );

    /* Random 2-state button */
    randomButton = new QPushButton( this );
    randomButton->setIcon( QIcon( ":/buttons/playlist/shuffle_on" ));
    randomButton->setToolTip( qtr( I_PL_RANDOM ));
    randomButton->setCheckable( true );
    randomButton->setChecked( model->hasRandom() );
    BUTTONACT( randomButton, toggleRandom() );
    buttons->addWidget( randomButton );

    /* Repeat 3-state button */
    repeatButton = new QPushButton( this );
    repeatButton->setToolTip( qtr( "Click to toggle between loop one, loop all" ) );
    repeatButton->setCheckable( true );

    if( model->hasRepeat() )
    {
        repeatButton->setIcon( QIcon( ":/buttons/playlist/repeat_one" ) );
        repeatButton->setChecked( true );
    }
    else if( model->hasLoop() )
    {
        repeatButton->setIcon( QIcon( ":/buttons/playlist/repeat_all" ) );
        repeatButton->setChecked( true );
    }
    else
    {
        repeatButton->setIcon( QIcon( ":/buttons/playlist/repeat_one" ) );
        repeatButton->setChecked( false );
    }
    BUTTONACT( repeatButton, toggleRepeat() );
    buttons->addWidget( repeatButton );

    /* Goto */
    gotoPlayingButton = new QPushButton;
    BUTTON_SET_ACT_I( gotoPlayingButton, "", buttons/playlist/jump_to,
            qtr( "Show the current item" ), gotoPlayingItem() );
    buttons->addWidget( gotoPlayingButton );

    /* A Spacer and the search possibilities */
    QSpacerItem *spacer = new QSpacerItem( 10, 20 );
    buttons->addItem( spacer );

    QLabel *filter = new QLabel( qtr(I_PL_SEARCH) + " " );
    buttons->addWidget( filter );

    SearchLineEdit *search = new SearchLineEdit( this );
    buttons->addWidget( search );
    filter->setBuddy( search );
    CONNECT( search, textChanged( const QString& ), this, search( const QString& ) );

    /* Title label */
    title = new QLabel;
    QFont titleFont;
    titleFont.setPointSize( titleFont.pointSize() + 6 );
    titleFont.setFamily( "Verdana" );
    title->setFont( titleFont );

    /* Finish the layout */
    layout->addWidget( title );
    layout->addWidget( view );
    layout->addLayout( buttons );
//    layout->addWidget( bar );
    setLayout( layout );

    selectColumnsSigMapper = new QSignalMapper( this );
    CONNECT( selectColumnsSigMapper, mapped( int ), this, toggleColumnShown( int ) );
}

/* Function to toggle between the Repeat states */
void StandardPLPanel::toggleRepeat()
{
    if( model->hasRepeat() )
    {
        model->setRepeat( false ); model->setLoop( true );
        repeatButton->setIcon( QIcon( ":/buttons/playlist/repeat_all" ) );
        repeatButton->setChecked( true );
    }
    else if( model->hasLoop() )
    {
        model->setRepeat( false ) ; model->setLoop( false );
        repeatButton->setChecked( false );
        repeatButton->setIcon( QIcon( ":/buttons/playlist/repeat_one" ) );
    }
    else
    {
        model->setRepeat( true ); model->setLoop( false );
        repeatButton->setChecked( true );
        repeatButton->setIcon( QIcon( ":/buttons/playlist/repeat_one" ) );
    }
}

/* Function to toggle between the Random states */
void StandardPLPanel::toggleRandom()
{
    bool prev = model->hasRandom();
    model->setRandom( !prev );
}

void StandardPLPanel::gotoPlayingItem()
{
    view->scrollTo( model->currentIndex() );
}

void StandardPLPanel::handleExpansion( const QModelIndex& index )
{
    view->scrollTo( index );
}

/* PopupAdd Menu for the Add Menu */
void StandardPLPanel::popupAdd()
{
    QMenu popup;
    if( currentRootId == THEPL->p_local_category->i_id ||
        currentRootId == THEPL->p_local_onelevel->i_id )
    {
        popup.addAction( qtr(I_PL_ADDF), THEDP, SLOT( simplePLAppendDialog()) );
        popup.addAction( qtr(I_PL_ADDDIR), THEDP, SLOT( PLAppendDir()) );
        popup.addAction( qtr(I_OP_ADVOP), THEDP, SLOT( PLAppendDialog()) );
    }
    else if( ( THEPL->p_ml_category &&
                currentRootId == THEPL->p_ml_category->i_id ) ||
             ( THEPL->p_ml_onelevel &&
                currentRootId == THEPL->p_ml_onelevel->i_id ) )
    {
        popup.addAction( qtr(I_PL_ADDF), THEDP, SLOT( simpleMLAppendDialog()) );
        popup.addAction( qtr(I_PL_ADDDIR), THEDP, SLOT( MLAppendDir() ) );
        popup.addAction( qtr(I_OP_ADVOP), THEDP, SLOT( MLAppendDialog() ) );
    }

    popup.exec( QCursor::pos() - addButton->mapFromGlobal( QCursor::pos() )
                        + QPoint( 0, addButton->height() ) );
}

void StandardPLPanel::popupSelectColumn( QPoint pos )
{
    QMenu menu;

    /* We do not offer the option to hide index 0 column, or
    * QTreeView will behave weird */
    int i, j;
    for( i = 1 << 1, j = 1; i < COLUMN_END; i <<= 1, j++ )
    {
        QAction* option = menu.addAction(
            qfu( psz_column_title( i ) ) );
        option->setCheckable( true );
        option->setChecked( !view->isColumnHidden( j ) );
        selectColumnsSigMapper->setMapping( option, j );
        CONNECT( option, triggered(), selectColumnsSigMapper, map() );
    }
    menu.exec( QCursor::pos() );
}

void StandardPLPanel::toggleColumnShown( int i )
{
    view->setColumnHidden( i, !view->isColumnHidden( i ) );
}

/* Search in the playlist */
void StandardPLPanel::search( const QString& searchText )
{
    model->search( searchText );
}

void StandardPLPanel::doPopup( QModelIndex index, QPoint point )
{
    QItemSelectionModel *selection = view->selectionModel();
    QModelIndexList list = selection->selectedIndexes();
    model->popup( index, point, list );
}

/* Set the root of the new Playlist */
/* This activated by the selector selection */
void StandardPLPanel::setRoot( playlist_item_t *p_item )
{
    QPL_LOCK;
    assert( p_item );

    playlist_item_t *p_pref_item = playlist_GetPreferredNode( THEPL, p_item );
    if( p_pref_item ) p_item = p_pref_item;

    /* needed for popupAdd() */
    currentRootId = p_item->i_id;

    /* cosmetics, ..still need playlist locking.. */
    char *psz_title = input_item_GetName( p_item->p_input );
    title->setText( qfu(psz_title) );
    free( psz_title );

    QPL_UNLOCK;

    /* do THE job */
    model->rebuild( p_item );

    /* enable/disable adding */
    if( p_item == THEPL->p_local_category ||
        p_item == THEPL->p_local_onelevel )
    {
        addButton->setEnabled( true );
        addButton->setToolTip( qtr(I_PL_ADDPL) );
    }
    else if( ( THEPL->p_ml_category && p_item == THEPL->p_ml_category) ||
              ( THEPL->p_ml_onelevel && p_item == THEPL->p_ml_onelevel ) )
    {
        addButton->setEnabled( true );
        addButton->setToolTip( qtr(I_PL_ADDML) );
    }
    else
        addButton->setEnabled( false );
}

void StandardPLPanel::removeItem( int i_id )
{
    model->removeItem( i_id );
}

/* Delete and Suppr key remove the selection
   FilterKey function and code function */
void StandardPLPanel::keyPressEvent( QKeyEvent *e )
{
    switch( e->key() )
    {
    case Qt::Key_Back:
    case Qt::Key_Delete:
        deleteSelection();
        break;
    }
}

void StandardPLPanel::deleteSelection()
{
    QItemSelectionModel *selection = view->selectionModel();
    QModelIndexList list = selection->selectedIndexes();
    model->doDelete( list );
}

StandardPLPanel::~StandardPLPanel()
{
    getSettings()->beginGroup("Playlist");
    getSettings()->setValue( "headerState", view->header()->saveState() );
    getSettings()->endGroup();
}

<commit_msg>Qt4: reset playlist columns settings in transition to 1.1.0<commit_after>/*****************************************************************************
 * standardpanel.cpp : The "standard" playlist panel : just a treeview
 ****************************************************************************
 * Copyright (C) 2000-2005 the VideoLAN team
 * $Id$
 *
 * Authors: Clément Stenac <zorglub@videolan.org>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

#include "qt4.hpp"
#include "dialogs_provider.hpp"

#include "components/playlist/playlist_model.hpp"
#include "components/playlist/panels.hpp"
#include "util/customwidgets.hpp"

#include <vlc_intf_strings.h>

#include <QPushButton>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QHeaderView>
#include <QKeyEvent>
#include <QModelIndexList>
#include <QLabel>
#include <QSpacerItem>
#include <QMenu>
#include <QSignalMapper>
#include <assert.h>

#include "sorting.h"

StandardPLPanel::StandardPLPanel( PlaylistWidget *_parent,
                                  intf_thread_t *_p_intf,
                                  playlist_t *p_playlist,
                                  playlist_item_t *p_root ):
                                  PLPanel( _parent, _p_intf )
{
    model = new PLModel( p_playlist, p_intf, p_root, this );

    QVBoxLayout *layout = new QVBoxLayout();
    layout->setSpacing( 0 ); layout->setMargin( 0 );

    /* Create and configure the QTreeView */
    view = new QVLCTreeView;
    view->setModel( model );
    view->setIconSize( QSize( 20, 20 ) );
    view->setAlternatingRowColors( true );
    view->setAnimated( true );
    view->setSelectionBehavior( QAbstractItemView::SelectRows );
    view->setSelectionMode( QAbstractItemView::ExtendedSelection );
    view->setDragEnabled( true );
    view->setAcceptDrops( true );
    view->setDropIndicatorShown( true );
    view->header()->setSortIndicator( -1 , Qt::AscendingOrder );
    view->setUniformRowHeights( true );
    view->setSortingEnabled( true );

    getSettings()->beginGroup("Playlist");
    if( getSettings()->contains( "headerStateV2" ) )
    {
        view->header()->restoreState(
                getSettings()->value( "headerStateV2" ).toByteArray() );
    }
    else
    {
        int m, c;
        for( m = 1, c = 0; m != COLUMN_END; m <<= 1, c++ )
        {
            view->setColumnHidden( c, !( m & COLUMN_DEFAULT ) );
            if( m == COLUMN_TITLE ) view->header()->resizeSection( c, 200 );
            else if( m == COLUMN_DURATION ) view->header()->resizeSection( c, 80 );
        }
    }
    view->header()->setSortIndicatorShown( true );
    view->header()->setClickable( true );
    view->header()->setContextMenuPolicy( Qt::CustomContextMenu );
    getSettings()->endGroup();

    /* Connections for the TreeView */
    CONNECT( view, activated( const QModelIndex& ) ,
             model,activateItem( const QModelIndex& ) );
    CONNECT( view, rightClicked( QModelIndex , QPoint ),
             this, doPopup( QModelIndex, QPoint ) );
    CONNECT( view->header(), customContextMenuRequested( const QPoint & ),
             this, popupSelectColumn( QPoint ) );
    CONNECT( model, currentChanged( const QModelIndex& ),
             this, handleExpansion( const QModelIndex& ) );

    currentRootId = -1;

    /* Buttons configuration */
    QHBoxLayout *buttons = new QHBoxLayout;

    /* Add item to the playlist button */
    addButton = new QPushButton;
    addButton->setIcon( QIcon( ":/buttons/playlist/playlist_add" ) );
    addButton->setMaximumWidth( 30 );
    BUTTONACT( addButton, popupAdd() );
    buttons->addWidget( addButton );

    /* Random 2-state button */
    randomButton = new QPushButton( this );
    randomButton->setIcon( QIcon( ":/buttons/playlist/shuffle_on" ));
    randomButton->setToolTip( qtr( I_PL_RANDOM ));
    randomButton->setCheckable( true );
    randomButton->setChecked( model->hasRandom() );
    BUTTONACT( randomButton, toggleRandom() );
    buttons->addWidget( randomButton );

    /* Repeat 3-state button */
    repeatButton = new QPushButton( this );
    repeatButton->setToolTip( qtr( "Click to toggle between loop one, loop all" ) );
    repeatButton->setCheckable( true );

    if( model->hasRepeat() )
    {
        repeatButton->setIcon( QIcon( ":/buttons/playlist/repeat_one" ) );
        repeatButton->setChecked( true );
    }
    else if( model->hasLoop() )
    {
        repeatButton->setIcon( QIcon( ":/buttons/playlist/repeat_all" ) );
        repeatButton->setChecked( true );
    }
    else
    {
        repeatButton->setIcon( QIcon( ":/buttons/playlist/repeat_one" ) );
        repeatButton->setChecked( false );
    }
    BUTTONACT( repeatButton, toggleRepeat() );
    buttons->addWidget( repeatButton );

    /* Goto */
    gotoPlayingButton = new QPushButton;
    BUTTON_SET_ACT_I( gotoPlayingButton, "", buttons/playlist/jump_to,
            qtr( "Show the current item" ), gotoPlayingItem() );
    buttons->addWidget( gotoPlayingButton );

    /* A Spacer and the search possibilities */
    QSpacerItem *spacer = new QSpacerItem( 10, 20 );
    buttons->addItem( spacer );

    QLabel *filter = new QLabel( qtr(I_PL_SEARCH) + " " );
    buttons->addWidget( filter );

    SearchLineEdit *search = new SearchLineEdit( this );
    buttons->addWidget( search );
    filter->setBuddy( search );
    CONNECT( search, textChanged( const QString& ), this, search( const QString& ) );

    /* Title label */
    title = new QLabel;
    QFont titleFont;
    titleFont.setPointSize( titleFont.pointSize() + 6 );
    titleFont.setFamily( "Verdana" );
    title->setFont( titleFont );

    /* Finish the layout */
    layout->addWidget( title );
    layout->addWidget( view );
    layout->addLayout( buttons );
//    layout->addWidget( bar );
    setLayout( layout );

    selectColumnsSigMapper = new QSignalMapper( this );
    CONNECT( selectColumnsSigMapper, mapped( int ), this, toggleColumnShown( int ) );
}

/* Function to toggle between the Repeat states */
void StandardPLPanel::toggleRepeat()
{
    if( model->hasRepeat() )
    {
        model->setRepeat( false ); model->setLoop( true );
        repeatButton->setIcon( QIcon( ":/buttons/playlist/repeat_all" ) );
        repeatButton->setChecked( true );
    }
    else if( model->hasLoop() )
    {
        model->setRepeat( false ) ; model->setLoop( false );
        repeatButton->setChecked( false );
        repeatButton->setIcon( QIcon( ":/buttons/playlist/repeat_one" ) );
    }
    else
    {
        model->setRepeat( true ); model->setLoop( false );
        repeatButton->setChecked( true );
        repeatButton->setIcon( QIcon( ":/buttons/playlist/repeat_one" ) );
    }
}

/* Function to toggle between the Random states */
void StandardPLPanel::toggleRandom()
{
    bool prev = model->hasRandom();
    model->setRandom( !prev );
}

void StandardPLPanel::gotoPlayingItem()
{
    view->scrollTo( model->currentIndex() );
}

void StandardPLPanel::handleExpansion( const QModelIndex& index )
{
    view->scrollTo( index );
}

/* PopupAdd Menu for the Add Menu */
void StandardPLPanel::popupAdd()
{
    QMenu popup;
    if( currentRootId == THEPL->p_local_category->i_id ||
        currentRootId == THEPL->p_local_onelevel->i_id )
    {
        popup.addAction( qtr(I_PL_ADDF), THEDP, SLOT( simplePLAppendDialog()) );
        popup.addAction( qtr(I_PL_ADDDIR), THEDP, SLOT( PLAppendDir()) );
        popup.addAction( qtr(I_OP_ADVOP), THEDP, SLOT( PLAppendDialog()) );
    }
    else if( ( THEPL->p_ml_category &&
                currentRootId == THEPL->p_ml_category->i_id ) ||
             ( THEPL->p_ml_onelevel &&
                currentRootId == THEPL->p_ml_onelevel->i_id ) )
    {
        popup.addAction( qtr(I_PL_ADDF), THEDP, SLOT( simpleMLAppendDialog()) );
        popup.addAction( qtr(I_PL_ADDDIR), THEDP, SLOT( MLAppendDir() ) );
        popup.addAction( qtr(I_OP_ADVOP), THEDP, SLOT( MLAppendDialog() ) );
    }

    popup.exec( QCursor::pos() - addButton->mapFromGlobal( QCursor::pos() )
                        + QPoint( 0, addButton->height() ) );
}

void StandardPLPanel::popupSelectColumn( QPoint pos )
{
    QMenu menu;

    /* We do not offer the option to hide index 0 column, or
    * QTreeView will behave weird */
    int i, j;
    for( i = 1 << 1, j = 1; i < COLUMN_END; i <<= 1, j++ )
    {
        QAction* option = menu.addAction(
            qfu( psz_column_title( i ) ) );
        option->setCheckable( true );
        option->setChecked( !view->isColumnHidden( j ) );
        selectColumnsSigMapper->setMapping( option, j );
        CONNECT( option, triggered(), selectColumnsSigMapper, map() );
    }
    menu.exec( QCursor::pos() );
}

void StandardPLPanel::toggleColumnShown( int i )
{
    view->setColumnHidden( i, !view->isColumnHidden( i ) );
}

/* Search in the playlist */
void StandardPLPanel::search( const QString& searchText )
{
    model->search( searchText );
}

void StandardPLPanel::doPopup( QModelIndex index, QPoint point )
{
    QItemSelectionModel *selection = view->selectionModel();
    QModelIndexList list = selection->selectedIndexes();
    model->popup( index, point, list );
}

/* Set the root of the new Playlist */
/* This activated by the selector selection */
void StandardPLPanel::setRoot( playlist_item_t *p_item )
{
    QPL_LOCK;
    assert( p_item );

    playlist_item_t *p_pref_item = playlist_GetPreferredNode( THEPL, p_item );
    if( p_pref_item ) p_item = p_pref_item;

    /* needed for popupAdd() */
    currentRootId = p_item->i_id;

    /* cosmetics, ..still need playlist locking.. */
    char *psz_title = input_item_GetName( p_item->p_input );
    title->setText( qfu(psz_title) );
    free( psz_title );

    QPL_UNLOCK;

    /* do THE job */
    model->rebuild( p_item );

    /* enable/disable adding */
    if( p_item == THEPL->p_local_category ||
        p_item == THEPL->p_local_onelevel )
    {
        addButton->setEnabled( true );
        addButton->setToolTip( qtr(I_PL_ADDPL) );
    }
    else if( ( THEPL->p_ml_category && p_item == THEPL->p_ml_category) ||
              ( THEPL->p_ml_onelevel && p_item == THEPL->p_ml_onelevel ) )
    {
        addButton->setEnabled( true );
        addButton->setToolTip( qtr(I_PL_ADDML) );
    }
    else
        addButton->setEnabled( false );
}

void StandardPLPanel::removeItem( int i_id )
{
    model->removeItem( i_id );
}

/* Delete and Suppr key remove the selection
   FilterKey function and code function */
void StandardPLPanel::keyPressEvent( QKeyEvent *e )
{
    switch( e->key() )
    {
    case Qt::Key_Back:
    case Qt::Key_Delete:
        deleteSelection();
        break;
    }
}

void StandardPLPanel::deleteSelection()
{
    QItemSelectionModel *selection = view->selectionModel();
    QModelIndexList list = selection->selectedIndexes();
    model->doDelete( list );
}

StandardPLPanel::~StandardPLPanel()
{
    getSettings()->beginGroup("Playlist");
    getSettings()->setValue( "headerStateV2", view->header()->saveState() );
    getSettings()->endGroup();
}

<|endoftext|>


<commit_before>b5a16817-4b02-11e5-8454-28cfe9171a43<commit_msg>Put the thingie in the thingie<commit_after>b5ae7e51-4b02-11e5-b6d7-28cfe9171a43<|endoftext|>


<commit_before>// Copyright 2022 The IREE Authors
//
// Licensed under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#include "iree/compiler/Codegen/Common/LinalgOpInfo.h"
#include "iree/compiler/Codegen/LLVMGPU/TilingUtils.h"
#include "iree/compiler/Codegen/LLVMGPU/TransposeUtils.h"
#include "iree/compiler/Codegen/PassDetail.h"
#include "iree/compiler/Codegen/Passes.h"
#include "mlir/Dialect/Bufferization/IR/Bufferization.h"
#include "mlir/Dialect/Func/IR/FuncOps.h"
#include "mlir/Transforms/Passes.h"

#define DEBUG_TYPE "iree-llvmgpu-alloc"

namespace mlir {
namespace iree_compiler {

/// Filter to decide which contract ops need allocations.
static bool contractOpFilter(Operation *op) {
  auto linalgOp = dyn_cast<linalg::LinalgOp>(op);
  if (!linalgOp) return false;
  SmallVector<unsigned> dims;
  linalgOp.getParallelDims(dims);
  SmallVector<int64_t, 4> shapes = linalgOp.getStaticLoopRanges();
  // Don't promote vector*matrix kind of case.
  int numNonUnitParallelLoop = 0;
  for (unsigned parallelDim : dims) {
    if (shapes[parallelDim] != 1) {
      numNonUnitParallelLoop++;
    }
  }
  return numNonUnitParallelLoop > 1 && linalg::isaContractionOpInterface(op) &&
         linalgOp.getNumParallelLoops() >= 2 &&
         linalgOp.getNumParallelLoops() <= 3;
}

/// Filter to decide which transpose ops need allocations.
static bool transposeOpFilter(Operation *op) {
  auto linalgOp = dyn_cast<linalg::LinalgOp>(op);
  if (!linalgOp) return false;
  LinalgOpInfo opInfo(linalgOp, sharedMemTransposeFilter);
  return opInfo.isTranspose();
}

/// Returns true if the index map represents a transpose that benefits from
/// shared mem.
static bool isSharedMemTranspose(AffineMap indexMap) {
  if (!indexMap.isEmpty() && indexMap.isPermutation()) {
    // Ensure that the fasted moving dimension (the last one) is permuted,
    // Otherwise shared memory promotion will not benefit the operation.
    if (indexMap.getDimPosition(indexMap.getNumDims() - 1) !=
        indexMap.getNumDims() - 1) {
      return true;
    }
  }
  return false;
}

namespace {
struct LLVMGPUTensorAllocPass
    : public LLVMGPUTensorAllocBase<LLVMGPUTensorAllocPass> {
 private:
  GPUPromoteSharedMemPattern promoteSharedMemPattern =
      GPUPromoteSharedMemPattern::ContractionOpPattern;

 public:
  LLVMGPUTensorAllocPass(GPUPromoteSharedMemPattern promoteSharedMemPattern)
      : promoteSharedMemPattern(promoteSharedMemPattern) {}
  void getDependentDialects(DialectRegistry &registry) const override {
    registry.insert<bufferization::BufferizationDialect>();
  }
  void runOnOperation() override {
    auto funcOp = getOperation();

    // Tile the reduction first to reduce the alloc size.
    if (failed(tileToSerialLoops(funcOp))) {
      return signalPassFailure();
    }

    SmallVector<Operation *> opsToPromote;
    funcOp.walk([&](Operation *op) {
      switch (promoteSharedMemPattern) {
        case GPUPromoteSharedMemPattern::ContractionOpPattern:
          if (contractOpFilter(op)) opsToPromote.push_back(op);
          break;
        case GPUPromoteSharedMemPattern::TransposeOpPattern:
          if (transposeOpFilter(op)) opsToPromote.push_back(op);
          break;
      }
    });
    for (Operation *op : opsToPromote) {
      OpBuilder builder(op);
      auto linalgOp = cast<linalg::LinalgOp>(op);
      bufferization::BufferizationOptions options;
      switch (promoteSharedMemPattern) {
        case GPUPromoteSharedMemPattern::ContractionOpPattern:
          // Promote all the input operands
          for (auto operand : linalgOp.getInputOperands()) {
            FailureOr<Value> ret = bufferization::allocateTensorForShapedValue(
                builder, op->getLoc(), operand->get(), false, options, true);
            if (failed(ret)) {
              return signalPassFailure();
            }
            Value v = ret.value();
            operand->set(v);
          }
          break;

        case GPUPromoteSharedMemPattern::TransposeOpPattern:
          LinalgOpInfo opInfo(linalgOp, sharedMemTransposeFilter);

          for (auto operand : opInfo.getTransposeOperands()) {
            FailureOr<Value> ret = bufferization::allocateTensorForShapedValue(
                builder, op->getLoc(), operand->get(), false, options, true);
            if (failed(ret)) {
              return signalPassFailure();
            }
            Value v = ret.value();
            operand->set(v);
          }
          break;
      }
    }
  }
};
}  // namespace

std::unique_ptr<OperationPass<func::FuncOp>> createLLVMGPUTensorAlloc(
    GPUPromoteSharedMemPattern promoteSharedMemPattern) {
  return std::make_unique<LLVMGPUTensorAllocPass>(promoteSharedMemPattern);
}

}  // namespace iree_compiler
}  // namespace mlir
<commit_msg>Do not promote to sharemem for dynamic tensors (#10649)<commit_after>// Copyright 2022 The IREE Authors
//
// Licensed under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#include "iree/compiler/Codegen/Common/LinalgOpInfo.h"
#include "iree/compiler/Codegen/LLVMGPU/TilingUtils.h"
#include "iree/compiler/Codegen/LLVMGPU/TransposeUtils.h"
#include "iree/compiler/Codegen/PassDetail.h"
#include "iree/compiler/Codegen/Passes.h"
#include "mlir/Dialect/Bufferization/IR/Bufferization.h"
#include "mlir/Dialect/Func/IR/FuncOps.h"
#include "mlir/Transforms/Passes.h"

#define DEBUG_TYPE "iree-llvmgpu-alloc"

namespace mlir {
namespace iree_compiler {

/// Filter to decide which contract ops need allocations.
static bool contractOpFilter(Operation *op) {
  auto linalgOp = dyn_cast<linalg::LinalgOp>(op);
  if (!linalgOp) return false;

  // The workgroup specialization already makes static shapes available for the
  // main tile part and makes the partial tile computation small, so promoting
  // to shared memory for the partial tile actually hurts the performance.
  if (linalgOp.hasDynamicShape()) return false;

  SmallVector<unsigned> dims;
  linalgOp.getParallelDims(dims);
  SmallVector<int64_t, 4> shapes = linalgOp.getStaticLoopRanges();
  // Don't promote vector*matrix kind of case.
  int numNonUnitParallelLoop = 0;
  for (unsigned parallelDim : dims) {
    if (shapes[parallelDim] != 1) {
      numNonUnitParallelLoop++;
    }
  }
  return numNonUnitParallelLoop > 1 && linalg::isaContractionOpInterface(op) &&
         linalgOp.getNumParallelLoops() >= 2 &&
         linalgOp.getNumParallelLoops() <= 3;
}

/// Filter to decide which transpose ops need allocations.
static bool transposeOpFilter(Operation *op) {
  auto linalgOp = dyn_cast<linalg::LinalgOp>(op);
  if (!linalgOp) return false;
  LinalgOpInfo opInfo(linalgOp, sharedMemTransposeFilter);
  return opInfo.isTranspose();
}

/// Returns true if the index map represents a transpose that benefits from
/// shared mem.
static bool isSharedMemTranspose(AffineMap indexMap) {
  if (!indexMap.isEmpty() && indexMap.isPermutation()) {
    // Ensure that the fasted moving dimension (the last one) is permuted,
    // Otherwise shared memory promotion will not benefit the operation.
    if (indexMap.getDimPosition(indexMap.getNumDims() - 1) !=
        indexMap.getNumDims() - 1) {
      return true;
    }
  }
  return false;
}

namespace {
struct LLVMGPUTensorAllocPass
    : public LLVMGPUTensorAllocBase<LLVMGPUTensorAllocPass> {
 private:
  GPUPromoteSharedMemPattern promoteSharedMemPattern =
      GPUPromoteSharedMemPattern::ContractionOpPattern;

 public:
  LLVMGPUTensorAllocPass(GPUPromoteSharedMemPattern promoteSharedMemPattern)
      : promoteSharedMemPattern(promoteSharedMemPattern) {}
  void getDependentDialects(DialectRegistry &registry) const override {
    registry.insert<bufferization::BufferizationDialect>();
  }
  void runOnOperation() override {
    auto funcOp = getOperation();

    // Tile the reduction first to reduce the alloc size.
    if (failed(tileToSerialLoops(funcOp))) {
      return signalPassFailure();
    }

    SmallVector<Operation *> opsToPromote;
    funcOp.walk([&](Operation *op) {
      switch (promoteSharedMemPattern) {
        case GPUPromoteSharedMemPattern::ContractionOpPattern:
          if (contractOpFilter(op)) opsToPromote.push_back(op);
          break;
        case GPUPromoteSharedMemPattern::TransposeOpPattern:
          if (transposeOpFilter(op)) opsToPromote.push_back(op);
          break;
      }
    });
    for (Operation *op : opsToPromote) {
      OpBuilder builder(op);
      auto linalgOp = cast<linalg::LinalgOp>(op);
      bufferization::BufferizationOptions options;
      switch (promoteSharedMemPattern) {
        case GPUPromoteSharedMemPattern::ContractionOpPattern:
          // Promote all the input operands
          for (auto operand : linalgOp.getInputOperands()) {
            FailureOr<Value> ret = bufferization::allocateTensorForShapedValue(
                builder, op->getLoc(), operand->get(), false, options, true);
            if (failed(ret)) {
              return signalPassFailure();
            }
            Value v = ret.value();
            operand->set(v);
          }
          break;

        case GPUPromoteSharedMemPattern::TransposeOpPattern:
          LinalgOpInfo opInfo(linalgOp, sharedMemTransposeFilter);

          for (auto operand : opInfo.getTransposeOperands()) {
            FailureOr<Value> ret = bufferization::allocateTensorForShapedValue(
                builder, op->getLoc(), operand->get(), false, options, true);
            if (failed(ret)) {
              return signalPassFailure();
            }
            Value v = ret.value();
            operand->set(v);
          }
          break;
      }
    }
  }
};
}  // namespace

std::unique_ptr<OperationPass<func::FuncOp>> createLLVMGPUTensorAlloc(
    GPUPromoteSharedMemPattern promoteSharedMemPattern) {
  return std::make_unique<LLVMGPUTensorAllocPass>(promoteSharedMemPattern);
}

}  // namespace iree_compiler
}  // namespace mlir
<|endoftext|>


<commit_before>#include <cpp-pcp-client/protocol/v1/serialization.hpp>

#if _WIN32
#include <Winsock2.h>
#else
#include <netinet/in.h>  // endianess functions: htonl, ntohl
#endif

namespace PCPClient {
namespace v1 {

#if BOOST_ENDIAN_LITTLE_BYTE

uint32_t getNetworkNumber(const uint32_t& number)
{
    return htonl(number);
}

uint32_t getHostNumber(const uint32_t& number)
{
    return ntohl(number);
}

#endif  // BOOST_ENDIAN_LITTLE_BYTE

}  // namespace v1
}  // namespace PCPClient
<commit_msg>(maint) if -> ifdef in serialization protocol<commit_after>#include <cpp-pcp-client/protocol/v1/serialization.hpp>

#if _WIN32
#include <Winsock2.h>
#else
#include <netinet/in.h>  // endianess functions: htonl, ntohl
#endif

namespace PCPClient {
namespace v1 {

#ifdef BOOST_ENDIAN_LITTLE_BYTE

uint32_t getNetworkNumber(const uint32_t& number)
{
    return htonl(number);
}

uint32_t getHostNumber(const uint32_t& number)
{
    return ntohl(number);
}

#endif  // BOOST_ENDIAN_LITTLE_BYTE

}  // namespace v1
}  // namespace PCPClient
<|endoftext|>


<commit_before>// Copyright 2022 The IREE Authors
//
// Licensed under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#include "iree/compiler/Codegen/Common/LinalgOpInfo.h"
#include "iree/compiler/Codegen/LLVMGPU/TilingUtils.h"
#include "iree/compiler/Codegen/LLVMGPU/TransposeUtils.h"
#include "iree/compiler/Codegen/PassDetail.h"
#include "iree/compiler/Codegen/Passes.h"
#include "mlir/Dialect/Bufferization/IR/Bufferization.h"
#include "mlir/Dialect/Func/IR/FuncOps.h"
#include "mlir/Transforms/Passes.h"

#define DEBUG_TYPE "iree-llvmgpu-alloc"

namespace mlir {
namespace iree_compiler {

/// Filter to decide which contract ops need allocations.
static bool contractOpFilter(Operation *op) {
  auto linalgOp = dyn_cast<linalg::LinalgOp>(op);
  if (!linalgOp) return false;
  // Can't promote dynamic shapes.
  if (linalgOp.hasDynamicShape()) return false;
  SmallVector<unsigned> dims;
  linalgOp.getParallelDims(dims);
  SmallVector<int64_t, 4> shapes = linalgOp.getStaticLoopRanges();
  // Don't promote vector*matrix kind of case.
  int numNonUnitParallelLoop = 0;
  for (unsigned parallelDim : dims) {
    if (shapes[parallelDim] != 1) {
      numNonUnitParallelLoop++;
    }
  }
  return numNonUnitParallelLoop > 1 && linalg::isaContractionOpInterface(op) &&
         linalgOp.getNumParallelLoops() >= 2 &&
         linalgOp.getNumParallelLoops() <= 3;
}

/// Filter to decide which transpose ops need allocations.
static bool transposeOpFilter(Operation *op) {
  auto linalgOp = dyn_cast<linalg::LinalgOp>(op);
  if (!linalgOp) return false;
  LinalgOpInfo opInfo(linalgOp, sharedMemTransposeFilter);
  return opInfo.isTranspose();
}

/// Returns true if the index map represents a transpose that benefits from
/// shared mem.
static bool isSharedMemTranspose(AffineMap indexMap) {
  if (!indexMap.isEmpty() && indexMap.isPermutation()) {
    // Ensure that the fasted moving dimension (the last one) is permuted,
    // Otherwise shared memory promotion will not benefit the operation.
    if (indexMap.getDimPosition(indexMap.getNumDims() - 1) !=
        indexMap.getNumDims() - 1) {
      return true;
    }
  }
  return false;
}

namespace {
struct LLVMGPUTensorAllocPass
    : public LLVMGPUTensorAllocBase<LLVMGPUTensorAllocPass> {
 private:
  GPUPromoteSharedMemPattern promoteSharedMemPattern =
      GPUPromoteSharedMemPattern::ContractionOpPattern;

 public:
  LLVMGPUTensorAllocPass(GPUPromoteSharedMemPattern promoteSharedMemPattern)
      : promoteSharedMemPattern(promoteSharedMemPattern) {}
  void getDependentDialects(DialectRegistry &registry) const override {
    registry.insert<bufferization::BufferizationDialect>();
  }
  void runOnOperation() override {
    auto funcOp = getOperation();

    // Tile the reduction first to reduce the alloc size.
    if (failed(tileReduction(funcOp))) {
      return signalPassFailure();
    }

    SmallVector<Operation *> opsToPromote;
    funcOp.walk([&](Operation *op) {
      switch (promoteSharedMemPattern) {
        case GPUPromoteSharedMemPattern::ContractionOpPattern:
          if (contractOpFilter(op)) opsToPromote.push_back(op);
          break;
        case GPUPromoteSharedMemPattern::TransposeOpPattern:
          if (transposeOpFilter(op)) opsToPromote.push_back(op);
          break;
      }
    });
    for (Operation *op : opsToPromote) {
      OpBuilder builder(op);
      auto linalgOp = cast<linalg::LinalgOp>(op);
      bufferization::BufferizationOptions options;
      switch (promoteSharedMemPattern) {
        case GPUPromoteSharedMemPattern::ContractionOpPattern:
          // Promote all the input operands
          for (auto operand : linalgOp.getInputOperands()) {
            FailureOr<Value> ret = bufferization::allocateTensorForShapedValue(
                builder, op->getLoc(), operand->get(), false, options, true);
            if (failed(ret)) {
              return signalPassFailure();
            }
            Value v = ret.value();
            operand->set(v);
          }
          break;

        case GPUPromoteSharedMemPattern::TransposeOpPattern:
          LinalgOpInfo opInfo(linalgOp, sharedMemTransposeFilter);

          for (auto operand : opInfo.getTransposeOperands()) {
            FailureOr<Value> ret = bufferization::allocateTensorForShapedValue(
                builder, op->getLoc(), operand->get(), false, options, true);
            if (failed(ret)) {
              return signalPassFailure();
            }
            Value v = ret.value();
            operand->set(v);
          }
          break;
      }
    }
  }
};
}  // namespace

std::unique_ptr<OperationPass<func::FuncOp>> createLLVMGPUTensorAlloc(
    GPUPromoteSharedMemPattern promoteSharedMemPattern) {
  return std::make_unique<LLVMGPUTensorAllocPass>(promoteSharedMemPattern);
}

}  // namespace iree_compiler
}  // namespace mlir
<commit_msg>[LLVMGPU] Remove restriction on shared memory promotion (#10558)<commit_after>// Copyright 2022 The IREE Authors
//
// Licensed under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#include "iree/compiler/Codegen/Common/LinalgOpInfo.h"
#include "iree/compiler/Codegen/LLVMGPU/TilingUtils.h"
#include "iree/compiler/Codegen/LLVMGPU/TransposeUtils.h"
#include "iree/compiler/Codegen/PassDetail.h"
#include "iree/compiler/Codegen/Passes.h"
#include "mlir/Dialect/Bufferization/IR/Bufferization.h"
#include "mlir/Dialect/Func/IR/FuncOps.h"
#include "mlir/Transforms/Passes.h"

#define DEBUG_TYPE "iree-llvmgpu-alloc"

namespace mlir {
namespace iree_compiler {

/// Filter to decide which contract ops need allocations.
static bool contractOpFilter(Operation *op) {
  auto linalgOp = dyn_cast<linalg::LinalgOp>(op);
  if (!linalgOp) return false;
  SmallVector<unsigned> dims;
  linalgOp.getParallelDims(dims);
  SmallVector<int64_t, 4> shapes = linalgOp.getStaticLoopRanges();
  // Don't promote vector*matrix kind of case.
  int numNonUnitParallelLoop = 0;
  for (unsigned parallelDim : dims) {
    if (shapes[parallelDim] != 1) {
      numNonUnitParallelLoop++;
    }
  }
  return numNonUnitParallelLoop > 1 && linalg::isaContractionOpInterface(op) &&
         linalgOp.getNumParallelLoops() >= 2 &&
         linalgOp.getNumParallelLoops() <= 3;
}

/// Filter to decide which transpose ops need allocations.
static bool transposeOpFilter(Operation *op) {
  auto linalgOp = dyn_cast<linalg::LinalgOp>(op);
  if (!linalgOp) return false;
  LinalgOpInfo opInfo(linalgOp, sharedMemTransposeFilter);
  return opInfo.isTranspose();
}

/// Returns true if the index map represents a transpose that benefits from
/// shared mem.
static bool isSharedMemTranspose(AffineMap indexMap) {
  if (!indexMap.isEmpty() && indexMap.isPermutation()) {
    // Ensure that the fasted moving dimension (the last one) is permuted,
    // Otherwise shared memory promotion will not benefit the operation.
    if (indexMap.getDimPosition(indexMap.getNumDims() - 1) !=
        indexMap.getNumDims() - 1) {
      return true;
    }
  }
  return false;
}

namespace {
struct LLVMGPUTensorAllocPass
    : public LLVMGPUTensorAllocBase<LLVMGPUTensorAllocPass> {
 private:
  GPUPromoteSharedMemPattern promoteSharedMemPattern =
      GPUPromoteSharedMemPattern::ContractionOpPattern;

 public:
  LLVMGPUTensorAllocPass(GPUPromoteSharedMemPattern promoteSharedMemPattern)
      : promoteSharedMemPattern(promoteSharedMemPattern) {}
  void getDependentDialects(DialectRegistry &registry) const override {
    registry.insert<bufferization::BufferizationDialect>();
  }
  void runOnOperation() override {
    auto funcOp = getOperation();

    // Tile the reduction first to reduce the alloc size.
    if (failed(tileReduction(funcOp))) {
      return signalPassFailure();
    }

    SmallVector<Operation *> opsToPromote;
    funcOp.walk([&](Operation *op) {
      switch (promoteSharedMemPattern) {
        case GPUPromoteSharedMemPattern::ContractionOpPattern:
          if (contractOpFilter(op)) opsToPromote.push_back(op);
          break;
        case GPUPromoteSharedMemPattern::TransposeOpPattern:
          if (transposeOpFilter(op)) opsToPromote.push_back(op);
          break;
      }
    });
    for (Operation *op : opsToPromote) {
      OpBuilder builder(op);
      auto linalgOp = cast<linalg::LinalgOp>(op);
      bufferization::BufferizationOptions options;
      switch (promoteSharedMemPattern) {
        case GPUPromoteSharedMemPattern::ContractionOpPattern:
          // Promote all the input operands
          for (auto operand : linalgOp.getInputOperands()) {
            FailureOr<Value> ret = bufferization::allocateTensorForShapedValue(
                builder, op->getLoc(), operand->get(), false, options, true);
            if (failed(ret)) {
              return signalPassFailure();
            }
            Value v = ret.value();
            operand->set(v);
          }
          break;

        case GPUPromoteSharedMemPattern::TransposeOpPattern:
          LinalgOpInfo opInfo(linalgOp, sharedMemTransposeFilter);

          for (auto operand : opInfo.getTransposeOperands()) {
            FailureOr<Value> ret = bufferization::allocateTensorForShapedValue(
                builder, op->getLoc(), operand->get(), false, options, true);
            if (failed(ret)) {
              return signalPassFailure();
            }
            Value v = ret.value();
            operand->set(v);
          }
          break;
      }
    }
  }
};
}  // namespace

std::unique_ptr<OperationPass<func::FuncOp>> createLLVMGPUTensorAlloc(
    GPUPromoteSharedMemPattern promoteSharedMemPattern) {
  return std::make_unique<LLVMGPUTensorAllocPass>(promoteSharedMemPattern);
}

}  // namespace iree_compiler
}  // namespace mlir
<|endoftext|>


<commit_before>09ea5259-2748-11e6-b2e1-e0f84713e7b8<commit_msg>fixes, fixes for everyone<commit_after>09f4e54c-2748-11e6-8052-e0f84713e7b8<|endoftext|>