<commit_before>/*
Name:		EasyBuzzer.cpp
Version:	1.0.3
Created:	9/29/2017 12:03:48 AM
Updated:	2/19/2019 12:19:00 AM
Author:		Evert Arias
Github:		https://github.com/evert-arias/EasyBuzzer
			Copyright (c) 2019 Evert Arias
*/

#include "EasyBuzzer.h"

/* Class constructor */
EasyBuzzerClass::EasyBuzzerClass()
{
#if defined ESP32
	ledcSetup(mChannel, mFreq, mResolution);
#endif
}
/* Class destructor */
EasyBuzzerClass::~EasyBuzzerClass() {}
/* Start beeping continuously at a given frequency. */
void EasyBuzzerClass::beep(unsigned int frequency)
{
	beep(frequency, 1, 0, 1, 0, 0, NULL);
}
/* Beep at a given frequency an specific number of beeps. */
void EasyBuzzerClass::beep(unsigned int frequency, unsigned int beeps)
{
	beep(frequency, mOnDuration, mOffDuration, 1, mPauseDuration, beeps, NULL);
}
/* Beep at a given frequency an specific number of beeps, with callback functionality. */
void EasyBuzzerClass::beep(unsigned int frequency, unsigned int beeps, void (*finishedCallbackFunction)())
{
	beep(frequency, mOnDuration, mOffDuration, 1, mPauseDuration, beeps, finishedCallbackFunction);
}
/* Beep sequence at a given frequency. */
void EasyBuzzerClass::beep(unsigned int frequency, unsigned int const onDuration, unsigned int const offDuration, byte const beeps, unsigned int const pauseDuration, unsigned int const sequences)
{
	mFreq = frequency;
	mOnDuration = onDuration ? max(MINIMUM_INTERVAL, onDuration) : 0;
	mOffDuration = offDuration ? max(MINIMUM_INTERVAL, offDuration) : 0;
	mBeeps = beeps;
	mPauseDuration = pauseDuration ? max(MINIMUM_INTERVAL, pauseDuration) : 0;
	mSequences = sequences;
	mFinishedCallbackFunction = NULL;
	mStartTime = max(millis(), 1);
	mLastRunTime = 0;
	update();
}
/* Beep sequence at a given frequency, with callback functionality. */
void EasyBuzzerClass::beep(unsigned int frequency, unsigned int const onDuration, unsigned int const offDuration, byte const beeps, unsigned int const pauseDuration, unsigned int const sequences, void (*finishedCallbackFunction)())
{
	mFreq = frequency;
	mOnDuration = onDuration ? max(MINIMUM_INTERVAL, onDuration) : 0;
	mOffDuration = offDuration ? max(MINIMUM_INTERVAL, offDuration) : 0;
	mBeeps = beeps;
	mPauseDuration = pauseDuration ? max(MINIMUM_INTERVAL, pauseDuration) : 0;
	mSequences = sequences;
	mFinishedCallbackFunction = finishedCallbackFunction;
	mStartTime = max(millis(), 1);
	mLastRunTime = 0;
	update();
}
/* Start beeping at a given frequency, for an specific duration. */
void EasyBuzzerClass::singleBeep(unsigned int frequency, unsigned int duration)
{
	beep(frequency, duration, mOffDuration, 1, mPauseDuration, 1, NULL);
}
/* Start beeping at a given frequency, for an specific duration, with callback functionality. */
void EasyBuzzerClass::singleBeep(unsigned int frequency, unsigned int duration, void (*finishedCallbackFunction)())
{
	beep(frequency, duration, mOffDuration, 1, mPauseDuration, 1, finishedCallbackFunction);
}
/* Stop beeping. */
void EasyBuzzerClass::stopBeep()
{
#if defined ESP32
	ledcDetachPin(mPin);
#else
	noTone(mPin);
#endif
}
/* Set the pin where the buzzer is connected. */
void EasyBuzzerClass::setPin(unsigned int pin)
{
	mPin = pin;
}
/* Set On duration. */
void EasyBuzzerClass::setOnDuration(unsigned int duration)
{
	mOnDuration = duration;
}
/* Set Off duration. */
void EasyBuzzerClass::setOffDuration(unsigned int duration)
{
	mOffDuration = duration;
}
/* Set Pause duration. */
void EasyBuzzerClass::setPauseDuration(unsigned int duration)
{
	mPauseDuration = duration;
}
/* Update function that keeps the library running. */
void EasyBuzzerClass::update()
{
	unsigned long currentTime = millis();
	if (currentTime - mLastRunTime < MINIMUM_INTERVAL)
	{
		return;
	}
	mLastRunTime = currentTime;
	if (!mStartTime || !mPin)
	{
		return;
	}

	unsigned long elapsedTime = currentTime - mStartTime;
	unsigned int blinkDuration = mOnDuration + mOffDuration;
	unsigned int sequenceDuration = blinkDuration * mBeeps + mPauseDuration - mOffDuration;

	if (!sequenceDuration || (mSequences != 0 && elapsedTime / sequenceDuration >= mSequences))
	{
		mStartTime = 0;
		if (mFinishedCallbackFunction)
		{
			mFinishedCallbackFunction();
		}
		return;
	};

	unsigned int blinkingDuration = blinkDuration * mBeeps;
	unsigned int timeInSequence = elapsedTime % sequenceDuration;

#if defined ESP32
	if (timeInSequence < blinkingDuration && timeInSequence % blinkDuration < mOnDuration)
	{
		ledcAttachPin(mPin, mChannel);
		ledcWriteTone(mChannel, mFreq);
	}
	else
	{
		ledcDetachPin(mPin);
	};
#else
	if (timeInSequence < blinkingDuration && timeInSequence % blinkDuration < mOnDuration)
	{
		tone(mPin, mFreq);
	}
	else
	{
		noTone(mPin);
	};
#endif
}

EasyBuzzerClass EasyBuzzer;
<commit_msg>Fix stopBeep() method on ESP32<commit_after>/*
Name:		EasyBuzzer.cpp
Version:	1.0.3
Created:	9/29/2017 12:03:48 AM
Updated:	2/19/2019 12:19:00 AM
Author:		Evert Arias
Github:		https://github.com/evert-arias/EasyBuzzer
			Copyright (c) 2019 Evert Arias
*/

#include "EasyBuzzer.h"

/* Class constructor */
EasyBuzzerClass::EasyBuzzerClass()
{
#if defined ESP32
	ledcSetup(mChannel, mFreq, mResolution);
#endif
}
/* Class destructor */
EasyBuzzerClass::~EasyBuzzerClass() {}
/* Start beeping continuously at a given frequency. */
void EasyBuzzerClass::beep(unsigned int frequency)
{
	beep(frequency, 1, 0, 1, 0, 0, NULL);
}
/* Beep at a given frequency an specific number of beeps. */
void EasyBuzzerClass::beep(unsigned int frequency, unsigned int beeps)
{
	beep(frequency, mOnDuration, mOffDuration, 1, mPauseDuration, beeps, NULL);
}
/* Beep at a given frequency an specific number of beeps, with callback functionality. */
void EasyBuzzerClass::beep(unsigned int frequency, unsigned int beeps, void (*finishedCallbackFunction)())
{
	beep(frequency, mOnDuration, mOffDuration, 1, mPauseDuration, beeps, finishedCallbackFunction);
}
/* Beep sequence at a given frequency. */
void EasyBuzzerClass::beep(unsigned int frequency, unsigned int const onDuration, unsigned int const offDuration, byte const beeps, unsigned int const pauseDuration, unsigned int const sequences)
{
	mFreq = frequency;
	mOnDuration = onDuration ? max(MINIMUM_INTERVAL, onDuration) : 0;
	mOffDuration = offDuration ? max(MINIMUM_INTERVAL, offDuration) : 0;
	mBeeps = beeps;
	mPauseDuration = pauseDuration ? max(MINIMUM_INTERVAL, pauseDuration) : 0;
	mSequences = sequences;
	mFinishedCallbackFunction = NULL;
	mStartTime = max(millis(), 1);
	mLastRunTime = 0;
	update();
}
/* Beep sequence at a given frequency, with callback functionality. */
void EasyBuzzerClass::beep(unsigned int frequency, unsigned int const onDuration, unsigned int const offDuration, byte const beeps, unsigned int const pauseDuration, unsigned int const sequences, void (*finishedCallbackFunction)())
{
	mFreq = frequency;
	mOnDuration = onDuration ? max(MINIMUM_INTERVAL, onDuration) : 0;
	mOffDuration = offDuration ? max(MINIMUM_INTERVAL, offDuration) : 0;
	mBeeps = beeps;
	mPauseDuration = pauseDuration ? max(MINIMUM_INTERVAL, pauseDuration) : 0;
	mSequences = sequences;
	mFinishedCallbackFunction = finishedCallbackFunction;
	mStartTime = max(millis(), 1);
	mLastRunTime = 0;
	update();
}
/* Start beeping at a given frequency, for an specific duration. */
void EasyBuzzerClass::singleBeep(unsigned int frequency, unsigned int duration)
{
	beep(frequency, duration, mOffDuration, 1, mPauseDuration, 1, NULL);
}
/* Start beeping at a given frequency, for an specific duration, with callback functionality. */
void EasyBuzzerClass::singleBeep(unsigned int frequency, unsigned int duration, void (*finishedCallbackFunction)())
{
	beep(frequency, duration, mOffDuration, 1, mPauseDuration, 1, finishedCallbackFunction);
}
/* Stop beeping. */
void EasyBuzzerClass::stopBeep()
{
#if defined ESP32
	ledcDetachPin(mPin);
	pinMode(mPin, INPUT);
#else
	noTone(mPin);
#endif
}
/* Set the pin where the buzzer is connected. */
void EasyBuzzerClass::setPin(unsigned int pin)
{
	mPin = pin;
}
/* Set On duration. */
void EasyBuzzerClass::setOnDuration(unsigned int duration)
{
	mOnDuration = duration;
}
/* Set Off duration. */
void EasyBuzzerClass::setOffDuration(unsigned int duration)
{
	mOffDuration = duration;
}
/* Set Pause duration. */
void EasyBuzzerClass::setPauseDuration(unsigned int duration)
{
	mPauseDuration = duration;
}
/* Update function that keeps the library running. */
void EasyBuzzerClass::update()
{
	unsigned long currentTime = millis();
	if (currentTime - mLastRunTime < MINIMUM_INTERVAL)
	{
		return;
	}
	mLastRunTime = currentTime;
	if (!mStartTime || !mPin)
	{
		return;
	}

	unsigned long elapsedTime = currentTime - mStartTime;
	unsigned int blinkDuration = mOnDuration + mOffDuration;
	unsigned int sequenceDuration = blinkDuration * mBeeps + mPauseDuration - mOffDuration;

	if (!sequenceDuration || (mSequences != 0 && elapsedTime / sequenceDuration >= mSequences))
	{
		mStartTime = 0;
		if (mFinishedCallbackFunction)
		{
			mFinishedCallbackFunction();
		}
		return;
	};

	unsigned int blinkingDuration = blinkDuration * mBeeps;
	unsigned int timeInSequence = elapsedTime % sequenceDuration;

#if defined ESP32
	if (timeInSequence < blinkingDuration && timeInSequence % blinkDuration < mOnDuration)
	{
		ledcAttachPin(mPin, mChannel);
		ledcWriteTone(mChannel, mFreq);
	}
	else
	{
		ledcDetachPin(mPin);
	};
#else
	if (timeInSequence < blinkingDuration && timeInSequence % blinkDuration < mOnDuration)
	{
		tone(mPin, mFreq);
	}
	else
	{
		noTone(mPin);
	};
#endif
}

EasyBuzzerClass EasyBuzzer;
<|endoftext|>


<commit_before>#include <vector>
#include "Drone.h"

#include "streaming.h"

int main(){

    cv::Point3d wishedPosition(0, -20, 700);

    Drone d;

    assert(d.isValid());

    assert(d.connect());

    while(!d.isRunning()){
        sleep(1);
    }

    std::cout << "EVERYTHING IS OK" << std::endl;

/*
    assert(d.takeOff());

    sleep(5);

    assert(d.modifyPitch(15));
    sleep(2);

    assert(d.modifyPitch(0));
    sleep(5);

    assert(d.land());
*/

    assert(d.startStreamingME());

/*
    initStream();
*/

    cv::VideoCapture cap(d.getVideoPath());
    while(!cap.isOpened()){
        cap = cv::VideoCapture(d.getVideoPath());
    }

    /**
     * UGLY CP FROM CPOS                            **********************************
     */

    cv::FileStorage fs("calib_bd2.xml", cv::FileStorage::READ);

    if(!fs.isOpened()){
        std::cout << "Can't open calibration file!" << std::endl;
        exit(1);
    }

    cv::Mat camMatrix, distCoeff;
    float square_size;

    fs["camera_matrix"] >> camMatrix;
    fs["distortion_coefficients"] >> distCoeff;
    fs["square_size"] >> square_size;
    fs.release();

    std::cout << camMatrix << std::endl << std::endl;
    std::cout << distCoeff << std::endl << std::endl;
    std::cout << square_size << std::endl << std::endl;

    int chess_x = 9;
    int chess_y = 6;
    int ref_pt = 22;

    /**
     * Chess board pts
     */

    cv::Mat model_pts = cv::Mat::zeros(chess_x * chess_y, 3, CV_32FC1);

    int i = 0;
    for(int y = -(ref_pt/chess_x); y < chess_y - (ref_pt/chess_x); ++y){
        for(int x = -(ref_pt%chess_x); x < chess_x - ref_pt%chess_x; ++x){
            model_pts.at<float>(i, 0) = x;
            model_pts.at<float>(i, 1) = y;
            ++i;
        }
    }

    std::cout << model_pts << std::endl;
    /*
    std::vector<cv::Point3d> model_pts;
    for(int x = -(ref_pt%chess_x); x < chess_x - ref_pt%chess_x; ++x){
        for(int y = -(ref_pt/chess_x); y < chess_y - (ref_pt/chess_x); ++y){
            model_pts.push_back(cv::Point3d(x, y, 0.));
        }
    }+
    */
    /**
     * Axis
     */
    std::vector<cv::Point3d> axis;
    axis.push_back(cv::Point3d(3, 0, 0));
    axis.push_back(cv::Point3d(0, 3, 0));
    axis.push_back(cv::Point3d(0, 0, -3));

    bool first_time = true;
    cv::Mat rvec, tvec;
    /**
     *                                              **********************************
     */
    cv::Point3d distFromWished(0,0,0);
    cv::Point3d dist(0,0,0);

    cv::Mat tmp;
    cv::Mat frame;
    while(true)
    {
        cap >> tmp;
        if(tmp.data != NULL) {
            // last image only
            while (1) {
                if(tmp.data != NULL) {
                    tmp.copyTo(frame);
                }else{
                    break;
                }
                cap >> tmp;
            }
            /**
             * UGLY CP FROM CPOS AGAIN *********************************************************************************
             */
            std::vector<cv::Point2d> corners;
            bool chess_board = cv::findChessboardCorners(frame, cv::Size(chess_x, chess_y), corners);
            //cv::cornerSubPix(frame, corners, cv::Size(11,11), cv::Size(-1,-1), cv::TermCriteria)
            if(chess_board) {
                for(int i = 0; i < corners.size(); ++i){
                    cv::circle(frame, corners[i], 5, cv::Scalar(0, 0, 255));
                }
                cv::circle(frame, corners[ref_pt], 10, cv::Scalar(0, 255, 0));

                cv::solvePnP(model_pts, corners, camMatrix, distCoeff, rvec, tvec, !first_time);

                cv::Mat rotM;
                std::vector<cv::Point2d> imgPts;
                cv::projectPoints(axis, rvec, tvec, camMatrix, distCoeff, imgPts);

                cv::line(frame, corners[ref_pt], imgPts[0], cv::Scalar(255, 0, 0), 5);
                cv::line(frame, corners[ref_pt], imgPts[1], cv::Scalar(0, 255, 0), 5);
                cv::line(frame, corners[ref_pt], imgPts[2], cv::Scalar(0, 0, 255), 5);

                cv::Rodrigues(rvec, rotM);

                cv::Mat camPos = rotM.t() * tvec;
                camPos *= square_size;
                dist.x = -camPos.at<double>(0,0);
                dist.y = camPos.at<double>(1,0);
                dist.z = camPos.at<double>(2,0);

                distFromWished = dist - wishedPosition;

                cv::putText(frame, "Dist from chessboard", cv::Point(10,30), cv::QT_FONT_NORMAL, 1, cv::Scalar(0,0,0), 2, 8);
                cv::putText(frame, std::to_string((int)dist.x), cv::Point(10,80), cv::QT_FONT_NORMAL, 1, cv::Scalar(255,0,0), 2, 8);
                cv::putText(frame, std::to_string((int)dist.y), cv::Point(10,130), cv::QT_FONT_NORMAL, 1, cv::Scalar(0,255,0), 2, 8);
                cv::putText(frame, std::to_string((int)dist.z), cv::Point(10,180), cv::QT_FONT_NORMAL, 1, cv::Scalar(0,0,255), 2, 8);

                cv::putText(frame, "Dist from wished", cv::Point(10,230), cv::QT_FONT_NORMAL, 1, cv::Scalar(0,0,0), 2, 8);
                cv::putText(frame, std::to_string((int)distFromWished.x), cv::Point(10,280), cv::QT_FONT_NORMAL, 1, cv::Scalar(255,0,0), 2, 8);
                cv::putText(frame, std::to_string((int)distFromWished.y), cv::Point(10,330), cv::QT_FONT_NORMAL, 1, cv::Scalar(0,255,0), 2, 8);
                cv::putText(frame, std::to_string((int)distFromWished.z), cv::Point(10,380), cv::QT_FONT_NORMAL, 1, cv::Scalar(0,0,255), 2, 8);

                cv::putText(frame, std::to_string(d.getBatteryLvl()), cv::Point(800,30), cv::FONT_HERSHEY_SCRIPT_SIMPLEX, 1, cv::Scalar(255,0,255), 3, 8);

                int askedRoll = ((int)distFromWished.x/10);
                int askedPitch = ((int)distFromWished.z/10);
                int askedAlt = ((int)distFromWished.y/10);

                cv::putText(frame, "Asked roll", cv::Point(100,280), cv::QT_FONT_NORMAL, 1, cv::Scalar(0,0,0), 2, 8);
                cv::putText(frame, "Asked altit", cv::Point(100,330), cv::QT_FONT_NORMAL, 1, cv::Scalar(0,0,0), 2, 8);
                cv::putText(frame, "Asked pitch", cv::Point(100,380), cv::QT_FONT_NORMAL, 1, cv::Scalar(0,0,0), 2, 8);

                cv::putText(frame, std::to_string(askedRoll), cv::Point(300,280), cv::QT_FONT_NORMAL, 1, cv::Scalar(255,0,0), 2, 8);
                cv::putText(frame, std::to_string(askedAlt), cv::Point(300,330), cv::QT_FONT_NORMAL, 1, cv::Scalar(0,255,0), 2, 8);
                cv::putText(frame, std::to_string(askedPitch), cv::Point(300,380), cv::QT_FONT_NORMAL, 1, cv::Scalar(0,0,255), 2, 8);

                first_time = false;
            }else{
                cv::putText(frame, "STOP EVERYTHIG, NO CHESSBOARD !", cv::Point(10,300), cv::QT_FONT_NORMAL, 1, cv::Scalar(0,0,255), 3, 8);
                first_time = true;
            }
            /**
             * *********************************************************************************************************
             */
            cv::imshow("frame", frame);
        }
        char k = (char)cv::waitKey(10);
        if(k == 'l') {
            break;
        }if(k == 'q') {
            d.emergency();
            break;
        }
    }

    d.land();

    return 0;
}<commit_msg>using uint8_t instead of int<commit_after>#include <vector>
#include "Drone.h"

#include "streaming.h"

int main(){

    cv::Point3d wishedPosition(0, -20, 700);

    Drone d;

    assert(d.isValid());

    assert(d.connect());

    while(!d.isRunning()){
        sleep(1);
    }

    std::cout << "EVERYTHING IS OK" << std::endl;

    //d.takeOff();
/*
    assert(d.takeOff());

    sleep(5);

    assert(d.modifyPitch(15));
    sleep(2);

    assert(d.modifyPitch(0));
    sleep(5);

    assert(d.land());
*/

    assert(d.startStreamingME());

/*
    initStream();
*/

    cv::VideoCapture cap(d.getVideoPath());
    while(!cap.isOpened()){
        cap = cv::VideoCapture(d.getVideoPath());
    }

    /**
     * UGLY CP FROM CPOS                            **********************************
     */

    cv::FileStorage fs("calib_bd2.xml", cv::FileStorage::READ);

    if(!fs.isOpened()){
        std::cout << "Can't open calibration file!" << std::endl;
        exit(1);
    }

    cv::Mat camMatrix, distCoeff;
    float square_size;

    fs["camera_matrix"] >> camMatrix;
    fs["distortion_coefficients"] >> distCoeff;
    fs["square_size"] >> square_size;
    fs.release();

    std::cout << camMatrix << std::endl << std::endl;
    std::cout << distCoeff << std::endl << std::endl;
    std::cout << square_size << std::endl << std::endl;

    int chess_x = 9;
    int chess_y = 6;
    int ref_pt = 22;

    /**
     * Chess board pts
     */

    cv::Mat model_pts = cv::Mat::zeros(chess_x * chess_y, 3, CV_32FC1);

    int i = 0;
    for(int y = -(ref_pt/chess_x); y < chess_y - (ref_pt/chess_x); ++y){
        for(int x = -(ref_pt%chess_x); x < chess_x - ref_pt%chess_x; ++x){
            model_pts.at<float>(i, 0) = x;
            model_pts.at<float>(i, 1) = y;
            ++i;
        }
    }

    std::cout << model_pts << std::endl;
    /*
    std::vector<cv::Point3d> model_pts;
    for(int x = -(ref_pt%chess_x); x < chess_x - ref_pt%chess_x; ++x){
        for(int y = -(ref_pt/chess_x); y < chess_y - (ref_pt/chess_x); ++y){
            model_pts.push_back(cv::Point3d(x, y, 0.));
        }
    }+
    */
    /**
     * Axis
     */
    std::vector<cv::Point3d> axis;
    axis.push_back(cv::Point3d(3, 0, 0));
    axis.push_back(cv::Point3d(0, 3, 0));
    axis.push_back(cv::Point3d(0, 0, -3));

    bool first_time = true;
    cv::Mat rvec, tvec;
    /**
     *                                              **********************************
     */
    cv::Point3d distFromWished(0,0,0);
    cv::Point3d dist(0,0,0);

    cv::Mat tmp;
    cv::Mat frame;
    while(true)
    {
        cap >> tmp;
        if(tmp.data != NULL) {
            // last image only
            while (1) {
                if(tmp.data != NULL) {
                    tmp.copyTo(frame);
                }else{
                    break;
                }
                cap >> tmp;
            }
            /**
             * UGLY CP FROM CPOS AGAIN *********************************************************************************
             */
            std::vector<cv::Point2d> corners;
            bool chess_board = cv::findChessboardCorners(frame, cv::Size(chess_x, chess_y), corners);
            //cv::cornerSubPix(frame, corners, cv::Size(11,11), cv::Size(-1,-1), cv::TermCriteria)
            if(chess_board) {
                for(int i = 0; i < corners.size(); ++i){
                    cv::circle(frame, corners[i], 5, cv::Scalar(0, 0, 255));
                }
                cv::circle(frame, corners[ref_pt], 10, cv::Scalar(0, 255, 0));

                cv::solvePnP(model_pts, corners, camMatrix, distCoeff, rvec, tvec, !first_time);

                cv::Mat rotM;
                std::vector<cv::Point2d> imgPts;
                cv::projectPoints(axis, rvec, tvec, camMatrix, distCoeff, imgPts);

                cv::line(frame, corners[ref_pt], imgPts[0], cv::Scalar(255, 0, 0), 5);
                cv::line(frame, corners[ref_pt], imgPts[1], cv::Scalar(0, 255, 0), 5);
                cv::line(frame, corners[ref_pt], imgPts[2], cv::Scalar(0, 0, 255), 5);

                cv::Rodrigues(rvec, rotM);

                cv::Mat camPos = rotM.t() * tvec;
                camPos *= square_size;
                dist.x = -camPos.at<double>(0,0);
                dist.y = camPos.at<double>(1,0);
                dist.z = camPos.at<double>(2,0);

                distFromWished = dist - wishedPosition;

                cv::putText(frame, "Dist from chessboard", cv::Point(10,30), cv::QT_FONT_NORMAL, 1, cv::Scalar(0,0,0), 2, 8);
                cv::putText(frame, std::to_string((int)dist.x), cv::Point(10,80), cv::QT_FONT_NORMAL, 1, cv::Scalar(255,0,0), 2, 8);
                cv::putText(frame, std::to_string((int)dist.y), cv::Point(10,130), cv::QT_FONT_NORMAL, 1, cv::Scalar(0,255,0), 2, 8);
                cv::putText(frame, std::to_string((int)dist.z), cv::Point(10,180), cv::QT_FONT_NORMAL, 1, cv::Scalar(0,0,255), 2, 8);

                cv::putText(frame, "Dist from wished", cv::Point(10,230), cv::QT_FONT_NORMAL, 1, cv::Scalar(0,0,0), 2, 8);
                cv::putText(frame, std::to_string((int)distFromWished.x), cv::Point(10,280), cv::QT_FONT_NORMAL, 1, cv::Scalar(255,0,0), 2, 8);
                cv::putText(frame, std::to_string((int)distFromWished.y), cv::Point(10,330), cv::QT_FONT_NORMAL, 1, cv::Scalar(0,255,0), 2, 8);
                cv::putText(frame, std::to_string((int)distFromWished.z), cv::Point(10,380), cv::QT_FONT_NORMAL, 1, cv::Scalar(0,0,255), 2, 8);

                cv::putText(frame, std::to_string(d.getBatteryLvl()), cv::Point(800,30), cv::FONT_HERSHEY_SCRIPT_SIMPLEX, 1, cv::Scalar(255,0,255), 3, 8);

                int8_t askedRoll = (int8_t)((int)distFromWished.x/10);
                int8_t askedPitch = (int8_t)((int)distFromWished.z/10);
                int8_t askedAlt = (int8_t)((int)distFromWished.y/10);

                cv::putText(frame, "Asked roll", cv::Point(100,280), cv::QT_FONT_NORMAL, 1, cv::Scalar(0,0,0), 2, 8);
                cv::putText(frame, "Asked altit", cv::Point(100,330), cv::QT_FONT_NORMAL, 1, cv::Scalar(0,0,0), 2, 8);
                cv::putText(frame, "Asked pitch", cv::Point(100,380), cv::QT_FONT_NORMAL, 1, cv::Scalar(0,0,0), 2, 8);

                cv::putText(frame, std::to_string(askedRoll), cv::Point(300,280), cv::QT_FONT_NORMAL, 1, cv::Scalar(255,0,0), 2, 8);
                cv::putText(frame, std::to_string(askedAlt), cv::Point(300,330), cv::QT_FONT_NORMAL, 1, cv::Scalar(0,255,0), 2, 8);
                cv::putText(frame, std::to_string(askedPitch), cv::Point(300,380), cv::QT_FONT_NORMAL, 1, cv::Scalar(0,0,255), 2, 8);

                //d.modifyRoll(askedRoll);
                //d.modifyAltitude(askedAlt);
                //d.modifyPitch(askedPitch);

                first_time = false;
            }else{
                cv::putText(frame, "STOP EVERYTHIG, NO CHESSBOARD !", cv::Point(10,300), cv::QT_FONT_NORMAL, 1, cv::Scalar(0,0,255), 3, 8);
                first_time = true;
            }
            /**
             * *********************************************************************************************************
             */
            cv::imshow("frame", frame);
        }
        char k = (char)cv::waitKey(10);
        if(k == 'l') {
            break;
        }if(k == 'q') {
            d.emergency();
            break;
        }
    }

    d.land();

    return 0;
}<|endoftext|>


<commit_before>/*
 * FileSystem.cpp
 *
 *  Created on: Jun 20, 2014
 *      Author: Pimenta
 */

// this
#include "FileSystem.hpp"

// standard
#include <cstdlib>
#include <set>

using namespace std;
using namespace helpers;

FileSystem::Folder FileSystem::rootFolder;
uint32_t FileSystem::localIP;

uint32_t FileSystem::Folder::getTotalFiles() {
  uint32_t total = 0;
  for (auto& kv : subfolders)
    total += kv.second.getTotalFiles();
  return total + files.size();
}

uint64_t FileSystem::Folder::getTotalSize() {
  int total = 0;
  for (auto& kv : subfolders)
    total += kv.second.getTotalSize();
  for (auto& kv : files)
    total += kv.second.size;
  return total;
}

FileSystem::Folder* FileSystem::Folder::findFolder(const string& subPath, Folder** parent) {
  if (!parsePath(subPath)) { // if the path is invalid
    if (parent) // if the parent folder was requested
      *parent = nullptr;
    return nullptr;
  }
  return findFolder_(subPath, parent);
}

FileSystem::File* FileSystem::Folder::findFile(const string& subPath, Folder** parent) {
  if (!parsePath(subPath)) { // if the path is invalid
    if (parent) // if the parent folder was requested
      *parent = nullptr;
    return nullptr;
  }
  return findFile_(subPath, parent);
}

FileSystem::Folder* FileSystem::Folder::findFolder_(const string& subPath, Folder** parent) {
  pair<string, string> brokenPath = extractFirst(subPath, '/');
  if (brokenPath.second == "") { // if subPath is a folder name
    if (parent) // if the parent folder was requested
      *parent = this;
    auto folder = subfolders.find(brokenPath.first);
    if (folder == subfolders.end()) // if the folder was not found
      return nullptr;
    return &folder->second;
  }
  auto parentFolder = subfolders.find(brokenPath.first);
  if (parentFolder == subfolders.end()) { // if a parent folder was not found
    if (parent) // if the parent folder was requested
      *parent = nullptr;
    return nullptr;
  }
  return parentFolder->second.findFolder_(brokenPath.second, parent); // recursive call
}

FileSystem::File* FileSystem::Folder::findFile_(const string& subPath, Folder** parent) {
  pair<string, string> brokenPath = extractFirst(subPath, '/');
  if (brokenPath.second == "") { // if supPath is a file name
    if (parent) // if the parent folder was requested
      *parent = this;
    auto file = files.find(brokenPath.first);
    if (file == files.end()) // if the file was not found
      return nullptr;
    return &file->second;
  }
  auto parentFolder = subfolders.find(brokenPath.first);
  if (parentFolder == subfolders.end()) { // if a parent folder was not found
    if (parent) // if the parent folder was requested
      *parent = nullptr;
    return nullptr;
  }
  return parentFolder->second.findFile_(brokenPath.second, parent); // recursive call
}

void FileSystem::init(uint32_t localIP) {
  rootFolder.subfolders.clear();
  rootFolder.files.clear();
  system("rm -rf www/files/*");
  FileSystem::localIP = localIP;
}

bool FileSystem::parseName(const string& name) {
  static set<char> allowedChars;
  static StaticInitializer staticInitializar([&]() {
    for (char c = '0'; c <= '9'; c++)
      allowedChars.insert(c);
    for (char c = 'a'; c <= 'z'; c++)
      allowedChars.insert(c);
    for (char c = 'A'; c <= 'Z'; c++)
      allowedChars.insert(c);
    allowedChars.insert('_');
    allowedChars.insert('-');
    allowedChars.insert('+');
    allowedChars.insert('.');
  });
  if (!name.size()) // if the name is empty
    return false;
  for (int i = 0; i < int(name.size()); i++) { // check if all chars are allowed
    if (allowedChars.find(name[i]) != allowedChars.end())
      return false;
  }
  return true;
}

bool FileSystem::parsePath(const string& path) {
  if (!path.size()) // if the path is empty
    return false;
  list<string> atoms = explode(path, '/');
  string reassembledPath;
  for (auto& folder : atoms) { // reassemble the exploded path
    if (!parseName(folder)) // if there is an invalid folder name
      return false;
    reassembledPath += '/';
    reassembledPath += folder;
  }
  return reassembledPath == path;
}

FileSystem::Folder* FileSystem::createFolder(const string& fullPath) {
  Folder* parent;
  Folder* folder = rootFolder.findFolder(fullPath, &parent);
  if (!parent || folder) // if parent folder was not found or the folder exist
    return nullptr;
  pair<string, string> brokenPath = extractLast(fullPath, '/');
  return &parent->subfolders[brokenPath.second];
}

FileSystem::Folder* FileSystem::retrieveFolder(const string& fullPath) {
  if (fullPath == "/")
    return &rootFolder;
  return rootFolder.findFolder(fullPath);
}

FileSystem::Folder* FileSystem::updateFolder(const string& fullPath, const string& newName) {
  if (!parseName(newName)) // if the new name is invalid
    return nullptr;
  Folder* parent;
  Folder* folder = rootFolder.findFolder(fullPath, &parent);
  if (!parent || !folder) // if parent or folder doesn't exist
    return nullptr;
  pair<string, string> brokenPath = extractLast(fullPath, '/');
  string newNameWithSlash = string("/") + newName;
  // if the new folder already exist
  if (parent->subfolders.find(newNameWithSlash) != parent->subfolders.end())
    return nullptr;
  Folder* newFolder = &parent->subfolders[newNameWithSlash];
  newFolder->subfolders = folder->subfolders;
  newFolder->files = folder->files;
  parent->subfolders.erase(brokenPath.second);
  //TODO rename files in this peer
  return newFolder;
}

bool FileSystem::deleteFolder(const string& fullPath) {
  Folder* parent;
  Folder* folder = rootFolder.findFolder(fullPath, &parent);
  if (!parent || !folder) // if parent of folder doesn't exist
    return false;
  pair<string, string> brokenPath = extractLast(fullPath, '/');
  parent->subfolders.erase(brokenPath.second);
  //TODO remove files in this peer
  return false;
}

FileSystem::File* FileSystem::createFile(const string& fullPath, const ByteQueue& byteQueue) {
  return nullptr;//TODO
}

FileSystem::File* FileSystem::retrieveFile(const string& fullPath) {
  return rootFolder.findFile(fullPath);
}

FileSystem::File* FileSystem::updateFile(const string& fullPath, const string& newName) {
  return nullptr;//TODO
}

bool FileSystem::deleteFile(const string& fullPath) {
  return false;//TODO
}

uint32_t FileSystem::getTotalFiles() {
  return rootFolder.getTotalFiles();
}

uint64_t FileSystem::getTotalSize() {
  return rootFolder.getTotalSize();
}

ByteQueue FileSystem::readFile(FILE* fp) {
  fseek(fp, 0, SEEK_END);
  size_t size = ftell(fp);
  fseek(fp, 0, SEEK_SET);
  ByteQueue data(size);
  fread(data.ptr(), size, 1, fp);
  return data;
}
<commit_msg>Adding file CRUD methods<commit_after>/*
 * FileSystem.cpp
 *
 *  Created on: Jun 20, 2014
 *      Author: Pimenta
 */

// this
#include "FileSystem.hpp"

// standard
#include <cstdlib>
#include <set>

using namespace std;
using namespace helpers;

FileSystem::Folder FileSystem::rootFolder;
uint32_t FileSystem::localIP;

uint32_t FileSystem::Folder::getTotalFiles() {
  uint32_t total = 0;
  for (auto& kv : subfolders)
    total += kv.second.getTotalFiles();
  return total + files.size();
}

uint64_t FileSystem::Folder::getTotalSize() {
  int total = 0;
  for (auto& kv : subfolders)
    total += kv.second.getTotalSize();
  for (auto& kv : files)
    total += kv.second.size;
  return total;
}

FileSystem::Folder* FileSystem::Folder::findFolder(const string& subPath, Folder** parent) {
  if (!parsePath(subPath)) { // if the path is invalid
    if (parent) // if the parent folder was requested
      *parent = nullptr;
    return nullptr;
  }
  return findFolder_(subPath, parent);
}

FileSystem::File* FileSystem::Folder::findFile(const string& subPath, Folder** parent) {
  if (!parsePath(subPath)) { // if the path is invalid
    if (parent) // if the parent folder was requested
      *parent = nullptr;
    return nullptr;
  }
  return findFile_(subPath, parent);
}

FileSystem::Folder* FileSystem::Folder::findFolder_(const string& subPath, Folder** parent) {
  pair<string, string> brokenPath = extractFirst(subPath, '/');
  if (brokenPath.second == "") { // if subPath is a folder name
    if (parent) // if the parent folder was requested
      *parent = this;
    auto folder = subfolders.find(brokenPath.first);
    if (folder == subfolders.end()) // if the folder was not found
      return nullptr;
    return &folder->second;
  }
  auto parentFolder = subfolders.find(brokenPath.first);
  if (parentFolder == subfolders.end()) { // if a parent folder was not found
    if (parent) // if the parent folder was requested
      *parent = nullptr;
    return nullptr;
  }
  return parentFolder->second.findFolder_(brokenPath.second, parent); // recursive call
}

FileSystem::File* FileSystem::Folder::findFile_(const string& subPath, Folder** parent) {
  pair<string, string> brokenPath = extractFirst(subPath, '/');
  if (brokenPath.second == "") { // if supPath is a file name
    if (parent) // if the parent folder was requested
      *parent = this;
    auto file = files.find(brokenPath.first);
    if (file == files.end()) // if the file was not found
      return nullptr;
    return &file->second;
  }
  auto parentFolder = subfolders.find(brokenPath.first);
  if (parentFolder == subfolders.end()) { // if a parent folder was not found
    if (parent) // if the parent folder was requested
      *parent = nullptr;
    return nullptr;
  }
  return parentFolder->second.findFile_(brokenPath.second, parent); // recursive call
}

void FileSystem::init(uint32_t localIP) {
  rootFolder.subfolders.clear();
  rootFolder.files.clear();
  system("rm -rf www/files/*");
  FileSystem::localIP = localIP;
}

bool FileSystem::parseName(const string& name) {
  static set<char> allowedChars;
  static StaticInitializer staticInitializar([&]() {
    for (char c = '0'; c <= '9'; c++)
      allowedChars.insert(c);
    for (char c = 'a'; c <= 'z'; c++)
      allowedChars.insert(c);
    for (char c = 'A'; c <= 'Z'; c++)
      allowedChars.insert(c);
    allowedChars.insert('_');
    allowedChars.insert('-');
    allowedChars.insert('+');
    allowedChars.insert('.');
  });
  if (!name.size()) // if the name is empty
    return false;
  for (int i = 0; i < int(name.size()); i++) { // check if all chars are allowed
    if (allowedChars.find(name[i]) != allowedChars.end())
      return false;
  }
  return true;
}

bool FileSystem::parsePath(const string& path) {
  if (!path.size()) // if the path is empty
    return false;
  list<string> atoms = explode(path, '/');
  string reassembledPath;
  for (auto& folder : atoms) { // reassemble the exploded path
    if (!parseName(folder)) // if there is an invalid folder name
      return false;
    reassembledPath += '/';
    reassembledPath += folder;
  }
  return reassembledPath == path;
}

FileSystem::Folder* FileSystem::createFolder(const string& fullPath) {
  Folder* parent;
  Folder* folder = rootFolder.findFolder(fullPath, &parent);
  if (!parent || folder) // if parent folder was not found or the folder exist
    return nullptr;
  pair<string, string> brokenPath = extractLast(fullPath, '/');
  return &parent->subfolders[brokenPath.second];
}

FileSystem::Folder* FileSystem::retrieveFolder(const string& fullPath) {
  if (fullPath == "/")
    return &rootFolder;
  return rootFolder.findFolder(fullPath);
}

FileSystem::Folder* FileSystem::updateFolder(const string& fullPath, const string& newName) {
  if (!parseName(newName)) // if the new name is invalid
    return nullptr;
  Folder* parent;
  Folder* folder = rootFolder.findFolder(fullPath, &parent);
  if (!parent || !folder) // if parent or folder doesn't exist
    return nullptr;
  string newNameWithSlash = string("/") + newName;
  // if the new folder already exist
  if (parent->subfolders.find(newNameWithSlash) != parent->subfolders.end())
    return nullptr;
  Folder* newFolder = &parent->subfolders[newNameWithSlash];
  newFolder->subfolders = folder->subfolders;
  newFolder->files = folder->files;
  pair<string, string> brokenPath = extractLast(fullPath, '/');
  parent->subfolders.erase(brokenPath.second);
  //TODO rename files in this peer
  return newFolder;
}

bool FileSystem::deleteFolder(const string& fullPath) {
  Folder* parent;
  Folder* folder = rootFolder.findFolder(fullPath, &parent);
  if (!parent || !folder) // if parent of folder doesn't exist
    return false;
  pair<string, string> brokenPath = extractLast(fullPath, '/');
  parent->subfolders.erase(brokenPath.second);
  //TODO remove files in this peer
  return false;
}

FileSystem::File* FileSystem::createFile(const string& fullPath, const ByteQueue& byteQueue) {
  return nullptr;//TODO
}

FileSystem::File* FileSystem::retrieveFile(const string& fullPath) {
  return rootFolder.findFile(fullPath);
}

FileSystem::File* FileSystem::updateFile(const string& fullPath, const string& newName) {
  return nullptr;//TODO
}

bool FileSystem::deleteFile(const string& fullPath) {
  return false;//TODO
}

uint32_t FileSystem::getTotalFiles() {
  return rootFolder.getTotalFiles();
}

uint64_t FileSystem::getTotalSize() {
  return rootFolder.getTotalSize();
}

ByteQueue FileSystem::readFile(FILE* fp) {
  fseek(fp, 0, SEEK_END);
  size_t size = ftell(fp);
  fseek(fp, 0, SEEK_SET);
  ByteQueue data(size);
  fread(data.ptr(), size, 1, fp);
  return data;
}
<|endoftext|>


<commit_before>/*
 * FileSystem.cpp
 *
 *  Created on: Jun 20, 2014
 *      Author: Pimenta
 */

// this
#include "FileSystem.hpp"

using namespace std;
using namespace helpers;

map<string, FileSystem::Folder> FileSystem::folders;

void FileSystem::init() {
  folders.clear();
}

bool FileSystem::createFolder(const string& fullPath) {
  //TODO
  return false;
}

FileSystem::Folder* FileSystem::retrieveFolder(const string& fullPath) {
  if (folders.find(fullPath) == folders.end())
    return nullptr;
  return &folders[fullPath];
}

bool FileSystem::updateFolder(const string& fullPath, const string& newPath) {
  //TODO
  return false;
}

bool FileSystem::deleteFolder(const string& fullPath) {
  //TODO
  return false;
}

FileSystem::File* FileSystem::retrieveFile(const string& fullPath) {//FIXME
  int i;
  for (i = fullPath.size() - 1; i >= 0 && fullPath[i] != '/'; i--);
  return &folders[fullPath.substr(0, i)].files[fullPath.substr(i + 1, fullPath.size())];
}

int FileSystem::getTotalFiles() {
  int total = 0;
  for (auto& kv : folders)
    total += kv.second.files.size();
  return total;
}

int FileSystem::getTotalSize() {
  int total = 0;
  for (auto& kv1 : folders) {
    for (auto& kv2 : kv1.second.files)
      total += kv2.second.size;
  }
  return total;
}

ByteQueue FileSystem::readFile(FILE* fp) {
  fseek(fp, 0, SEEK_END);
  size_t size = ftell(fp);
  fseek(fp, 0, SEEK_SET);
  ByteQueue data(size);
  fread(data.ptr(), size, 1, fp);
  return data;
}
<commit_msg>Fixing bug<commit_after>/*
 * FileSystem.cpp
 *
 *  Created on: Jun 20, 2014
 *      Author: Pimenta
 */

// this
#include "FileSystem.hpp"

using namespace std;
using namespace helpers;

map<string, FileSystem::Folder> FileSystem::folders;

void FileSystem::init() {
  folders.clear();
}

bool FileSystem::createFolder(const string& fullPath) {
  //TODO
  return false;
}

FileSystem::Folder* FileSystem::retrieveFolder(const string& fullPath) {
  auto folder = folders.find(fullPath);
  if (folder == folders.end())
    return nullptr;
  return &folder->second;
}

bool FileSystem::updateFolder(const string& fullPath, const string& newPath) {
  //TODO
  return false;
}

bool FileSystem::deleteFolder(const string& fullPath) {
  //TODO
  return false;
}

FileSystem::File* FileSystem::retrieveFile(const string& fullPath) {
  int i;
  for (i = fullPath.size() - 1; i >= 0 && fullPath[i] != '/'; i--);
  auto folder = folders.find(fullPath.substr(0, i));
  if (folder == folders.end())
    return nullptr;
  auto& files = folder->second.files;
  auto file = files.find(fullPath.substr(i + 1, fullPath.size()));
  if (file == folder->second.files.end())
    return nullptr;
  return &file->second;
}

int FileSystem::getTotalFiles() {
  int total = 0;
  for (auto& kv : folders)
    total += kv.second.files.size();
  return total;
}

int FileSystem::getTotalSize() {
  int total = 0;
  for (auto& kv1 : folders) {
    for (auto& kv2 : kv1.second.files)
      total += kv2.second.size;
  }
  return total;
}

ByteQueue FileSystem::readFile(FILE* fp) {
  fseek(fp, 0, SEEK_END);
  size_t size = ftell(fp);
  fseek(fp, 0, SEEK_SET);
  ByteQueue data(size);
  fread(data.ptr(), size, 1, fp);
  return data;
}
<|endoftext|>


<commit_before>#include "GameWindow.hpp"

#include <sstream>

#include <al.h>
#include <glm/detail/setup.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>

#include "Game.hpp"
#include "GlobalProperties.hpp"
#include "GLFWHandler.hpp"
#include "GameState.hpp"
#include "MessageState.hpp"
#include "Audio.hpp"

namespace Diggler {

int GameWindow::InstanceCount = 0;

static void glfwErrorCallback(int error, const char *description) {
  getErrorStream() << "GLFW Error " << error << ": " << description << std::endl;
}

#ifdef DEBUG
static void APIENTRY glDebugCallback(GLenum source, GLenum type, GLuint id,
  GLenum severity, GLsizei length, const GLchar *message, const void *userParam) {
  const char *sourceStr = "???";
  switch (source) {
    case GL_DEBUG_SOURCE_API:
      sourceStr = "API";
      break;
    case GL_DEBUG_SOURCE_WINDOW_SYSTEM:
      sourceStr = "WIN";
      break;
    case GL_DEBUG_SOURCE_SHADER_COMPILER:
      sourceStr = "SHC";
      break;
    case GL_DEBUG_SOURCE_THIRD_PARTY:
      sourceStr = "3PT";
      break;
    case GL_DEBUG_SOURCE_APPLICATION:
      sourceStr = "APP";
      break;
    case GL_DEBUG_SOURCE_OTHER:
      sourceStr = "OTH";
      break;
  }
  const char *typeStr = "???";
  switch (type) {
    case GL_DEBUG_TYPE_ERROR:
      typeStr = "ERR";
      break;
    case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
      typeStr = "DEP";
      break;
    case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
      typeStr = "UND";
      break;
    case GL_DEBUG_TYPE_PORTABILITY:
      typeStr = "PRT";
      break;
    case GL_DEBUG_TYPE_PERFORMANCE:
      typeStr = "PRF";
      break;
    case GL_DEBUG_TYPE_MARKER:
      typeStr = "MKR";
      break;
    case GL_DEBUG_TYPE_PUSH_GROUP:
      typeStr = "GP+";
      break;
    case GL_DEBUG_TYPE_POP_GROUP:
      typeStr = "GP-";
      break;
    case GL_DEBUG_TYPE_OTHER:
      typeStr = "OTH";
      break;
  }
  const char *severityStr = "??";
  switch (severity) {
  case GL_DEBUG_SEVERITY_HIGH:
    severityStr = "HI";
    break;
  case GL_DEBUG_SEVERITY_MEDIUM:
    severityStr = "MD";
    break;
  case GL_DEBUG_SEVERITY_LOW:
    severityStr = "LO";
    break;
  case GL_DEBUG_SEVERITY_NOTIFICATION:
    severityStr = "NT";
    break;
  }
  char line[3 + 1 + 3 + 1 + 2 + 2 + 1];
  std::snprintf(line, sizeof(line)/sizeof(line[0]), "%3s %3s %2s] ", sourceStr, typeStr, severityStr);
  getDebugStreamRaw() << line << message << std::endl;
}
#endif

GameWindow::GameWindow(Game *G) : G(G) {
  if (InstanceCount++ == 0) {
    glfwSetErrorCallback(glfwErrorCallback);
    int glfwStatus = glfwInit();
    if (glfwStatus != GL_TRUE) {
      std::ostringstream err;
      err << "GLFW init failed (" << glfwStatus << ')';
      throw std::runtime_error(err.str());
    }
    getOutputStreamRaw() << "GLFW linked " << GLFW_VERSION_MAJOR << '.' << GLFW_VERSION_MINOR <<
        '.' << GLFW_VERSION_REVISION << ", using " << glfwGetVersionString() << std::endl;
  }

  GLFWHandler::getInstance().setWindow(this, m_window);

  m_w = 640; m_h = 480;

  glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
  glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
  //glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API);
  glfwWindowHint(GLFW_SAMPLES, 0); // Gimme aliasing everywhere
  //glfwWindowHint(GLFW_STENCIL_BITS, 8);

#ifdef DEBUG
  glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GL_TRUE);
#endif

  m_window = glfwCreateWindow(m_w, m_h, "Diggler", nullptr, nullptr);
  if (!m_window) {
    glfwTerminate();
    throw std::runtime_error("GLFW window creation failed");
  }
  glfwMakeContextCurrent(m_window);
#ifdef DEBUG
  glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, nullptr, GL_TRUE);
  glDebugMessageCallback(glDebugCallback, nullptr);
#endif
  glfwSetFramebufferSizeCallback(m_window, GLFWHandler::resize);
  glfwSetCursorPosCallback(m_window, GLFWHandler::cursorPos);
  glfwSetKeyCallback(m_window, GLFWHandler::key);
  glfwSetMouseButtonCallback(m_window, GLFWHandler::mouseButton);
  glfwSetScrollCallback(m_window, GLFWHandler::mouseScroll);
  glfwSetCharCallback(m_window, GLFWHandler::unichar);
  glfwSwapInterval(1);
  /*GLint bits;
  glGetIntegerv(GL_STENCIL_BITS, &bits);
  getDebugStream() << bits << " stencil bits" << std::endl;*/

  getOutputStreamRaw() << "GLM " << GLM_VERSION_MAJOR << '.' << GLM_VERSION_MINOR << '.' << GLM_VERSION_PATCH << ' '
#if GLM_ARCH & GLM_ARCH_AVX512_BIT
  << "AVX512 "
#endif
#if GLM_ARCH & GLM_ARCH_AVX2_BIT
  << "AVX2 "
#endif
#if GLM_ARCH & GLM_ARCH_AVX_BIT
  << "AVX "
#endif
#if GLM_ARCH & GLM_ARCH_SSE42_BIT
 << "SSE42 "
#endif
#if GLM_ARCH & GLM_ARCH_SSE41_BIT
  << "SSE41 "
#endif
#if GLM_ARCH & GLM_ARCH_SSSE3_BIT
 << "SSSE3 "
#endif
#if GLM_ARCH & GLM_ARCH_SSE3_BIT
  << "SSE3 "
#endif
#if GLM_ARCH & GLM_ARCH_SSE2_BIT
  << "SSE2 "
#endif
  ;

  getOutputStreamRaw() << "-- Epoxy GL" << (epoxy_is_desktop_gl() ? "" : "ES") << epoxy_gl_version() << std::endl;

  if (InstanceCount == 1) { // If we're the first instance
    const uint8 *GL_version = glGetString(GL_VERSION);
    //const uint8 *GL_vendor = glGetString(GL_VENDOR);
    const uint8 *GL_renderer = glGetString(GL_RENDERER);
    getOutputStreamRaw() << "GL " << GL_version << " / " << GL_renderer << std::endl;
  }

  UIM = new UI::Manager;
  UIM->onResize(m_w, m_h);

  G->init();
  UIM->setup(G);
  G->GW = this;
  G->UIM = UIM;
  G->A->loadSoundAssets();

  G->FM->loadFont(getAssetPath("04b08.png"), "04b08");
  G->FM->setDefaultFont("04b08");

  glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
  glEnable(GL_BLEND);
  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}

GameWindow::~GameWindow() {
  m_currentState.reset();
  m_nextState.reset();
  delete UIM;

  glfwDestroyWindow(m_window);

  if (--InstanceCount == 0) {
    glfwTerminate();
  }
}

bool GameWindow::shouldClose() const {
  return glfwWindowShouldClose(m_window);
}

void GameWindow::setVisible(bool visible) {
  return visible ? glfwShowWindow(m_window) : glfwHideWindow(m_window);
}

bool GameWindow::isVisible() const {
  return glfwGetWindowAttrib(m_window, GLFW_VISIBLE);
}

void GameWindow::cbChar(char32 unichar) {
  UIM->onChar(unichar);
  m_currentState->onChar(unichar);
}

void GameWindow::cbKey(int key, int scancode, int action, int mods) {
  UIM->onKey(key, scancode, action, mods);
  m_currentState->onKey(key, scancode, action, mods);
}

void GameWindow::cbMouseButton(int key, int action, int mods) {
  UIM->onMouseButton(key, action, mods);
  m_currentState->onMouseButton(key, action, mods);
}

void GameWindow::cbCursorPos(double x, double y) {
  UIM->onCursorPos(x, y);
  m_currentState->onCursorPos(x, y);
}

void GameWindow::cbMouseScroll(double x, double y) {
  UIM->onMouseScroll(x, y);
  m_currentState->onMouseScroll(x, y);
}

void GameWindow::cbResize(int w, int h) {
  m_w = w; m_h = h;
  glViewport(0, 0, w, h);
  UIM->onResize(w, h);
  m_currentState->onResize(w, h);
}

void GameWindow::setNextState(std::unique_ptr<State> &&next) {
  m_nextState = std::move(next);
}

void GameWindow::run() {
  while (m_nextState != nullptr && !glfwWindowShouldClose(m_window)) {
    m_currentState = std::move(m_nextState);
    m_nextState = nullptr;
    UIM->clear();
    m_currentState->run();
  }
}

void GameWindow::showMessage(const std::string &msg, const std::string &submsg) {
  setNextState(std::move(std::make_unique<MessageState>(this, msg, submsg)));
}

}
<commit_msg>Fix shutdown crash (client Game members destructed before State)<commit_after>#include "GameWindow.hpp"

#include <sstream>

#include <al.h>
#include <glm/detail/setup.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>

#include "Game.hpp"
#include "GlobalProperties.hpp"
#include "GLFWHandler.hpp"
#include "GameState.hpp"
#include "MessageState.hpp"
#include "Audio.hpp"

namespace Diggler {

int GameWindow::InstanceCount = 0;

static void glfwErrorCallback(int error, const char *description) {
  getErrorStream() << "GLFW Error " << error << ": " << description << std::endl;
}

#ifdef DEBUG
static void APIENTRY glDebugCallback(GLenum source, GLenum type, GLuint id,
  GLenum severity, GLsizei length, const GLchar *message, const void *userParam) {
  const char *sourceStr = "???";
  switch (source) {
    case GL_DEBUG_SOURCE_API:
      sourceStr = "API";
      break;
    case GL_DEBUG_SOURCE_WINDOW_SYSTEM:
      sourceStr = "WIN";
      break;
    case GL_DEBUG_SOURCE_SHADER_COMPILER:
      sourceStr = "SHC";
      break;
    case GL_DEBUG_SOURCE_THIRD_PARTY:
      sourceStr = "3PT";
      break;
    case GL_DEBUG_SOURCE_APPLICATION:
      sourceStr = "APP";
      break;
    case GL_DEBUG_SOURCE_OTHER:
      sourceStr = "OTH";
      break;
  }
  const char *typeStr = "???";
  switch (type) {
    case GL_DEBUG_TYPE_ERROR:
      typeStr = "ERR";
      break;
    case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
      typeStr = "DEP";
      break;
    case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
      typeStr = "UND";
      break;
    case GL_DEBUG_TYPE_PORTABILITY:
      typeStr = "PRT";
      break;
    case GL_DEBUG_TYPE_PERFORMANCE:
      typeStr = "PRF";
      break;
    case GL_DEBUG_TYPE_MARKER:
      typeStr = "MKR";
      break;
    case GL_DEBUG_TYPE_PUSH_GROUP:
      typeStr = "GP+";
      break;
    case GL_DEBUG_TYPE_POP_GROUP:
      typeStr = "GP-";
      break;
    case GL_DEBUG_TYPE_OTHER:
      typeStr = "OTH";
      break;
  }
  const char *severityStr = "??";
  switch (severity) {
  case GL_DEBUG_SEVERITY_HIGH:
    severityStr = "HI";
    break;
  case GL_DEBUG_SEVERITY_MEDIUM:
    severityStr = "MD";
    break;
  case GL_DEBUG_SEVERITY_LOW:
    severityStr = "LO";
    break;
  case GL_DEBUG_SEVERITY_NOTIFICATION:
    severityStr = "NT";
    break;
  }
  char line[3 + 1 + 3 + 1 + 2 + 2 + 1];
  std::snprintf(line, sizeof(line)/sizeof(line[0]), "%3s %3s %2s] ", sourceStr, typeStr, severityStr);
  getDebugStreamRaw() << line << message << std::endl;
}
#endif

GameWindow::GameWindow(Game *G) : G(G) {
  if (InstanceCount++ == 0) {
    glfwSetErrorCallback(glfwErrorCallback);
    int glfwStatus = glfwInit();
    if (glfwStatus != GL_TRUE) {
      std::ostringstream err;
      err << "GLFW init failed (" << glfwStatus << ')';
      throw std::runtime_error(err.str());
    }
    getOutputStreamRaw() << "GLFW linked " << GLFW_VERSION_MAJOR << '.' << GLFW_VERSION_MINOR <<
        '.' << GLFW_VERSION_REVISION << ", using " << glfwGetVersionString() << std::endl;
  }

  GLFWHandler::getInstance().setWindow(this, m_window);

  m_w = 640; m_h = 480;

  glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
  glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
  //glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API);
  glfwWindowHint(GLFW_SAMPLES, 0); // Gimme aliasing everywhere
  //glfwWindowHint(GLFW_STENCIL_BITS, 8);

#ifdef DEBUG
  glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GL_TRUE);
#endif

  m_window = glfwCreateWindow(m_w, m_h, "Diggler", nullptr, nullptr);
  if (!m_window) {
    glfwTerminate();
    throw std::runtime_error("GLFW window creation failed");
  }
  glfwMakeContextCurrent(m_window);
#ifdef DEBUG
  glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, nullptr, GL_TRUE);
  glDebugMessageCallback(glDebugCallback, nullptr);
#endif
  glfwSetFramebufferSizeCallback(m_window, GLFWHandler::resize);
  glfwSetCursorPosCallback(m_window, GLFWHandler::cursorPos);
  glfwSetKeyCallback(m_window, GLFWHandler::key);
  glfwSetMouseButtonCallback(m_window, GLFWHandler::mouseButton);
  glfwSetScrollCallback(m_window, GLFWHandler::mouseScroll);
  glfwSetCharCallback(m_window, GLFWHandler::unichar);
  glfwSwapInterval(1);
  /*GLint bits;
  glGetIntegerv(GL_STENCIL_BITS, &bits);
  getDebugStream() << bits << " stencil bits" << std::endl;*/

  getOutputStreamRaw() << "GLM " << GLM_VERSION_MAJOR << '.' << GLM_VERSION_MINOR << '.' << GLM_VERSION_PATCH << ' '
#if GLM_ARCH & GLM_ARCH_AVX512_BIT
  << "AVX512 "
#endif
#if GLM_ARCH & GLM_ARCH_AVX2_BIT
  << "AVX2 "
#endif
#if GLM_ARCH & GLM_ARCH_AVX_BIT
  << "AVX "
#endif
#if GLM_ARCH & GLM_ARCH_SSE42_BIT
 << "SSE42 "
#endif
#if GLM_ARCH & GLM_ARCH_SSE41_BIT
  << "SSE41 "
#endif
#if GLM_ARCH & GLM_ARCH_SSSE3_BIT
 << "SSSE3 "
#endif
#if GLM_ARCH & GLM_ARCH_SSE3_BIT
  << "SSE3 "
#endif
#if GLM_ARCH & GLM_ARCH_SSE2_BIT
  << "SSE2 "
#endif
  ;

  getOutputStreamRaw() << "-- Epoxy GL" << (epoxy_is_desktop_gl() ? "" : "ES") << epoxy_gl_version() << std::endl;

  if (InstanceCount == 1) { // If we're the first instance
    const uint8 *GL_version = glGetString(GL_VERSION);
    //const uint8 *GL_vendor = glGetString(GL_VENDOR);
    const uint8 *GL_renderer = glGetString(GL_RENDERER);
    getOutputStreamRaw() << "GL " << GL_version << " / " << GL_renderer << std::endl;
  }

  UIM = new UI::Manager;
  UIM->onResize(m_w, m_h);

  G->init();
  UIM->setup(G);
  G->GW = this;
  G->UIM = UIM;
  G->A->loadSoundAssets();

  G->FM->loadFont(getAssetPath("04b08.png"), "04b08");
  G->FM->setDefaultFont("04b08");

  glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
  glEnable(GL_BLEND);
  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}

GameWindow::~GameWindow() {
  m_currentState.reset();
  m_nextState.reset();
  delete UIM;

  glfwDestroyWindow(m_window);

  if (--InstanceCount == 0) {
    glfwTerminate();
  }
}

bool GameWindow::shouldClose() const {
  return glfwWindowShouldClose(m_window);
}

void GameWindow::setVisible(bool visible) {
  return visible ? glfwShowWindow(m_window) : glfwHideWindow(m_window);
}

bool GameWindow::isVisible() const {
  return glfwGetWindowAttrib(m_window, GLFW_VISIBLE);
}

void GameWindow::cbChar(char32 unichar) {
  UIM->onChar(unichar);
  m_currentState->onChar(unichar);
}

void GameWindow::cbKey(int key, int scancode, int action, int mods) {
  UIM->onKey(key, scancode, action, mods);
  m_currentState->onKey(key, scancode, action, mods);
}

void GameWindow::cbMouseButton(int key, int action, int mods) {
  UIM->onMouseButton(key, action, mods);
  m_currentState->onMouseButton(key, action, mods);
}

void GameWindow::cbCursorPos(double x, double y) {
  UIM->onCursorPos(x, y);
  m_currentState->onCursorPos(x, y);
}

void GameWindow::cbMouseScroll(double x, double y) {
  UIM->onMouseScroll(x, y);
  m_currentState->onMouseScroll(x, y);
}

void GameWindow::cbResize(int w, int h) {
  m_w = w; m_h = h;
  glViewport(0, 0, w, h);
  UIM->onResize(w, h);
  m_currentState->onResize(w, h);
}

void GameWindow::setNextState(std::unique_ptr<State> &&next) {
  m_nextState = std::move(next);
}

void GameWindow::run() {
  while (m_nextState != nullptr && !glfwWindowShouldClose(m_window)) {
    m_currentState = std::move(m_nextState);
    m_nextState = nullptr;
    UIM->clear();
    m_currentState->run();
    m_currentState.reset();
  }
}

void GameWindow::showMessage(const std::string &msg, const std::string &submsg) {
  setNextState(std::move(std::make_unique<MessageState>(this, msg, submsg)));
}

}
<|endoftext|>


<commit_before>#include "Genes/Gene.h"

#include <cmath>
#include <iostream>
#include <algorithm>

#include "Game/Board.h"
#include "Game/Color.h"
#include "Utility.h"

Gene::Gene() : priority(0.0)
{
}

void Gene::reset_properties() const
{
    properties["Priority"] = priority;
}

void Gene::load_properties()
{
    priority = properties["Priority"];
}

void Gene::read_from(std::istream& is)
{
    reset_properties();

    std::string line;
    while(std::getline(is, line))
    {
        line = String::strip_comments(line, '#');
        if(line.empty())
        {
            break;
        }

        auto split_line = String::split(line, ":");
        if(split_line.size() != 2)
        {
            throw_on_invalid_line(line, "There should be exactly one colon per gene property line.");
        }
        auto property_name = String::trim_outer_whitespace(split_line[0]);
        auto property_data = String::trim_outer_whitespace(split_line[1]);
        if(property_name == "Name")
        {
            if(property_data == name())
            {
                continue;
            }
            else
            {
                throw std::runtime_error("Reading data for wrong gene. Gene is " + name() + ", data is for " + property_data + ".");
            }
        }
        auto property_value = std::stod(property_data);
        try
        {
            properties.at(property_name) = property_value;
        }
        catch(const std::out_of_range&)
        {
            throw_on_invalid_line(line, "Unrecognized parameter.");
        }
    }

    load_properties();
}

void Gene::read_from(const std::string& file_name)
{
    auto ifs = std::ifstream(file_name);
    std::string line;

    while(std::getline(ifs, line))
    {
        if(String::starts_with(line, "Name: "))
        {
            auto gene_name = String::trim_outer_whitespace(String::split(line, ":", 1)[1]);
            if(gene_name == name())
            {
                read_from(ifs);
                return;
            }
        }
    }

    throw std::runtime_error(name() + " not found in " + file_name);
}

void Gene::throw_on_invalid_line(const std::string& line, const std::string& reason) const
{
    throw std::runtime_error("Invalid line in while reading for " + name() + ": " + line + "\n" + reason);
}

void Gene::mutate()
{
    priority += Random::random_laplace(10.0);
    gene_specific_mutation();
}

void Gene::gene_specific_mutation()
{
}

double Gene::evaluate(const Board& board, const Board& opposite_board) const
{
    return priority*score_board(board, opposite_board);
}

void Gene::print(std::ostream& os) const
{
    reset_properties();
    os << "Name: " << name() << "\n";
    for(const auto& name_value : properties)
    {
        os << name_value.first << ": " << name_value.second << "\n";
    }
    os << '\n';
}

void Gene::reset_piece_strength_gene(const Piece_Strength_Gene*)
{
}

bool Gene::test(const Board& board, double expected_score) const
{
    auto other_board = board;
    other_board.set_turn(opposite(board.whose_turn()));
    auto result = score_board(board, other_board);
    if(std::abs(result - expected_score) > 1e-6)
    {
        std::cerr << "Error in " << name() << ": Expected " << expected_score << ", Got: " << result << '\n';
        return false;
    }

    return true;
}

double Gene::get_priority() const
{
    return priority;
}

void Gene::make_priority_minimum_zero()
{
    priority = std::max(priority, 0.0);
}

void Gene::make_priority_positive()
{
    priority = std::abs(priority);
}
<commit_msg>Better genetic value parsing<commit_after>#include "Genes/Gene.h"

#include <cmath>
#include <iostream>
#include <algorithm>

#include "Game/Board.h"
#include "Game/Color.h"
#include "Utility.h"

Gene::Gene() : priority(0.0)
{
}

void Gene::reset_properties() const
{
    properties["Priority"] = priority;
}

void Gene::load_properties()
{
    priority = properties["Priority"];
}

void Gene::read_from(std::istream& is)
{
    reset_properties();

    std::string line;
    while(std::getline(is, line))
    {
        line = String::strip_comments(line, '#');
        if(line.empty())
        {
            break;
        }

        auto split_line = String::split(line, ":");
        if(split_line.size() != 2)
        {
            throw_on_invalid_line(line, "There should be exactly one colon per gene property line.");
        }
        auto property_name = String::trim_outer_whitespace(split_line[0]);
        auto property_data = String::trim_outer_whitespace(split_line[1]);
        if(property_name == "Name")
        {
            if(property_data == name())
            {
                continue;
            }
            else
            {
                throw std::runtime_error("Reading data for wrong gene. Gene is " + name() + ", data is for " + property_data + ".");
            }
        }

        try
        {
            properties.at(property_name) = std::stod(property_data);
        }
        catch(const std::out_of_range&)
        {
            throw_on_invalid_line(line, "Unrecognized parameter.");
        }
        catch(const std::invalid_argument&)
        {
            throw_on_invalid_line(line, "Bad parameter value.");
        }
    }

    load_properties();
}

void Gene::read_from(const std::string& file_name)
{
    auto ifs = std::ifstream(file_name);
    std::string line;

    while(std::getline(ifs, line))
    {
        if(String::starts_with(line, "Name: "))
        {
            auto gene_name = String::trim_outer_whitespace(String::split(line, ":", 1)[1]);
            if(gene_name == name())
            {
                read_from(ifs);
                return;
            }
        }
    }

    throw std::runtime_error(name() + " not found in " + file_name);
}

void Gene::throw_on_invalid_line(const std::string& line, const std::string& reason) const
{
    throw std::runtime_error("Invalid line in while reading for " + name() + ": " + line + "\n" + reason);
}

void Gene::mutate()
{
    priority += Random::random_laplace(10.0);
    gene_specific_mutation();
}

void Gene::gene_specific_mutation()
{
}

double Gene::evaluate(const Board& board, const Board& opposite_board) const
{
    return priority*score_board(board, opposite_board);
}

void Gene::print(std::ostream& os) const
{
    reset_properties();
    os << "Name: " << name() << "\n";
    for(const auto& name_value : properties)
    {
        os << name_value.first << ": " << name_value.second << "\n";
    }
    os << '\n';
}

void Gene::reset_piece_strength_gene(const Piece_Strength_Gene*)
{
}

bool Gene::test(const Board& board, double expected_score) const
{
    auto other_board = board;
    other_board.set_turn(opposite(board.whose_turn()));
    auto result = score_board(board, other_board);
    if(std::abs(result - expected_score) > 1e-6)
    {
        std::cerr << "Error in " << name() << ": Expected " << expected_score << ", Got: " << result << '\n';
        return false;
    }

    return true;
}

double Gene::get_priority() const
{
    return priority;
}

void Gene::make_priority_minimum_zero()
{
    priority = std::max(priority, 0.0);
}

void Gene::make_priority_positive()
{
    priority = std::abs(priority);
}
<|endoftext|>


<commit_before>/* Copyright 2019 Google LLC. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#include "trmul.h"

#include <cstring>

#include "third_party/gemmlowp/profiling/instrumentation.h"
#include "allocator.h"
#include "block_map.h"
#include "common.h"
#include "opt_set.h"
#include "side_pair.h"
#include "spec.h"
#include "thread_pool.h"
#include "trace.h"

namespace ruy {

namespace {

struct TrMulTask final : Task {
  TrMulTask(TrMulParams* params_, const BlockMap& block_map_,
            std::atomic<int>* atomic_block_id_, int thread_id_,
            SidePair<std::atomic<bool>*> packed_,
            TuningResolver* tuning_resolver_, Allocator* local_allocator_,
            Trace* trace_)
      : params(params_),
        block_map(block_map_),
        atomic_block_id(atomic_block_id_),
        thread_id(thread_id_),
        packed(packed_),
        tuning_resolver(tuning_resolver_),
        local_allocator(local_allocator_),
        trace(trace_) {}

  void Run() override {
    TraceRecordThreadStart(thread_id, trace);

    // Local indicators of packedness to avoid the overhead of atomic ops.
    SidePair<bool*> local_packed{nullptr, nullptr};

    for (Side side : {Side::kLhs, Side::kRhs}) {
      if (packed[side]) {
        const int size = NumBlocksPerSide(side, block_map);
        local_allocator->Allocate(size, &local_packed[side]);
        memset(local_packed[side], 0, size * sizeof(bool));
      }
    }

    const int num_blocks = NumBlocks(block_map);

    const Tuning tuning = tuning_resolver->Resolve();

    TraceRecordThreadLoopStart(thread_id, trace);

    SidePair<int> block;
    SidePair<int> start;
    SidePair<int> end;

    // Each thread starts by initially reserving the block whose id
    // is the thread id.
    int block_id = thread_id;
    TraceRecordBlockReserved(thread_id, block_id, trace);

    while (block_id < num_blocks) {
      // Reserve the next block to handle. In order to hide the latency
      // (typically comparable to an access to the level of data cache that
      // is shared among CPU cores, e.g. 60 cycles on an ARM CPU as of 2019)
      // of this atomic operation, we structure this code so as to avoid
      // immediately depending on the `next_n` result.
      const int next_block_id =
          atomic_block_id->fetch_add(1, std::memory_order_relaxed);
      TraceRecordBlockReserved(thread_id, next_block_id, trace);
      // Get coordinates of the current block to handle, in "block space".
      GetBlockByIndex(block_map, block_id, &block);
      // Get coordinates of the current block to handle, in matrix space.
      GetBlockMatrixCoords(block_map, block, &start, &end);
      TraceRecordBlockCoordsComputed(block_id, trace);
      // Maybe pack the current LHS/RHS block, if not already packed.
      for (Side side : {Side::kLhs, Side::kRhs}) {
        EnsurePacked(side, block_id, local_packed, block, start, end, tuning);
      }
      // Actually do matrix multiplication work
      params->RunKernel(tuning, start, end);
      TraceRecordBlockFinished(block_id, trace);
      // Move on to the next block as obtained by the atomic increment
      // at the start of this while loop iteration.
      block_id = next_block_id;
    }

    local_allocator->FreeAll();

    TraceRecordThreadEnd(thread_id, trace);
  }

 private:
  void EnsurePacked(Side side, int block_id, const SidePair<bool*> local_packed,
                    const SidePair<int>& block, const SidePair<int>& start,
                    const SidePair<int>& end, Tuning tuning) {
    // If two threads concurrently hit the same block to pack,
    // we allow them to concurrently pack it, writing the same packed matrix
    // data to the same location. That is considered worth it to avoid
    // having one thread blocked on another one. Avoiding that is considered
    // important especially on mobile, where there can be large speed
    // discrepancy between threads, e.g. if different threads are scheduled
    // on CPU cores of different types (big/little), different clock speed,
    // different contention with other processes.
    if (local_packed[side] && !local_packed[side][block[side]]) {
      if (!packed[side][block[side]].load(std::memory_order_acquire)) {
        params->RunPack(side, tuning, start, end);
        TraceRecordBlockPacked(side, block_id, trace);
        local_packed[side][block[side]] = true;
        packed[side][block[side]].store(true, std::memory_order_release);
      }
    }
  }

  TrMulParams* params;
  const BlockMap& block_map;
  std::atomic<int>* atomic_block_id;
  int thread_id;
  SidePair<std::atomic<bool>*> packed;
  TuningResolver* tuning_resolver;
  Allocator* local_allocator;
  Trace* trace;
};

void AllocatePMatrix(Allocator* allocator, PMatrix* packed) {
  packed->data = allocator->AllocateBytes(DataSize(*packed));
  packed->sums = allocator->AllocateBytes(SumsSize(*packed));
}

int GetThreadCount(Context* context, int rows, int cols, int depth) {
  // Empirically determined rule for reasonable number of
  // threads to use. This is proportional to the number of arithmetic ops
  // in this Mul (product of the 3 sizes).
  int guess = (std::uint64_t(rows) * cols * depth) >> 13;
  return clamp(guess, 1, context->max_num_threads);
}

LoopStructure GetLoopStructure(int thread_count, int rows, int cols, int depth,
                               int cache_friendly_traversal_threshold) {
  if (thread_count == 1 &&
      (rows + cols) * depth < cache_friendly_traversal_threshold) {
    return LoopStructure::kSimple;
  }
  return LoopStructure::kGeneral;
}

}  // namespace

void TrMul(TrMulParams* params, Context* context) {
  gemmlowp::ScopedProfilingLabel label("TrMul");

  PMatrix& packed_lhs = params->packed[Side::kLhs];
  PMatrix& packed_rhs = params->packed[Side::kRhs];
  DMatrix& lhs = params->src[Side::kLhs];
  DMatrix& rhs = params->src[Side::kRhs];

  const int rows = lhs.layout.cols;
  const int cols = rhs.layout.cols;
  const int depth = lhs.layout.rows;

  int thread_count = GetThreadCount(context, rows, cols, depth);
  const auto loop_structure =
      GetLoopStructure(thread_count, rows, cols, depth,
                       params->cache_friendly_traversal_threshold);
  Allocator* allocator = context->GetMainAllocator();

  // Allocate packed matrices
  for (Side side : {Side::kLhs, Side::kRhs}) {
    if (!params->is_prepacked[side]) {
      AllocatePMatrix(allocator, &params->packed[side]);
    }
  }

  // Case of running this TrMul as a simple loop.
  // This is a good place to start reading this function: all the rest
  // of this function is just an optimized, but functionally equivalent,
  // version of that.
  if (loop_structure == LoopStructure::kSimple) {
    gemmlowp::ScopedProfilingLabel label_simple("TrMulImpl, simple loop");
    Tuning tuning = context->GetMainThreadTuning();

    const SidePair<int> origin{0, 0};
    const SidePair<int> rounded_dims{packed_lhs.layout.cols,
                                     packed_rhs.layout.cols};
    for (Side side : {Side::kLhs, Side::kRhs}) {
      if (!params->is_prepacked[side]) {
        params->RunPack(side, tuning, origin, rounded_dims);
      }
    }
    params->RunKernel(tuning, origin, rounded_dims);

    allocator->FreeAll();
    return;
  }

  gemmlowp::ScopedProfilingLabel label_general("TrMulImpl, general case");

  auto* trace = NewTraceOrNull(&context->tracing, rows, depth, cols);
  TraceRecordStart(trace);

  // Initialize block map.
  BlockMap block_map;
  MakeBlockMap(packed_lhs.layout.cols, packed_rhs.layout.cols, depth,
               packed_lhs.layout.kernel.cols, packed_rhs.layout.kernel.cols,
               packed_lhs.data_type.size, packed_rhs.data_type.size,
               params->cache_friendly_traversal_threshold, &block_map);

  // Initialize per-thread state.
  thread_count = clamp(thread_count, 1, NumBlocks(block_map));
  context->EnsureNPerThreadStates(thread_count);
  for (auto& per_thread_state : context->per_thread_states) {
    per_thread_state->tuning_resolver.SetTuning(context->explicit_tuning);
  }

  // Allocate and initialize atomic values tracking already-packed blocks.
  SidePair<std::atomic<bool>*> packed{nullptr, nullptr};
  for (Side side : {Side::kLhs, Side::kRhs}) {
    if (!params->is_prepacked[side]) {
      const int size = NumBlocksPerSide(side, block_map);
      allocator->Allocate(size, &packed[side]);
      for (int i = 0; i < size; i++) {
        packed[side][i].store(false, std::memory_order_relaxed);
      }
    }
  }

  // Create the atomic block id, allocate it using Allocator so that
  // we get the alignment ensuring that it sits alone in its exclusives
  // reservation granule.
  std::atomic<int>* atomic_block_id;
  allocator->Allocate(1, &atomic_block_id);

  // Create task objects.
  TrMulTask* tasks;
  allocator->Allocate(thread_count, &tasks);

  atomic_block_id->store(thread_count);

  for (int i = 0; i < thread_count; i++) {
    new (tasks + i) TrMulTask(params, block_map, atomic_block_id, i, packed,
                              &context->per_thread_states[i]->tuning_resolver,
                              &context->per_thread_states[i]->allocator, trace);
  }

  // Do the computation.
  TraceRecordExecute(trace);
  TraceStartRecordingBlockAndThreadFields(block_map, thread_count, trace);

  context->workers_pool.Execute(thread_count, tasks);

  // Finish up.
  for (int i = 0; i < thread_count; i++) {
    tasks[i].~TrMulTask();
  }

  TraceRecordEnd(trace);

  allocator->FreeAll();
}

}  // namespace ruy
<commit_msg>Oops: we were never taking advantage of a read of the atomic 'packed' indicator returning true, to update the local_packed indicator. In other words, when another thread had packed a block, and we had obtained that information from an expensive atomic read, we did not cache that precious information to avoid subsequent expensive atomic reads.<commit_after>/* Copyright 2019 Google LLC. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#include "trmul.h"

#include <cstring>

#include "third_party/gemmlowp/profiling/instrumentation.h"
#include "allocator.h"
#include "block_map.h"
#include "common.h"
#include "opt_set.h"
#include "side_pair.h"
#include "spec.h"
#include "thread_pool.h"
#include "trace.h"

namespace ruy {

namespace {

struct TrMulTask final : Task {
  TrMulTask(TrMulParams* params_, const BlockMap& block_map_,
            std::atomic<int>* atomic_block_id_, int thread_id_,
            SidePair<std::atomic<bool>*> packed_,
            TuningResolver* tuning_resolver_, Allocator* local_allocator_,
            Trace* trace_)
      : params(params_),
        block_map(block_map_),
        atomic_block_id(atomic_block_id_),
        thread_id(thread_id_),
        packed(packed_),
        tuning_resolver(tuning_resolver_),
        local_allocator(local_allocator_),
        trace(trace_) {}

  void Run() override {
    TraceRecordThreadStart(thread_id, trace);

    // Local indicators of packedness to avoid the overhead of atomic ops.
    SidePair<bool*> local_packed{nullptr, nullptr};

    for (Side side : {Side::kLhs, Side::kRhs}) {
      if (packed[side]) {
        const int size = NumBlocksPerSide(side, block_map);
        local_allocator->Allocate(size, &local_packed[side]);
        memset(local_packed[side], 0, size * sizeof(bool));
      }
    }

    const int num_blocks = NumBlocks(block_map);

    const Tuning tuning = tuning_resolver->Resolve();

    TraceRecordThreadLoopStart(thread_id, trace);

    SidePair<int> block;
    SidePair<int> start;
    SidePair<int> end;

    // Each thread starts by initially reserving the block whose id
    // is the thread id.
    int block_id = thread_id;
    TraceRecordBlockReserved(thread_id, block_id, trace);

    while (block_id < num_blocks) {
      // Reserve the next block to handle. In order to hide the latency
      // (typically comparable to an access to the level of data cache that
      // is shared among CPU cores, e.g. 60 cycles on an ARM CPU as of 2019)
      // of this atomic operation, we structure this code so as to avoid
      // immediately depending on the `next_n` result.
      const int next_block_id =
          atomic_block_id->fetch_add(1, std::memory_order_relaxed);
      TraceRecordBlockReserved(thread_id, next_block_id, trace);
      // Get coordinates of the current block to handle, in "block space".
      GetBlockByIndex(block_map, block_id, &block);
      // Get coordinates of the current block to handle, in matrix space.
      GetBlockMatrixCoords(block_map, block, &start, &end);
      TraceRecordBlockCoordsComputed(block_id, trace);
      // Maybe pack the current LHS/RHS block, if not already packed.
      for (Side side : {Side::kLhs, Side::kRhs}) {
        EnsurePacked(side, block_id, local_packed, block, start, end, tuning);
      }
      // Actually do matrix multiplication work
      params->RunKernel(tuning, start, end);
      TraceRecordBlockFinished(block_id, trace);
      // Move on to the next block as obtained by the atomic increment
      // at the start of this while loop iteration.
      block_id = next_block_id;
    }

    local_allocator->FreeAll();

    TraceRecordThreadEnd(thread_id, trace);
  }

 private:
  void EnsurePacked(Side side, int block_id, const SidePair<bool*> local_packed,
                    const SidePair<int>& block, const SidePair<int>& start,
                    const SidePair<int>& end, Tuning tuning) {
    // If two threads concurrently hit the same block to pack,
    // we allow them to concurrently pack it, writing the same packed matrix
    // data to the same location. That is considered worth it to avoid
    // having one thread blocked on another one. Avoiding that is considered
    // important especially on mobile, where there can be large speed
    // discrepancy between threads, e.g. if different threads are scheduled
    // on CPU cores of different types (big/little), different clock speed,
    // different contention with other processes.
    if (local_packed[side] && !local_packed[side][block[side]]) {
      if (!packed[side][block[side]].load(std::memory_order_acquire)) {
        params->RunPack(side, tuning, start, end);
        TraceRecordBlockPacked(side, block_id, trace);
        packed[side][block[side]].store(true, std::memory_order_release);
      }
      local_packed[side][block[side]] = true;
    }
  }

  TrMulParams* params;
  const BlockMap& block_map;
  std::atomic<int>* atomic_block_id;
  int thread_id;
  SidePair<std::atomic<bool>*> packed;
  TuningResolver* tuning_resolver;
  Allocator* local_allocator;
  Trace* trace;
};

void AllocatePMatrix(Allocator* allocator, PMatrix* packed) {
  packed->data = allocator->AllocateBytes(DataSize(*packed));
  packed->sums = allocator->AllocateBytes(SumsSize(*packed));
}

int GetThreadCount(Context* context, int rows, int cols, int depth) {
  // Empirically determined rule for reasonable number of
  // threads to use. This is proportional to the number of arithmetic ops
  // in this Mul (product of the 3 sizes).
  int guess = (std::uint64_t(rows) * cols * depth) >> 13;
  return clamp(guess, 1, context->max_num_threads);
}

LoopStructure GetLoopStructure(int thread_count, int rows, int cols, int depth,
                               int cache_friendly_traversal_threshold) {
  if (thread_count == 1 &&
      (rows + cols) * depth < cache_friendly_traversal_threshold) {
    return LoopStructure::kSimple;
  }
  return LoopStructure::kGeneral;
}

}  // namespace

void TrMul(TrMulParams* params, Context* context) {
  gemmlowp::ScopedProfilingLabel label("TrMul");

  PMatrix& packed_lhs = params->packed[Side::kLhs];
  PMatrix& packed_rhs = params->packed[Side::kRhs];
  DMatrix& lhs = params->src[Side::kLhs];
  DMatrix& rhs = params->src[Side::kRhs];

  const int rows = lhs.layout.cols;
  const int cols = rhs.layout.cols;
  const int depth = lhs.layout.rows;

  int thread_count = GetThreadCount(context, rows, cols, depth);
  const auto loop_structure =
      GetLoopStructure(thread_count, rows, cols, depth,
                       params->cache_friendly_traversal_threshold);
  Allocator* allocator = context->GetMainAllocator();

  // Allocate packed matrices
  for (Side side : {Side::kLhs, Side::kRhs}) {
    if (!params->is_prepacked[side]) {
      AllocatePMatrix(allocator, &params->packed[side]);
    }
  }

  // Case of running this TrMul as a simple loop.
  // This is a good place to start reading this function: all the rest
  // of this function is just an optimized, but functionally equivalent,
  // version of that.
  if (loop_structure == LoopStructure::kSimple) {
    gemmlowp::ScopedProfilingLabel label_simple("TrMulImpl, simple loop");
    Tuning tuning = context->GetMainThreadTuning();

    const SidePair<int> origin{0, 0};
    const SidePair<int> rounded_dims{packed_lhs.layout.cols,
                                     packed_rhs.layout.cols};
    for (Side side : {Side::kLhs, Side::kRhs}) {
      if (!params->is_prepacked[side]) {
        params->RunPack(side, tuning, origin, rounded_dims);
      }
    }
    params->RunKernel(tuning, origin, rounded_dims);

    allocator->FreeAll();
    return;
  }

  gemmlowp::ScopedProfilingLabel label_general("TrMulImpl, general case");

  auto* trace = NewTraceOrNull(&context->tracing, rows, depth, cols);
  TraceRecordStart(trace);

  // Initialize block map.
  BlockMap block_map;
  MakeBlockMap(packed_lhs.layout.cols, packed_rhs.layout.cols, depth,
               packed_lhs.layout.kernel.cols, packed_rhs.layout.kernel.cols,
               packed_lhs.data_type.size, packed_rhs.data_type.size,
               params->cache_friendly_traversal_threshold, &block_map);

  // Initialize per-thread state.
  thread_count = clamp(thread_count, 1, NumBlocks(block_map));
  context->EnsureNPerThreadStates(thread_count);
  for (auto& per_thread_state : context->per_thread_states) {
    per_thread_state->tuning_resolver.SetTuning(context->explicit_tuning);
  }

  // Allocate and initialize atomic values tracking already-packed blocks.
  SidePair<std::atomic<bool>*> packed{nullptr, nullptr};
  for (Side side : {Side::kLhs, Side::kRhs}) {
    if (!params->is_prepacked[side]) {
      const int size = NumBlocksPerSide(side, block_map);
      allocator->Allocate(size, &packed[side]);
      for (int i = 0; i < size; i++) {
        packed[side][i].store(false, std::memory_order_relaxed);
      }
    }
  }

  // Create the atomic block id, allocate it using Allocator so that
  // we get the alignment ensuring that it sits alone in its exclusives
  // reservation granule.
  std::atomic<int>* atomic_block_id;
  allocator->Allocate(1, &atomic_block_id);

  // Create task objects.
  TrMulTask* tasks;
  allocator->Allocate(thread_count, &tasks);

  atomic_block_id->store(thread_count);

  for (int i = 0; i < thread_count; i++) {
    new (tasks + i) TrMulTask(params, block_map, atomic_block_id, i, packed,
                              &context->per_thread_states[i]->tuning_resolver,
                              &context->per_thread_states[i]->allocator, trace);
  }

  // Do the computation.
  TraceRecordExecute(trace);
  TraceStartRecordingBlockAndThreadFields(block_map, thread_count, trace);

  context->workers_pool.Execute(thread_count, tasks);

  // Finish up.
  for (int i = 0; i < thread_count; i++) {
    tasks[i].~TrMulTask();
  }

  TraceRecordEnd(trace);

  allocator->FreeAll();
}

}  // namespace ruy
<|endoftext|>


<commit_before>/*
 * Port for usage with qt-framework and development for kdesvn
 * (C) 2005-2007 by Rajko Albrecht
 * http://kdesvn.alwins-world.de
 */
/*
 * ====================================================================
 * Copyright (c) 2002-2005 The RapidSvn Group.  All rights reserved.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library (in the file LGPL.txt); if not,
 * write to the Free Software Foundation, Inc., 51 Franklin St,
 * Fifth Floor, Boston, MA  02110-1301  USA
 *
 * This software consists of voluntary contributions made by many
 * individuals.  For exact contribution history, see the revision
 * history and logs, available at http://rapidsvn.tigris.org/.
 * ====================================================================
 */

// svncpp
#include "pool.hpp"

namespace svn
{
   bool Pool::s_initialized = false;

  apr_pool_t *
  Pool::pool_create (apr_pool_t * parent)
  {
    return svn_pool_create (parent);
  }

  Pool::Pool (apr_pool_t * parent)
    : m_parent (parent), m_pool (pool_create (parent))
  {
  }

  Pool::~Pool ()
  {
    if(m_pool)
    {
      svn_pool_destroy (m_pool);
    }
  }

  apr_pool_t *
  Pool::pool () const
  {
      svn_pool_clear(m_pool);
    return m_pool;
  }

  void
  Pool::renew ()
  {
    if (m_pool)
    {
      svn_pool_destroy (m_pool);
    }
    m_pool = pool_create (m_parent);
  }

//TODO
//   apr_pool_t *
//   Pool::operator=(const Pool & pool)
//   {
//     return
//     if (this == &path)
//       return *this;
//     m_path = path.c_str();
//     return *this;
//   }
}

/* -----------------------------------------------------------------
 * local variables:
 * eval: (load-file "../../rapidsvn-dev.el")
 * end:
 */
<commit_msg>removed wrong pool handling<commit_after>/*
 * Port for usage with qt-framework and development for kdesvn
 * (C) 2005-2007 by Rajko Albrecht
 * http://kdesvn.alwins-world.de
 */
/*
 * ====================================================================
 * Copyright (c) 2002-2005 The RapidSvn Group.  All rights reserved.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library (in the file LGPL.txt); if not,
 * write to the Free Software Foundation, Inc., 51 Franklin St,
 * Fifth Floor, Boston, MA  02110-1301  USA
 *
 * This software consists of voluntary contributions made by many
 * individuals.  For exact contribution history, see the revision
 * history and logs, available at http://rapidsvn.tigris.org/.
 * ====================================================================
 */

// svncpp
#include "pool.hpp"

namespace svn
{
   bool Pool::s_initialized = false;

  apr_pool_t *
  Pool::pool_create (apr_pool_t * parent)
  {
    return svn_pool_create (parent);
  }

  Pool::Pool (apr_pool_t * parent)
    : m_parent (parent), m_pool (pool_create (parent))
  {
  }

  Pool::~Pool ()
  {
    if(m_pool)
    {
        svn_pool_destroy (m_pool);
    }
  }

  apr_pool_t *
  Pool::pool () const
  {
    return m_pool;
  }

  void
  Pool::renew ()
  {
    if (m_pool)
    {
      svn_pool_destroy (m_pool);
    }
    m_pool = pool_create (m_parent);
  }

//TODO
//   apr_pool_t *
//   Pool::operator=(const Pool & pool)
//   {
//     return
//     if (this == &path)
//       return *this;
//     m_path = path.c_str();
//     return *this;
//   }
}

/* -----------------------------------------------------------------
 * local variables:
 * eval: (load-file "../../rapidsvn-dev.el")
 * end:
 */
<|endoftext|>