<commit_before>#include "ofApp.h"
#include "ofxXmlSettings.h"

const int kForward = 1;
const int kBack = -1;

void ofApp::animateVideo(const int direction) {
    if (direction != kForward && direction != kBack) {
        ofLogError() << "Invalid direction " << direction;
        return;
    }
    if (videoPlayer.getSpeed() != direction) {
        videoPlayer.setPaused(true);
        videoPlayer.setSpeed(direction);
    }

    if (!isPlaying()) {
        videoPlayer.play();
    }

    videoPlayer.update();
}

bool ofApp::isPlaying() {
    return videoPlayer.isPlaying() && !videoPlayer.isPaused();
}

bool ofApp::loadVideo() {
    videoPlayer = ofVideoPlayer();
    if (!videoPlayer.loadMovie(ofToDataPath(configuration.VideoFileName))) {
        return false;
    }
    videoPlayer.setLoopState(OF_LOOP_NONE);
    return true;
}

void ofApp::setup(){
    // start logging
    ofLogToFile("app.log");

    // start recoding events
    if (!eventLog.open(ofToDataPath("events.txt"), ofFile::WriteOnly)) {
        ofLogError() << "Error opening events.txt - !!!DATA WILL BE LOST!!!";
    }

    if (!configuration.Read()) {
        ofLogError() << "Error reading configuration";
    }

    if (!gameStats.Read()) {
        ofLogError() << "Error reading game stats.";
    }

    ofSetFrameRate(configuration.FrameRate);

    ofSetFullscreen(configuration.Fullscreen);

#ifdef TARGET_OSX
    ofSetDataPathRoot("../Resources/data/");
#endif

    // Distance reading
    serialPort.listDevices();
    vector<ofSerialDeviceInfo> deviceList = serialPort.getDeviceList();
    if (configuration.ActiveSerialPort < deviceList.size()) {
        if (!serialPort.setup(configuration.ActiveSerialPort, 9600)) {
            ofLogError() << "Failed to connect to serial device! "
                << deviceList[configuration.ActiveSerialPort].getDeviceName();
        }
    }

    currentDistance = configuration.MaxDistance;

    previousDistanceChangeAt = ofGetElapsedTimeMillis();

    // HUD
    if (!f.loadFont("verdana.ttf", 16, true, true)) {
        ofLogError() << "Error loading font";
    }
    f.setLineHeight(18.0f);
    f.setLetterSpacing(1.037);

    // Audio
    if (!heartbeatSound.loadSound("2.mp3")) {
        ofLogError() << "Error loading heartbeat sound";
    }
    heartbeatSound.setLoop(true);

    // Video
    if (!loadVideo()) {
        ofLogError() << "Error loading video";
    }
}

bool Configuration::Read() {
    // Read configuration or create default
    ofxXmlSettings xml;
    if (!xml.loadFile("configuration.xml")) {
        xml.setValue("configuration:Fullscreen", Fullscreen);
        xml.setValue("configuration:MinDistance", MinDistance);
        xml.setValue("configuration:MaxDistance", MaxDistance);
        xml.setValue("configuration:DeathZone", DeathZone);
        xml.setValue("configuration:RestartIntervalSeconds", RestartIntervalSeconds);
        xml.setValue("configuration:ActiveSerialPort", ActiveSerialPort);
        xml.setValue("configuration:StartingFramesPerSecond", StartingFramesPerSecond);
        xml.setValue("configuration:FinishingFramesPerSecond", FinishingFramesPerSecond);
        xml.setValue("configuration:StartingVolume", StartingVolume);
        xml.setValue("configuration:FinishingVolume", FinishingVolume);
        xml.setValue("configuration:StartingHeartBeatSpeed", StartingHeartBeatSpeed);
        xml.setValue("configuration:FinishingHeartBeatSpeed", FinishingHeartBeatSpeed);
        xml.setValue("configuration:FrameRate", FrameRate);
        xml.setValue("configuration:VideoFileName", VideoFileName);

        if (!xml.saveFile("configuration.xml")) {
            ofLogError() << "Error saving configuration file";
            return false;
        }
    } else {
        Fullscreen = xml.getValue("configuration:Fullscreen", Fullscreen);
        MinDistance = xml.getValue("configuration:MinDistance", MinDistance);
        MaxDistance = xml.getValue("configuration:MaxDistance", MaxDistance);
        DeathZone = xml.getValue("configuration:DeathZone", DeathZone);
        RestartIntervalSeconds = xml.getValue("configuration:RestartIntervalSeconds", RestartIntervalSeconds);
        ActiveSerialPort = xml.getValue("configuration:ActiveSerialPort", ActiveSerialPort);
        StartingFramesPerSecond = xml.getValue("configuration:StartingFramesPerSecond", StartingFramesPerSecond);
        FinishingFramesPerSecond = xml.getValue("configuration:FinishingFramesPerSecond", FinishingFramesPerSecond);
        StartingVolume = xml.getValue("configuration:StartingVolume", StartingVolume);
        FinishingVolume = xml.getValue("configuration:FinishingVolume", FinishingVolume);
        StartingHeartBeatSpeed = xml.getValue("configuration:StartingHeartBeatSpeed", StartingHeartBeatSpeed);
        FinishingHeartBeatSpeed = xml.getValue("configuration:FinishingHeartBeatSpeed", FinishingHeartBeatSpeed);
        FrameRate = xml.getValue("configuration:FrameRate", FrameRate);
        VideoFileName = xml.getValue("configuration:VideoFileName", VideoFileName);
    }

    return true;
}

bool GameStats::Read() {
    // Read game stats or create default
    ofxXmlSettings xml;
    if (!xml.loadFile("gamestats.xml")) {
        if (!Write()) {
            return false;
        }
    } else {
        Saves = xml.getValue("gamestats:Saves", Saves);
        Kills = xml.getValue("gamestats:Kills", Kills);
    }

    return true;
}

bool GameStats::Write() const {
    ofFile f(ofToDataPath("gamestats.xml"));
    f.moveTo("gamestats_backup.xml", false, true);

    ofxXmlSettings xml;
    xml.setValue("gamestats:Saves", Saves);
    xml.setValue("gamestats:Kills", Kills);
    return xml.saveFile("gamestats.xml");
}

void ofApp::update(){
    long now = ofGetElapsedTimeMillis();

    if (isPlaying()) {
        if (videoPlayer.getSpeed() == kForward) {
            if (videoPlayer.getCurrentFrame() >= frameForDistance()) {
                videoPlayer.setPaused(true);
            }
        } else if (videoPlayer.getSpeed() == kBack) {
            if (videoPlayer.getCurrentFrame() <= frameForDistance()) {
                videoPlayer.setPaused(true);
            }
        }
    }

    // Determine if user is now in the death zone
    if (!state.finishedAt && (currentDistance < configuration.MinDistance + configuration.DeathZone)) {
        ofLogNotice() << "Game finished with kill at " << now;

        eventLog << "killed=" << now << std::endl;

        state.finishedAt = now;
        state.saved = false;

        setDistance("killed", configuration.MinDistance);

        gameStats.Kills++;
        if (!gameStats.Write()) {
            ofLogError() << "Error writing game stats";
        }
    }

    // If save zone is active and user finds itself in it,
    // then declare the game saved and finish it.
    int saveZoneStartsAt = std::abs(configuration.MaxDistance - configuration.DeathZone);
    if (!state.finishedAt && state.saveZoneActive && currentDistance > saveZoneStartsAt) {
        ofLogNotice() << "Game finished with save at " << now;

        eventLog << "saved=" << now << std::endl;

        state.finishedAt = now;
        state.saved = true;

        setDistance("saved", configuration.MaxDistance);

        gameStats.Saves++;
        if (!gameStats.Write()) {
            ofLogError() << "Error writing game stats";
        }
    }

    // If user has moved out of save zone, and game is not finished
    // yet, activate save zone
    int moved = std::abs(configuration.MaxDistance - currentDistance);
    if (!state.finishedAt && moved > configuration.DeathZone) {
        state.saveZoneActive = true;
    }

    // Restart if needed
    if (state.finishedAt && (state.finishedAt < now - (configuration.RestartIntervalSeconds*1000))) {
        ofLogNotice() << "Game restarted";

        state = GameState();

        setDistance("restart", configuration.MaxDistance);

        if (!loadVideo()) {
            ofLogError() << "Error loading video after kill";
        }
        ofLogNotice() << "frame after resettting video player: " << videoPlayer.getCurrentFrame();

        eventLog << "started=" << now << std::endl;
    }

    // Read serial
    if (serialPort.isInitialized()) {
        if (serialPort.available()) {
            char c = serialPort.readByte();
            if ('\n' == c) {
                std::string input = serialbuf.str();
                serialbuf.str("");
                ofLogNotice() << "Serial input: " << input << std::endl;
                float f = ofToFloat(input);

                int prev = currentDistance;

                setDistance("Serial input", f);

                if (prev > currentDistance) {
                    animateVideo(kForward);
                } else if (prev < currentDistance) {
                    animateVideo(kBack);
                }
            } else {
                serialbuf << c;
            }
        }
    }

    // Update visual
    int millis = ofMap(currentDistance,
                       configuration.MaxDistance,
                       configuration.MinDistance,
                       1000 / configuration.StartingFramesPerSecond,
                       1000 / configuration.FinishingFramesPerSecond);
    fps = 1000 / millis;

    // Update video
    videoPlayer.update();

    // Update audio
    if (!state.finishedAt) {
        if (!heartbeatSound.getIsPlaying()) {
            heartbeatSound.play();
        }
        heartbeatSound.setSpeed(ofMap(currentDistance,
                                      configuration.MaxDistance, configuration.MinDistance,
                                      configuration.StartingHeartBeatSpeed, configuration.FinishingHeartBeatSpeed));
    } else {
        if (heartbeatSound.getIsPlaying()) {
            heartbeatSound.stop();
        }
    }

    ofSoundUpdate();
}

// Frame for current distance
// Note that this is not the actual frame that will be animated.
// Instead will start to animate towards this frame.
int ofApp::frameForDistance() {
    return ofMap(currentDistance,
                 configuration.MinDistance,
                 configuration.MaxDistance,
                 videoPlayer.getTotalNumFrames(),
                 0);
}

void ofApp::draw(){
    int restartCountdownSeconds = 0;
    if (state.finishedAt) {
        long now = ofGetElapsedTimeMillis();
        int beenDeadSeconds = (now - state.finishedAt) / 1000;
        restartCountdownSeconds = configuration.RestartIntervalSeconds - beenDeadSeconds;
    }

    // Update HUD
    int y = 40;
    f.drawString("dist=" + ofToString(currentDistance), 10, y);
    f.drawString("f=" + ofToString(videoPlayer.getCurrentFrame()) + "/" + ofToString(videoPlayer.getTotalNumFrames()),
                 160, y);
    f.drawString("dest.f=" + ofToString(frameForDistance()), 300, y);
    f.drawString("fps=" + ofToString(fps), 460, y);
    f.drawString("sv=" + ofToString(gameStats.Saves), 560, y);
    f.drawString("kl=" + ofToString(gameStats.Kills), 660, y);
    f.drawString("rs=" + ofToString(restartCountdownSeconds), 760, y);
    f.drawString("vid=" + ofToString(isPlaying()), 860, y);

    const int margin = 50;

    // Draw video
    if (state.finishedAt && !isPlaying()) {
        if (state.saved) {
            ofSetHexColor(0xFFFFFF);
        } else {
            ofSetHexColor(0x000000);
        }
        ofRect(0, margin, ofGetWindowWidth(), ofGetWindowHeight() - margin);
        ofFill();
        if (!state.saved) {
            ofSetHexColor(0xFFFFFF);
        } else {
            ofSetHexColor(0x000000);
        }
        std::string text("");
        if (state.saved) {
            text = "LIFES SAVED: " + ofToString(gameStats.Saves);
        } else {
            text = "TOTAL KILLS: " + ofToString(gameStats.Kills);
        }
        f.drawString(text,
                     ofGetWindowWidth() / 2 - 100,
                     ofGetWindowHeight() / 2);

        return;
    }

    ofSetHexColor(0xFFFFFF);
    ofFill();
    videoPlayer.draw(0, margin, ofGetWindowWidth(), ofGetWindowHeight() - margin);
}

void ofApp::keyPressed(int key){
    ofLogNotice() << "keyPressed key=" << key;

    if (state.finishedAt) {
        return;
    }

    if (isPlaying()) {
        return;
    }

    const int kMinStep = 100;

    if (OF_KEY_UP == key) {
        // distance decreases as viewer approaches
        int n = currentDistance - kMinStep - int(ofRandom(100));

        setDistance("keyboard up", n);

        animateVideo(kForward);
    } else if (OF_KEY_DOWN == key) {
        // distance incrases as viewer steps back
        int n = currentDistance + kMinStep + int(ofRandom(100));

        setDistance("keyboard down", n);

        animateVideo(kBack);
    }
}

void ofApp::setDistance(const std::string reason, const int value) {
    currentDistance = ofClamp(value, configuration.MinDistance, configuration.MaxDistance);
}
<commit_msg>serial fixes<commit_after>#include "ofApp.h"
#include "ofxXmlSettings.h"

const int kForward = 1;
const int kBack = -1;

void ofApp::animateVideo(const int direction) {
    if (direction != kForward && direction != kBack) {
        ofLogError() << "Invalid direction " << direction;
        return;
    }
    if (videoPlayer.getSpeed() != direction) {
        videoPlayer.setPaused(true);
        videoPlayer.setSpeed(direction);
    }

    if (!isPlaying()) {
        videoPlayer.play();
    }

    videoPlayer.update();
}

bool ofApp::isPlaying() {
    return videoPlayer.isPlaying() && !videoPlayer.isPaused();
}

bool ofApp::loadVideo() {
    videoPlayer = ofVideoPlayer();
    if (!videoPlayer.loadMovie(ofToDataPath(configuration.VideoFileName))) {
        return false;
    }
    videoPlayer.setLoopState(OF_LOOP_NONE);
    return true;
}

void ofApp::setup(){
    // start logging
    ofLogToFile("app.log");

    // start recoding events
    if (!eventLog.open(ofToDataPath("events.txt"), ofFile::WriteOnly)) {
        ofLogError() << "Error opening events.txt - !!!DATA WILL BE LOST!!!";
    }

    if (!configuration.Read()) {
        ofLogError() << "Error reading configuration";
    }

    if (!gameStats.Read()) {
        ofLogError() << "Error reading game stats.";
    }

    ofSetFrameRate(configuration.FrameRate);

    ofSetFullscreen(configuration.Fullscreen);

#ifdef TARGET_OSX
    ofSetDataPathRoot("../Resources/data/");
#endif

    // Distance reading
    serialPort.listDevices();
    vector<ofSerialDeviceInfo> deviceList = serialPort.getDeviceList();
    if (configuration.ActiveSerialPort < deviceList.size()) {
        if (!serialPort.setup(configuration.ActiveSerialPort, 9600)) {
            ofLogError() << "Failed to connect to serial device! "
                << deviceList[configuration.ActiveSerialPort].getDeviceName();
        }
    }

    currentDistance = configuration.MaxDistance;

    previousDistanceChangeAt = ofGetElapsedTimeMillis();

    // HUD
    if (!f.loadFont("verdana.ttf", 16, true, true)) {
        ofLogError() << "Error loading font";
    }
    f.setLineHeight(18.0f);
    f.setLetterSpacing(1.037);

    // Audio
    if (!heartbeatSound.loadSound("2.mp3")) {
        ofLogError() << "Error loading heartbeat sound";
    }
    heartbeatSound.setLoop(true);

    // Video
    if (!loadVideo()) {
        ofLogError() << "Error loading video";
    }
}

bool Configuration::Read() {
    // Read configuration or create default
    ofxXmlSettings xml;
    if (!xml.loadFile("configuration.xml")) {
        xml.setValue("configuration:Fullscreen", Fullscreen);
        xml.setValue("configuration:MinDistance", MinDistance);
        xml.setValue("configuration:MaxDistance", MaxDistance);
        xml.setValue("configuration:DeathZone", DeathZone);
        xml.setValue("configuration:RestartIntervalSeconds", RestartIntervalSeconds);
        xml.setValue("configuration:ActiveSerialPort", ActiveSerialPort);
        xml.setValue("configuration:StartingFramesPerSecond", StartingFramesPerSecond);
        xml.setValue("configuration:FinishingFramesPerSecond", FinishingFramesPerSecond);
        xml.setValue("configuration:StartingVolume", StartingVolume);
        xml.setValue("configuration:FinishingVolume", FinishingVolume);
        xml.setValue("configuration:StartingHeartBeatSpeed", StartingHeartBeatSpeed);
        xml.setValue("configuration:FinishingHeartBeatSpeed", FinishingHeartBeatSpeed);
        xml.setValue("configuration:FrameRate", FrameRate);
        xml.setValue("configuration:VideoFileName", VideoFileName);

        if (!xml.saveFile("configuration.xml")) {
            ofLogError() << "Error saving configuration file";
            return false;
        }
    } else {
        Fullscreen = xml.getValue("configuration:Fullscreen", Fullscreen);
        MinDistance = xml.getValue("configuration:MinDistance", MinDistance);
        MaxDistance = xml.getValue("configuration:MaxDistance", MaxDistance);
        DeathZone = xml.getValue("configuration:DeathZone", DeathZone);
        RestartIntervalSeconds = xml.getValue("configuration:RestartIntervalSeconds", RestartIntervalSeconds);
        ActiveSerialPort = xml.getValue("configuration:ActiveSerialPort", ActiveSerialPort);
        StartingFramesPerSecond = xml.getValue("configuration:StartingFramesPerSecond", StartingFramesPerSecond);
        FinishingFramesPerSecond = xml.getValue("configuration:FinishingFramesPerSecond", FinishingFramesPerSecond);
        StartingVolume = xml.getValue("configuration:StartingVolume", StartingVolume);
        FinishingVolume = xml.getValue("configuration:FinishingVolume", FinishingVolume);
        StartingHeartBeatSpeed = xml.getValue("configuration:StartingHeartBeatSpeed", StartingHeartBeatSpeed);
        FinishingHeartBeatSpeed = xml.getValue("configuration:FinishingHeartBeatSpeed", FinishingHeartBeatSpeed);
        FrameRate = xml.getValue("configuration:FrameRate", FrameRate);
        VideoFileName = xml.getValue("configuration:VideoFileName", VideoFileName);
    }

    return true;
}

bool GameStats::Read() {
    // Read game stats or create default
    ofxXmlSettings xml;
    if (!xml.loadFile("gamestats.xml")) {
        if (!Write()) {
            return false;
        }
    } else {
        Saves = xml.getValue("gamestats:Saves", Saves);
        Kills = xml.getValue("gamestats:Kills", Kills);
    }

    return true;
}

bool GameStats::Write() const {
    ofFile f(ofToDataPath("gamestats.xml"));
    f.moveTo("gamestats_backup.xml", false, true);

    ofxXmlSettings xml;
    xml.setValue("gamestats:Saves", Saves);
    xml.setValue("gamestats:Kills", Kills);
    return xml.saveFile("gamestats.xml");
}

void ofApp::update(){
    long now = ofGetElapsedTimeMillis();

    if (isPlaying()) {
        if (videoPlayer.getSpeed() == kForward) {
            if (videoPlayer.getCurrentFrame() >= frameForDistance()) {
                videoPlayer.setPaused(true);
            }
        } else if (videoPlayer.getSpeed() == kBack) {
            if (videoPlayer.getCurrentFrame() <= frameForDistance()) {
                videoPlayer.setPaused(true);
            }
        }
    }

    // Determine if user is now in the death zone
    if (!state.finishedAt && (currentDistance < configuration.MinDistance + configuration.DeathZone)) {
        ofLogNotice() << "Game finished with kill at " << now;

        eventLog << "killed=" << now << std::endl;

        state.finishedAt = now;
        state.saved = false;

        setDistance("killed", configuration.MinDistance);

        gameStats.Kills++;
        if (!gameStats.Write()) {
            ofLogError() << "Error writing game stats";
        }
    }

    // If save zone is active and user finds itself in it,
    // then declare the game saved and finish it.
    int saveZoneStartsAt = std::abs(configuration.MaxDistance - configuration.DeathZone);
    if (!state.finishedAt && state.saveZoneActive && currentDistance > saveZoneStartsAt) {
        ofLogNotice() << "Game finished with save at " << now;

        eventLog << "saved=" << now << std::endl;

        state.finishedAt = now;
        state.saved = true;

        setDistance("saved", configuration.MaxDistance);

        gameStats.Saves++;
        if (!gameStats.Write()) {
            ofLogError() << "Error writing game stats";
        }
    }

    // If user has moved out of save zone, and game is not finished
    // yet, activate save zone
    int moved = std::abs(configuration.MaxDistance - currentDistance);
    if (!state.finishedAt && moved > configuration.DeathZone) {
        state.saveZoneActive = true;
    }

    // Restart if needed
    if (state.finishedAt && (state.finishedAt < now - (configuration.RestartIntervalSeconds*1000))) {
        ofLogNotice() << "Game restarted";

        state = GameState();

        setDistance("restart", configuration.MaxDistance);

        if (!loadVideo()) {
            ofLogError() << "Error loading video after kill";
        }
        ofLogNotice() << "frame after resettting video player: " << videoPlayer.getCurrentFrame();

        eventLog << "started=" << now << std::endl;
    }

    // Read serial
    if (serialPort.isInitialized() && serialPort.available()) {
        char c = serialPort.readByte();
        if ('\n' == c) {
            std::string input = serialbuf.str();
            serialbuf.str("");
            ofLogNotice() << "Serial input: " << input << std::endl;

            if (state.finishedAt) {
                return;
            }

            if (isPlaying()) {
                return;
            }

            float f = ofToFloat(input);

            int prev = currentDistance;

            setDistance("Serial input", f);

            if (prev > currentDistance) {
                animateVideo(kForward);
            } else if (prev < currentDistance) {
                animateVideo(kBack);
            }
        } else {
            serialbuf << c;
        }
    }

    // Update visual
    int millis = ofMap(currentDistance,
                       configuration.MaxDistance,
                       configuration.MinDistance,
                       1000 / configuration.StartingFramesPerSecond,
                       1000 / configuration.FinishingFramesPerSecond);
    fps = 1000 / millis;

    // Update video
    videoPlayer.update();

    // Update audio
    if (!state.finishedAt) {
        if (!heartbeatSound.getIsPlaying()) {
            heartbeatSound.play();
        }
        heartbeatSound.setSpeed(ofMap(currentDistance,
                                      configuration.MaxDistance, configuration.MinDistance,
                                      configuration.StartingHeartBeatSpeed, configuration.FinishingHeartBeatSpeed));
    } else {
        if (heartbeatSound.getIsPlaying()) {
            heartbeatSound.stop();
        }
    }

    ofSoundUpdate();
}

// Frame for current distance
// Note that this is not the actual frame that will be animated.
// Instead will start to animate towards this frame.
int ofApp::frameForDistance() {
    return ofMap(currentDistance,
                 configuration.MinDistance,
                 configuration.MaxDistance,
                 videoPlayer.getTotalNumFrames(),
                 0);
}

void ofApp::draw(){
    int restartCountdownSeconds = 0;
    if (state.finishedAt) {
        long now = ofGetElapsedTimeMillis();
        int beenDeadSeconds = (now - state.finishedAt) / 1000;
        restartCountdownSeconds = configuration.RestartIntervalSeconds - beenDeadSeconds;
    }

    // Update HUD
    int y = 40;
    f.drawString("dist=" + ofToString(currentDistance), 10, y);
    f.drawString("f=" + ofToString(videoPlayer.getCurrentFrame()) + "/" + ofToString(videoPlayer.getTotalNumFrames()),
                 160, y);
    f.drawString("dest.f=" + ofToString(frameForDistance()), 300, y);
    f.drawString("fps=" + ofToString(fps), 460, y);
    f.drawString("sv=" + ofToString(gameStats.Saves), 560, y);
    f.drawString("kl=" + ofToString(gameStats.Kills), 660, y);
    f.drawString("rs=" + ofToString(restartCountdownSeconds), 760, y);
    f.drawString("vid=" + ofToString(isPlaying()), 860, y);

    const int margin = 50;

    // Draw video
    if (state.finishedAt && !isPlaying()) {
        if (state.saved) {
            ofSetHexColor(0xFFFFFF);
        } else {
            ofSetHexColor(0x000000);
        }
        ofRect(0, margin, ofGetWindowWidth(), ofGetWindowHeight() - margin);
        ofFill();
        if (!state.saved) {
            ofSetHexColor(0xFFFFFF);
        } else {
            ofSetHexColor(0x000000);
        }
        std::string text("");
        if (state.saved) {
            text = "LIFES SAVED: " + ofToString(gameStats.Saves);
        } else {
            text = "TOTAL KILLS: " + ofToString(gameStats.Kills);
        }
        f.drawString(text,
                     ofGetWindowWidth() / 2 - 100,
                     ofGetWindowHeight() / 2);

        return;
    }

    ofSetHexColor(0xFFFFFF);
    ofFill();
    videoPlayer.draw(0, margin, ofGetWindowWidth(), ofGetWindowHeight() - margin);
}

void ofApp::keyPressed(int key){
    ofLogNotice() << "keyPressed key=" << key;

    if (state.finishedAt) {
        return;
    }

    if (isPlaying()) {
        return;
    }

    const int kMinStep = 100;

    if (OF_KEY_UP == key) {
        // distance decreases as viewer approaches
        int n = currentDistance - kMinStep - int(ofRandom(100));

        setDistance("keyboard up", n);

        animateVideo(kForward);
    } else if (OF_KEY_DOWN == key) {
        // distance incrases as viewer steps back
        int n = currentDistance + kMinStep + int(ofRandom(100));

        setDistance("keyboard down", n);

        animateVideo(kBack);
    }
}

void ofApp::setDistance(const std::string reason, const int value) {
    currentDistance = ofClamp(value, configuration.MinDistance, configuration.MaxDistance);
}
<|endoftext|>


<commit_before>#include "Image.h"
#include "Type.h"
#include "Util.h"
#include "Uniform.h"
#include "Var.h"
#include <assert.h>
#include "../src/buffer.h"

namespace Halide {
    struct DynImage::Contents {
        Contents(const Type &t, int a);
        Contents(const Type &t, int a, int b);
        Contents(const Type &t, int a, int b, int c);
        Contents(const Type &t, int a, int b, int c, int d);
        Contents(const Type &t, std::vector<int> sizes);
        ~Contents();

        void allocate(size_t bytes);

        Type type;
        std::vector<int> size, stride;
        const std::string name;
        unsigned char *data;
        std::vector<unsigned char> host_buffer;
        buffer_t buf;
        mutable void (*copyToHost)(buffer_t*);
        mutable void (*freeBuffer)(buffer_t*);
    };

    DynImage::Contents::Contents(const Type &t, int a) :
        type(t), size(vec(a)), stride(vec(1)), name(uniqueName('i')), copyToHost(NULL), freeBuffer(NULL) {
        assert(a > 0 && "Images must have positive sizes\n");
        allocate(a * (t.bits/8));
    }

    DynImage::Contents::Contents(const Type &t, int a, int b) :
        type(t), size(vec(a, b)), stride(vec(1, a)), name(uniqueName('i')), copyToHost(NULL), freeBuffer(NULL) {
        assert(a > 0 && b > 0 && "Images must have positive sizes");
        allocate(a * b * (t.bits/8));
    }

    DynImage::Contents::Contents(const Type &t, int a, int b, int c) :
        type(t), size(vec(a, b, c)), stride(vec(1, a, a*b)), name(uniqueName('i')), copyToHost(NULL), freeBuffer(NULL) {
        assert(a > 0 && b > 0 && c > 0 && "Images must have positive sizes");
        allocate(a * b * c * (t.bits/8));
    }

    DynImage::Contents::Contents(const Type &t, int a, int b, int c, int d) :
        type(t), size(vec(a, b, c, d)), stride(vec(1, a, a*b, a*b*c)), name(uniqueName('i')), copyToHost(NULL), freeBuffer(NULL) {
        assert(a > 0 && b > 0 && c > 0 && d > 0 && "Images must have positive sizes");
        allocate(a * b * c * d * (t.bits/8));
    }

    DynImage::Contents::Contents(const Type &t, std::vector<int> sizes) :
        type(t), size(sizes), stride(sizes.size()), name(uniqueName('i')), copyToHost(NULL), freeBuffer(NULL) {

        size_t total = 1;
        for (size_t i = 0; i < sizes.size(); i++) {
            assert(sizes[i] > 0 && "Images must have positive sizes");
            stride[i] = total;
            total *= sizes[i];
        }

        allocate(total * (t.bits/8));
    }

    DynImage::Contents::~Contents() {
        if (freeBuffer) {
            fprintf(stderr, "freeBuffer %p\n", &buf);
            freeBuffer(&buf);
        }
    }

    void DynImage::Contents::allocate(size_t bytes) {
        host_buffer.resize(bytes+32);
        data = &(host_buffer[0]);
        unsigned char offset = ((size_t)data) & 0x1f;
        if (offset) {
            data += 32 - offset;
        }

        assert(size.size() <= 4);
        buf.host = data;
        buf.dev = 0;
        buf.host_dirty = false;
        buf.dev_dirty = false;
        buf.dims[0] = buf.dims[1] = buf.dims[2] = buf.dims[3] = 1;
        for (size_t i = 0; i < size.size(); i++) {
            buf.dims[i] = size[i];
        }
        buf.elem_size = type.bits/8;
    }

    DynImage::DynImage(const Type &t, int a) : contents(new Contents(t, a)) {}

    DynImage::DynImage(const Type &t, int a, int b) : contents(new Contents(t, a, b)) {}

    DynImage::DynImage(const Type &t, int a, int b, int c) : contents(new Contents(t, a, b, c)) {}

    DynImage::DynImage(const Type &t, int a, int b, int c, int d) : contents(new Contents(t, a, b, c, d)) {}
    DynImage::DynImage(const Type &t, std::vector<int> sizes) : contents(new Contents(t, sizes)) {}

    DynImage::DynImage(const DynImage &other) : contents(other.contents) {}

    const Type &DynImage::type() const {
        return contents->type;
    }

    int DynImage::stride(int i) const {
        if (i >= dimensions()) {
            fprintf(stderr,
                    "ERROR: accessing stride of dim %d of %d-dimensional image %s\n",
                    i, dimensions(), name().c_str());
            assert(i < dimensions());
        }
        return contents->stride[i];
    }

    int DynImage::size(int i) const {
        if (i >= dimensions()) {
            fprintf(stderr,
                    "ERROR: accessing size of dim %d of %d-dimensional image %s\n",
                    i, dimensions(), name().c_str());
            assert(i < dimensions());
        }
        return contents->size[i];
    }

    int DynImage::dimensions() const {
        return contents->size.size();
    }

    unsigned char *DynImage::data() const {
        return contents->data;
    }

    const std::string &DynImage::name() const {
        return contents->name;
    }

    buffer_t* DynImage::buffer() const {
        return &contents->buf;
    }

    void DynImage::setRuntimeHooks(void (*copyToHostFn)(buffer_t *), void (*freeFn)(buffer_t *)) const {
        contents->copyToHost = copyToHostFn;
        contents->freeBuffer = freeFn;
    }

    void DynImage::copyToHost() const {
        // printf("%p->copyToHost...", this);
        if (contents->buf.dev_dirty) {
            // printf("runs\n");
            assert(contents->copyToHost);
            contents->copyToHost(&contents->buf);
        } else {
            // printf("skipped - not dirty\n");
        }
    }

    void DynImage::copyToDev() const {
        if (contents->buf.host_dirty) {
            // TODO
            assert(false);
        }
    }

    void DynImage::markHostDirty() const {
        assert(!contents->buf.dev_dirty);
        contents->buf.host_dirty = true;
    }

    void DynImage::markDevDirty() const {
        assert(!contents->buf.host_dirty);
        contents->buf.dev_dirty = true;
    }

    bool DynImage::hostDirty() const {
        return contents->buf.host_dirty;
    }
    bool DynImage::devDirty() const {
        return contents->buf.dev_dirty;
    }

    Expr DynImage::operator()(const Expr &a) const {
        return ImageRef(*this, vec(a));
    }

    Expr DynImage::operator()(const Expr &a, const Expr &b) const {
        return ImageRef(*this, vec(a, b));
    }

    Expr DynImage::operator()(const Expr &a, const Expr &b, const Expr &c) const {
        return ImageRef(*this, vec(a, b, c));
    }

    Expr DynImage::operator()(const Expr &a, const Expr &b, const Expr &c, const Expr &d) const {
        return ImageRef(*this, vec(a, b, c, d));
    }

    struct UniformImage::Contents {
        Contents(const Type &t, int dims) :
            t(t), name(uniqueName('m')) {
            sizes.resize(dims);
            for (int i = 0; i < dims; i++) {
                sizes[i] = Var(std::string(".") + name + ".dim." + int_to_str(i), false);
            }
        }

        Contents(const Type &t, int dims, const std::string &name_) :
            t(t), name(sanitizeName(name_)) {
            sizes.resize(dims);
            for (int i = 0; i < dims; i++) {
                sizes[i] = Var(std::string(".") + name + ".dim." + int_to_str(i), false);
            }
        }

        Type t;
        shared_ptr<DynImage> image;
        std::vector<Expr> sizes;
        const std::string name;
    };

    UniformImage::UniformImage(const Type &t, int dims) :
        contents(new Contents(t, dims)) {
        for (int i = 0; i < dims; i++) {
            contents->sizes[i].child(*this);
        }
    }

    UniformImage::UniformImage(const Type &t, int dims, const std::string &name) :
        contents(new Contents(t, dims, sanitizeName(name))) {
        for (int i = 0; i < dims; i++) {
            contents->sizes[i].child(*this);
        }
    }

    UniformImage::UniformImage(const UniformImage &other) :
        contents(other.contents) {
    }

    void UniformImage::operator=(const DynImage &image) {
        assert(image.type() == contents->t);
        assert((size_t)image.dimensions() == contents->sizes.size());
        contents->image.reset(new DynImage(image));
    }

    const DynImage &UniformImage::boundImage() const {
        assert(contents->image);
        return *(contents->image);
    }

    unsigned char *UniformImage::data() const {
        assert(contents->image);
        return contents->image->data();
    }

    bool UniformImage::operator==(const UniformImage &other) const {
        return contents == other.contents;
    }

    Expr UniformImage::operator()(const Expr &a) const {
        return UniformImageRef(*this, vec(a));
    }

    Expr UniformImage::operator()(const Expr &a, const Expr &b) const {
        return UniformImageRef(*this, vec(a, b));
    }

    Expr UniformImage::operator()(const Expr &a, const Expr &b, const Expr &c) const {
        return UniformImageRef(*this, vec(a, b, c));
    }

    Expr UniformImage::operator()(const Expr &a, const Expr &b, const Expr &c, const Expr &d) const {
        return UniformImageRef(*this, vec(a, b, c, d));
    }

    Type UniformImage::type() const {
        return contents->t;
    }

    const std::string &UniformImage::name() const {
        return contents->name;
    }

    int UniformImage::dimensions() const {
        return contents->sizes.size();
    }

    const Expr &UniformImage::size(int i) const {
        return contents->sizes[i];
    }

}
<commit_msg>Change UniformImage sizes to avoid spurious vars<commit_after>#include "Image.h"
#include "Type.h"
#include "Util.h"
#include "Uniform.h"
#include "Var.h"
#include <assert.h>
#include "../src/buffer.h"

namespace Halide {
    struct DynImage::Contents {
        Contents(const Type &t, int a);
        Contents(const Type &t, int a, int b);
        Contents(const Type &t, int a, int b, int c);
        Contents(const Type &t, int a, int b, int c, int d);
        Contents(const Type &t, std::vector<int> sizes);
        ~Contents();

        void allocate(size_t bytes);

        Type type;
        std::vector<int> size, stride;
        const std::string name;
        unsigned char *data;
        std::vector<unsigned char> host_buffer;
        buffer_t buf;
        mutable void (*copyToHost)(buffer_t*);
        mutable void (*freeBuffer)(buffer_t*);
    };

    DynImage::Contents::Contents(const Type &t, int a) :
        type(t), size(vec(a)), stride(vec(1)), name(uniqueName('i')), copyToHost(NULL), freeBuffer(NULL) {
        assert(a > 0 && "Images must have positive sizes\n");
        allocate(a * (t.bits/8));
    }

    DynImage::Contents::Contents(const Type &t, int a, int b) :
        type(t), size(vec(a, b)), stride(vec(1, a)), name(uniqueName('i')), copyToHost(NULL), freeBuffer(NULL) {
        assert(a > 0 && b > 0 && "Images must have positive sizes");
        allocate(a * b * (t.bits/8));
    }

    DynImage::Contents::Contents(const Type &t, int a, int b, int c) :
        type(t), size(vec(a, b, c)), stride(vec(1, a, a*b)), name(uniqueName('i')), copyToHost(NULL), freeBuffer(NULL) {
        assert(a > 0 && b > 0 && c > 0 && "Images must have positive sizes");
        allocate(a * b * c * (t.bits/8));
    }

    DynImage::Contents::Contents(const Type &t, int a, int b, int c, int d) :
        type(t), size(vec(a, b, c, d)), stride(vec(1, a, a*b, a*b*c)), name(uniqueName('i')), copyToHost(NULL), freeBuffer(NULL) {
        assert(a > 0 && b > 0 && c > 0 && d > 0 && "Images must have positive sizes");
        allocate(a * b * c * d * (t.bits/8));
    }

    DynImage::Contents::Contents(const Type &t, std::vector<int> sizes) :
        type(t), size(sizes), stride(sizes.size()), name(uniqueName('i')), copyToHost(NULL), freeBuffer(NULL) {

        size_t total = 1;
        for (size_t i = 0; i < sizes.size(); i++) {
            assert(sizes[i] > 0 && "Images must have positive sizes");
            stride[i] = total;
            total *= sizes[i];
        }

        allocate(total * (t.bits/8));
    }

    DynImage::Contents::~Contents() {
        if (freeBuffer) {
            fprintf(stderr, "freeBuffer %p\n", &buf);
            freeBuffer(&buf);
        }
    }

    void DynImage::Contents::allocate(size_t bytes) {
        host_buffer.resize(bytes+32);
        data = &(host_buffer[0]);
        unsigned char offset = ((size_t)data) & 0x1f;
        if (offset) {
            data += 32 - offset;
        }

        assert(size.size() <= 4);
        buf.host = data;
        buf.dev = 0;
        buf.host_dirty = false;
        buf.dev_dirty = false;
        buf.dims[0] = buf.dims[1] = buf.dims[2] = buf.dims[3] = 1;
        for (size_t i = 0; i < size.size(); i++) {
            buf.dims[i] = size[i];
        }
        buf.elem_size = type.bits/8;
    }

    DynImage::DynImage(const Type &t, int a) : contents(new Contents(t, a)) {}

    DynImage::DynImage(const Type &t, int a, int b) : contents(new Contents(t, a, b)) {}

    DynImage::DynImage(const Type &t, int a, int b, int c) : contents(new Contents(t, a, b, c)) {}

    DynImage::DynImage(const Type &t, int a, int b, int c, int d) : contents(new Contents(t, a, b, c, d)) {}
    DynImage::DynImage(const Type &t, std::vector<int> sizes) : contents(new Contents(t, sizes)) {}

    DynImage::DynImage(const DynImage &other) : contents(other.contents) {}

    const Type &DynImage::type() const {
        return contents->type;
    }

    int DynImage::stride(int i) const {
        if (i >= dimensions()) {
            fprintf(stderr,
                    "ERROR: accessing stride of dim %d of %d-dimensional image %s\n",
                    i, dimensions(), name().c_str());
            assert(i < dimensions());
        }
        return contents->stride[i];
    }

    int DynImage::size(int i) const {
        if (i >= dimensions()) {
            fprintf(stderr,
                    "ERROR: accessing size of dim %d of %d-dimensional image %s\n",
                    i, dimensions(), name().c_str());
            assert(i < dimensions());
        }
        return contents->size[i];
    }

    int DynImage::dimensions() const {
        return contents->size.size();
    }

    unsigned char *DynImage::data() const {
        return contents->data;
    }

    const std::string &DynImage::name() const {
        return contents->name;
    }

    buffer_t* DynImage::buffer() const {
        return &contents->buf;
    }

    void DynImage::setRuntimeHooks(void (*copyToHostFn)(buffer_t *), void (*freeFn)(buffer_t *)) const {
        contents->copyToHost = copyToHostFn;
        contents->freeBuffer = freeFn;
    }

    void DynImage::copyToHost() const {
        // printf("%p->copyToHost...", this);
        if (contents->buf.dev_dirty) {
            // printf("runs\n");
            assert(contents->copyToHost);
            contents->copyToHost(&contents->buf);
        } else {
            // printf("skipped - not dirty\n");
        }
    }

    void DynImage::copyToDev() const {
        if (contents->buf.host_dirty) {
            // TODO
            assert(false);
        }
    }

    void DynImage::markHostDirty() const {
        assert(!contents->buf.dev_dirty);
        contents->buf.host_dirty = true;
    }

    void DynImage::markDevDirty() const {
        assert(!contents->buf.host_dirty);
        contents->buf.dev_dirty = true;
    }

    bool DynImage::hostDirty() const {
        return contents->buf.host_dirty;
    }
    bool DynImage::devDirty() const {
        return contents->buf.dev_dirty;
    }

    Expr DynImage::operator()(const Expr &a) const {
        return ImageRef(*this, vec(a));
    }

    Expr DynImage::operator()(const Expr &a, const Expr &b) const {
        return ImageRef(*this, vec(a, b));
    }

    Expr DynImage::operator()(const Expr &a, const Expr &b, const Expr &c) const {
        return ImageRef(*this, vec(a, b, c));
    }

    Expr DynImage::operator()(const Expr &a, const Expr &b, const Expr &c, const Expr &d) const {
        return ImageRef(*this, vec(a, b, c, d));
    }

    extern MLVal makeVar(const MLVal& name);
    static Expr makeRawVar(std::string name) {
        return Expr(makeVar(name), Int(32));
    }

    struct UniformImage::Contents {
        Contents(const Type &t, int dims) :
            t(t), name(uniqueName('m')) {
            sizes.resize(dims);
            for (int i = 0; i < dims; i++) {
                sizes[i] = makeRawVar(std::string(".") + name + ".dim." + int_to_str(i));
            }
        }

        Contents(const Type &t, int dims, const std::string &name_) :
            t(t), name(sanitizeName(name_)) {
            sizes.resize(dims);
            for (int i = 0; i < dims; i++) {
                sizes[i] = makeRawVar(std::string(".") + name + ".dim." + int_to_str(i));
            }
        }

        Type t;
        shared_ptr<DynImage> image;
        std::vector<Expr> sizes;
        const std::string name;
    };

    UniformImage::UniformImage(const Type &t, int dims) :
        contents(new Contents(t, dims)) {
        for (int i = 0; i < dims; i++) {
            contents->sizes[i].child(*this);
        }
    }

    UniformImage::UniformImage(const Type &t, int dims, const std::string &name) :
        contents(new Contents(t, dims, sanitizeName(name))) {
        for (int i = 0; i < dims; i++) {
            contents->sizes[i].child(*this);
        }
    }

    UniformImage::UniformImage(const UniformImage &other) :
        contents(other.contents) {
    }

    void UniformImage::operator=(const DynImage &image) {
        assert(image.type() == contents->t);
        assert((size_t)image.dimensions() == contents->sizes.size());
        contents->image.reset(new DynImage(image));
    }

    const DynImage &UniformImage::boundImage() const {
        assert(contents->image);
        return *(contents->image);
    }

    unsigned char *UniformImage::data() const {
        assert(contents->image);
        return contents->image->data();
    }

    bool UniformImage::operator==(const UniformImage &other) const {
        return contents == other.contents;
    }

    Expr UniformImage::operator()(const Expr &a) const {
        return UniformImageRef(*this, vec(a));
    }

    Expr UniformImage::operator()(const Expr &a, const Expr &b) const {
        return UniformImageRef(*this, vec(a, b));
    }

    Expr UniformImage::operator()(const Expr &a, const Expr &b, const Expr &c) const {
        return UniformImageRef(*this, vec(a, b, c));
    }

    Expr UniformImage::operator()(const Expr &a, const Expr &b, const Expr &c, const Expr &d) const {
        return UniformImageRef(*this, vec(a, b, c, d));
    }

    Type UniformImage::type() const {
        return contents->t;
    }

    const std::string &UniformImage::name() const {
        return contents->name;
    }

    int UniformImage::dimensions() const {
        return contents->sizes.size();
    }

    const Expr &UniformImage::size(int i) const {
        return contents->sizes[i];
    }

}
<|endoftext|>


<commit_before>#pragma once
#include <algorithm>
#include <type_traits>
#include <vector>

#include "base/helpers.hpp"
#include "maths.hpp"
#include "range/ranges.hpp"
#include "queue.hpp"

enum GraphType {
	Weighted = 1
};

template<size_t MASK>
struct is_weighted
{
	/// caide keep
	static constexpr bool value = (MASK & GraphType::Weighted) != 0;
};

template<typename T = long long, size_t MASK = 0>
class Graph {
public:
	using EdgesList = std::vector<size_t>;

	class Edge {
	public:
		constexpr explicit Edge(const std::vector<size_t>& from, const std::vector<size_t>& to,
			const std::vector<T>& weight, const size_t index) :
			from_(from), to_(to), weight_(weight), index_(index) {}

		size_t from() const {
			return from_[index_];
		}

		size_t to() const {
			return to_[index_];
		}

		template<size_t Mask = MASK, typename std::enable_if<is_weighted<Mask>::value>::type* = nullptr>
		T weight() const {
			return weight_[index_];
		}

		constexpr size_t id() const {
			return index_;
		}

		void set_index(const size_t index) {
			index_ = index;
		}

		constexpr Edge reversed() const {
			return Edge(to_, from_, weight_, index_);
		}

	private:
		const std::vector<size_t>& from_;
		const std::vector<size_t>& to_;
		const std::vector<T>& weight_;
		size_t index_;

	};

	template<typename Range>
	class EdgesHolder {
	public:

		template<typename BaseConstIterator>
		class EdgeConstIterator : public BaseConstIterator {
		public:
			using value_type = Edge;
			using pointer = const value_type*;
			using const_reference = const value_type&;

			constexpr explicit EdgeConstIterator(BaseConstIterator it, const std::vector<size_t>& from,
				const std::vector<size_t>& to, const std::vector<T>& weight) :
				BaseConstIterator(it), cur_edge_(from, to, weight, 0) {}

			pointer operator->() {
				return addressof(operator*());
			}

			const_reference operator*() {
				const typename BaseConstIterator::value_type index = this->BaseConstIterator::operator*();
				cur_edge_.set_index(index);
				return cur_edge_;
			}

		private:
			Edge cur_edge_;

		};

		using const_iterator = EdgeConstIterator<typename Range::const_iterator>;
		using value_type = typename const_iterator::value_type;

		constexpr explicit EdgesHolder(const Range& range, const std::vector<size_t>& from,
			const std::vector<size_t>& to, const std::vector<T>& weight) :
			begin_(range.begin(), from, to, weight), end_(range.end(), from, to, weight) {}

		constexpr const_iterator begin() const {
			return begin_;
		}

		constexpr const_iterator end() const {
			return end_;
		}

		constexpr size_t size() const {
			return end_ - begin_;
		}

	private:
		const const_iterator begin_;
		const const_iterator end_;

	};

	Graph() = default;

	virtual ~Graph() {
		clear();
	}

	void init(const size_t vertices_count) {
		clear();
		vertices_count_ = vertices_count;
		edges_.resize(vertices_count_);
	}

	IntegerRange<size_t> vertices() const {
		return range(vertices_count_);
	}

	IntegerRange<size_t>::const_iterator begin() const {
		return vertices().begin();
	}

	IntegerRange<size_t>::const_iterator end() const {
		return vertices().end();
	}

	EdgesHolder<EdgesList> edges(const size_t vertex) const {
		return EdgesHolder<EdgesList>(edges_[vertex], from_, to_, weight_);
	}

	EdgesHolder<IntegerRange<size_t>> edges() const {
		return EdgesHolder<IntegerRange<size_t>>(range(from_.size()), from_, to_, weight_);
	}

	void clear();

	size_t vertices_count() const {
		return vertices_count_;
	}

	size_t edges_count() const {
		return from_.size();
	}

	size_t from(const size_t index) const {
		return from_[index];
	}

	size_t to(const size_t index) const {
		return to_[index];
	}

	template<size_t Mask = MASK, typename std::enable_if<is_weighted<Mask>::value>::type* = nullptr>
	T weight(const size_t index) const {
		return weight_[index];
	}

	template<size_t Mask = MASK, typename std::enable_if<is_weighted<Mask>::value>::type* = nullptr>
	T weight_infinity() const {
		return std::numeric_limits<T>::max() / 2;
	}

	template<size_t Mask = MASK, typename std::enable_if<!is_weighted<Mask>::value>::type* = nullptr>
	void add_directed_edge(const size_t from, const size_t to) {
		push_edge(from, to);
	}

	template<size_t Mask = MASK, typename std::enable_if<is_weighted<Mask>::value>::type* = nullptr>
	void add_directed_edge(const size_t from, const size_t to, const T weight) {
		weight_.emplace_back(weight);
		push_edge(from, to);
	}

	template<size_t Mask = MASK, typename std::enable_if<!is_weighted<Mask>::value>::type* = nullptr>
	void add_directed_edge(const Edge& edge) {
		add_directed_edge(edge.from(), edge.to());
	}

	template<size_t Mask = MASK, typename std::enable_if<is_weighted<Mask>::value>::type* = nullptr>
	void add_directed_edge(const Edge& edge) {
		add_directed_edge(edge.from(), edge.to(), edge.weight());
	}

	bool is_sparse() const {
		return vertices_count_ == 0 || sqr(static_cast<long long>(vertices_count_)) >= (edges_count() << 4);
	}

	size_t find_vertex_with_max_degree() const;

	bool is_bipartite(std::vector<size_t>& partition) const;

	template<size_t Mask = MASK, typename std::enable_if<is_weighted<Mask>::value>::type* = nullptr>
	std::vector<std::vector<T>> floyd() const {
		auto dist = make_vector<T>(vertices_count_, vertices_count_, weight_infinity());
		for (const auto v : vertices()) {
			dist[v][v] = 0;
		}
		for (const auto& edge : edges()) {
			umin(dist[edge.from()][edge.to()], edge.weight());
		}
		for (const auto k : vertices()) {
			for (const auto i : vertices()) {
				for (const auto j : vertices()) {
					umin(dist[i][j], dist[i][k] + dist[k][j]);
				}
			}
		}
		return dist;
	}

	template<size_t Mask = MASK, typename std::enable_if<is_weighted<Mask>::value>::type* = nullptr>
	void dijkstra(const size_t start_vertex, std::vector<T>* distance, std::vector<size_t>* last_edge = nullptr) const {
		if (is_sparse() && false) {
			sparse_dijkstra(start_vertex, distance, last_edge);
		} else {
			dense_dijkstra(start_vertex, distance, last_edge);
		}
	}

protected:
	void push_edge(const size_t from, const size_t to) {
		const size_t edge_id = from_.size();
		from_.emplace_back(from);
		to_.emplace_back(to);
		edges_[from].emplace_back(edge_id);
	}

	std::vector<EdgesList> edges_;
	std::vector<size_t> from_;
	std::vector<size_t> to_;
	std::vector<T> weight_;

	size_t vertices_count_;

private:

	template<size_t Mask = MASK, typename std::enable_if<is_weighted<Mask>::value>::type* = nullptr>
	void sparse_dijkstra(const size_t start_vertex, std::vector<T>* distance, std::vector<size_t>* last_edge) const {
		std::vector<T> dist(vertices_count_, weight_infinity());
		std::vector<size_t> last(vertices_count_, std::numeric_limits<size_t>::max());
		dist[start_vertex] = 0;
		using QueueNode = std::pair<T, size_t>;
		std::priority_queue<QueueNode> q;
		q.emplace(0, start_vertex);
		while (!q.empty()) {
			const QueueNode node = q.top();
			q.pop();
			const T len = -node.first;
			const size_t vertex = node.second;
			if (len > dist[vertex]) {
				continue;
			}
			for (const auto& it : edges(vertex)) {
				const T new_dist = len + it.weight();
				const size_t to_vertex = it.to();
				if (umin(dist[to_vertex], new_dist)) {
					q.push(std::make_pair(-new_dist, to_vertex));
					last[to_vertex] = it.id();
				}
			}
		}
		distance->swap(dist);
		if (last_edge != nullptr) {
			last_edge->swap(last);
		}
	}

	template<size_t Mask = MASK, typename std::enable_if<is_weighted<Mask>::value>::type* = nullptr>
	void dense_dijkstra(const size_t start_vertex, std::vector<T>* distance, std::vector<size_t>* last_edge) const {
		std::vector<bool> used(vertices_count_);
		std::vector<T> dist(vertices_count_, weight_infinity());
		std::vector<size_t> last(vertices_count_, std::numeric_limits<size_t>::max());
		dist[start_vertex] = 0;
		for (size_t iter = 0; iter < vertices_count_; ++iter) {
			size_t vertex = std::numeric_limits<size_t>::max();
			T min_dist = weight_infinity();
			for (const size_t v : vertices()) {
				if (!used[v] && umin(min_dist, dist[v])) {
					min_dist = dist[v];
					vertex = v;
				}
			}
			if (vertex == std::numeric_limits<size_t>::max()) {
				break;
			}
			used[vertex] = true;
			for (const auto& it : edges(vertex)) {
				const size_t to_vertex = it.to();
				const T len = min_dist + it.weight();
				if (!used[to_vertex] && umin(dist[to_vertex], len)) {
					dist[to_vertex] = len;
					last[to_vertex] = it.id();
				}
			}
		}
		distance->swap(dist);
		if (last_edge != nullptr) {
			last_edge->swap(last);
		}
	}

};

template<typename T, size_t MASK>
void Graph<T, MASK>::clear() {
	vertices_count_ = 0;
	edges_.clear();
	from_.clear();
	to_.clear();
	weight_.clear();
}

template<typename T, size_t MASK>
size_t Graph<T, MASK>::find_vertex_with_max_degree() const {
	const auto iter = std::max_element(edges_.begin(), edges_.end(),
		[](const EdgesList& lhs, const EdgesList& rhs) {
		return lhs.size() < rhs.size();
	});
	return static_cast<size_t>(std::distance(edges_.begin(), iter));
}

template<typename T, size_t MASK>
bool Graph<T, MASK>::is_bipartite(std::vector<size_t>& partition) const {
	const size_t kNone = std::numeric_limits<size_t>::max();
	partition.assign(vertices_count_, kNone);
	Queue<size_t> q(vertices_count_);
	for (size_t i = 0; i < vertices_count_; ++i) {
		if (partition[i] == kNone) {
			q.clear();
			q.push(i);
			partition[i] = 0;
			while (!q.empty()) {
				const size_t vertex = q.pop_front();
				const size_t color = partition[vertex];
				for (const auto& it : edges(vertex)) {
					const size_t to_vertex = it.to();
					if (partition[to_vertex] == kNone) {
						partition[to_vertex] = color ^ 1;
						q.push(to_vertex);
						continue;
					}
					if (partition[to_vertex] == color) {
						return false;
					}
				}
			}
		}
	}
	return true;
}
<commit_msg>Implemented dijkstra shortest path search algorithm.<commit_after>#pragma once
#include <algorithm>
#include <type_traits>
#include <vector>

#include "base/helpers.hpp"
#include "maths.hpp"
#include "range/ranges.hpp"
#include "queue.hpp"

enum GraphType {
	Weighted = 1
};

template<size_t MASK>
struct is_weighted
{
	/// caide keep
	static constexpr bool value = (MASK & GraphType::Weighted) != 0;
};

template<typename T = long long, size_t MASK = 0>
class Graph {
public:
	using EdgesList = std::vector<size_t>;

	class Edge {
	public:
		constexpr explicit Edge(const std::vector<size_t>& from, const std::vector<size_t>& to,
			const std::vector<T>& weight, const size_t index) :
			from_(from), to_(to), weight_(weight), index_(index) {}

		size_t from() const {
			return from_[index_];
		}

		size_t to() const {
			return to_[index_];
		}

		template<size_t Mask = MASK, typename std::enable_if<is_weighted<Mask>::value>::type* = nullptr>
		T weight() const {
			return weight_[index_];
		}

		constexpr size_t id() const {
			return index_;
		}

		void set_index(const size_t index) {
			index_ = index;
		}

		constexpr Edge reversed() const {
			return Edge(to_, from_, weight_, index_);
		}

	private:
		const std::vector<size_t>& from_;
		const std::vector<size_t>& to_;
		const std::vector<T>& weight_;
		size_t index_;

	};

	template<typename Range>
	class EdgesHolder {
	public:

		template<typename BaseConstIterator>
		class EdgeConstIterator : public BaseConstIterator {
		public:
			using value_type = Edge;
			using pointer = const value_type*;
			using const_reference = const value_type&;

			constexpr explicit EdgeConstIterator(BaseConstIterator it, const std::vector<size_t>& from,
				const std::vector<size_t>& to, const std::vector<T>& weight) :
				BaseConstIterator(it), cur_edge_(from, to, weight, 0) {}

			pointer operator->() {
				return addressof(operator*());
			}

			const_reference operator*() {
				const typename BaseConstIterator::value_type index = this->BaseConstIterator::operator*();
				cur_edge_.set_index(index);
				return cur_edge_;
			}

		private:
			Edge cur_edge_;

		};

		using const_iterator = EdgeConstIterator<typename Range::const_iterator>;
		using value_type = typename const_iterator::value_type;

		constexpr explicit EdgesHolder(const Range& range, const std::vector<size_t>& from,
			const std::vector<size_t>& to, const std::vector<T>& weight) :
			begin_(range.begin(), from, to, weight), end_(range.end(), from, to, weight) {}

		constexpr const_iterator begin() const {
			return begin_;
		}

		constexpr const_iterator end() const {
			return end_;
		}

		constexpr size_t size() const {
			return end_ - begin_;
		}

	private:
		const const_iterator begin_;
		const const_iterator end_;

	};

	Graph() = default;

	virtual ~Graph() {
		clear();
	}

	void init(const size_t vertices_count) {
		clear();
		vertices_count_ = vertices_count;
		edges_.resize(vertices_count_);
	}

	IntegerRange<size_t> vertices() const {
		return range(vertices_count_);
	}

	IntegerRange<size_t>::const_iterator begin() const {
		return vertices().begin();
	}

	IntegerRange<size_t>::const_iterator end() const {
		return vertices().end();
	}

	EdgesHolder<EdgesList> edges(const size_t vertex) const {
		return EdgesHolder<EdgesList>(edges_[vertex], from_, to_, weight_);
	}

	EdgesHolder<IntegerRange<size_t>> edges() const {
		return EdgesHolder<IntegerRange<size_t>>(range(from_.size()), from_, to_, weight_);
	}

	void clear();

	size_t vertices_count() const {
		return vertices_count_;
	}

	size_t edges_count() const {
		return from_.size();
	}

	size_t from(const size_t index) const {
		return from_[index];
	}

	size_t to(const size_t index) const {
		return to_[index];
	}

	template<size_t Mask = MASK, typename std::enable_if<is_weighted<Mask>::value>::type* = nullptr>
	T weight(const size_t index) const {
		return weight_[index];
	}

	template<size_t Mask = MASK, typename std::enable_if<is_weighted<Mask>::value>::type* = nullptr>
	T weight_infinity() const {
		return std::numeric_limits<T>::max() / 2;
	}

	template<size_t Mask = MASK, typename std::enable_if<!is_weighted<Mask>::value>::type* = nullptr>
	void add_directed_edge(const size_t from, const size_t to) {
		push_edge(from, to);
	}

	template<size_t Mask = MASK, typename std::enable_if<is_weighted<Mask>::value>::type* = nullptr>
	void add_directed_edge(const size_t from, const size_t to, const T weight) {
		weight_.emplace_back(weight);
		push_edge(from, to);
	}

	template<size_t Mask = MASK, typename std::enable_if<!is_weighted<Mask>::value>::type* = nullptr>
	void add_directed_edge(const Edge& edge) {
		add_directed_edge(edge.from(), edge.to());
	}

	template<size_t Mask = MASK, typename std::enable_if<is_weighted<Mask>::value>::type* = nullptr>
	void add_directed_edge(const Edge& edge) {
		add_directed_edge(edge.from(), edge.to(), edge.weight());
	}

	bool is_sparse() const {
		return vertices_count_ == 0 || sqr(static_cast<long long>(vertices_count_)) >= (edges_count() << 4);
	}

	size_t find_vertex_with_max_degree() const;

	bool is_bipartite(std::vector<size_t>& partition) const;

	template<size_t Mask = MASK, typename std::enable_if<is_weighted<Mask>::value>::type* = nullptr>
	std::vector<std::vector<T>> floyd() const {
		auto dist = make_vector<T>(vertices_count_, vertices_count_, weight_infinity());
		for (const auto v : vertices()) {
			dist[v][v] = 0;
		}
		for (const auto& edge : edges()) {
			umin(dist[edge.from()][edge.to()], edge.weight());
		}
		for (const auto k : vertices()) {
			for (const auto i : vertices()) {
				for (const auto j : vertices()) {
					umin(dist[i][j], dist[i][k] + dist[k][j]);
				}
			}
		}
		return dist;
	}

	template<size_t Mask = MASK, typename std::enable_if<is_weighted<Mask>::value>::type* = nullptr>
	void dijkstra(const size_t start_vertex, std::vector<T>* distance, std::vector<size_t>* last_edge = nullptr) const {
		if (is_sparse() && false) {
			sparse_dijkstra(start_vertex, distance, last_edge);
		} else {
			dense_dijkstra(start_vertex, distance, last_edge);
		}
	}

	template<size_t Mask = MASK, typename std::enable_if<is_weighted<Mask>::value>::type* = nullptr>
	T dijkstra(const size_t start_vertex, const size_t finish_vertex, std::vector<size_t>* path = nullptr) const {
		if (start_vertex == finish_vertex) {
			return 0;
		}
		std::vector<T> dist;
		std::vector<size_t> last;
		dijkstra(start_vertex, &dist, &last);
		if (path != nullptr) {
			std::vector<size_t> tmp_path;
			size_t vertex = finish_vertex;
			while (vertex != start_vertex) {
				const size_t edge = last[vertex];
				tmp_path.emplace_back(edge);
				vertex = from_[edge];
			}
			std::reverse(tmp_path.begin(), tmp_path.end());
			path->swap(tmp_path);
		}
		return dist[finish_vertex];
	}

protected:
	void push_edge(const size_t from, const size_t to) {
		const size_t edge_id = from_.size();
		from_.emplace_back(from);
		to_.emplace_back(to);
		edges_[from].emplace_back(edge_id);
	}

	std::vector<EdgesList> edges_;
	std::vector<size_t> from_;
	std::vector<size_t> to_;
	std::vector<T> weight_;

	size_t vertices_count_;

private:
	template<size_t Mask = MASK, typename std::enable_if<is_weighted<Mask>::value>::type* = nullptr>
	void sparse_dijkstra(const size_t start_vertex, std::vector<T>* distance, std::vector<size_t>* last_edge) const {
		std::vector<T> dist(vertices_count_, weight_infinity());
		std::vector<size_t> last(vertices_count_, std::numeric_limits<size_t>::max());
		dist[start_vertex] = 0;
		using QueueNode = std::pair<T, size_t>;
		std::priority_queue<QueueNode> q;
		q.emplace(0, start_vertex);
		while (!q.empty()) {
			const QueueNode node = q.top();
			q.pop();
			const T len = -node.first;
			const size_t vertex = node.second;
			if (len > dist[vertex]) {
				continue;
			}
			for (const auto& it : edges(vertex)) {
				const T new_dist = len + it.weight();
				const size_t to_vertex = it.to();
				if (umin(dist[to_vertex], new_dist)) {
					q.push(std::make_pair(-new_dist, to_vertex));
					last[to_vertex] = it.id();
				}
			}
		}
		distance->swap(dist);
		if (last_edge != nullptr) {
			last_edge->swap(last);
		}
	}

	template<size_t Mask = MASK, typename std::enable_if<is_weighted<Mask>::value>::type* = nullptr>
	void dense_dijkstra(const size_t start_vertex, std::vector<T>* distance, std::vector<size_t>* last_edge) const {
		std::vector<bool> used(vertices_count_);
		std::vector<T> dist(vertices_count_, weight_infinity());
		std::vector<size_t> last(vertices_count_, std::numeric_limits<size_t>::max());
		dist[start_vertex] = 0;
		for (size_t iter = 0; iter < vertices_count_; ++iter) {
			size_t vertex = std::numeric_limits<size_t>::max();
			T min_dist = weight_infinity();
			for (const size_t v : vertices()) {
				if (!used[v] && umin(min_dist, dist[v])) {
					min_dist = dist[v];
					vertex = v;
				}
			}
			if (vertex == std::numeric_limits<size_t>::max()) {
				break;
			}
			used[vertex] = true;
			for (const auto& it : edges(vertex)) {
				const size_t to_vertex = it.to();
				const T len = min_dist + it.weight();
				if (!used[to_vertex] && umin(dist[to_vertex], len)) {
					dist[to_vertex] = len;
					last[to_vertex] = it.id();
				}
			}
		}
		distance->swap(dist);
		if (last_edge != nullptr) {
			last_edge->swap(last);
		}
	}

};

template<typename T, size_t MASK>
void Graph<T, MASK>::clear() {
	vertices_count_ = 0;
	edges_.clear();
	from_.clear();
	to_.clear();
	weight_.clear();
}

template<typename T, size_t MASK>
size_t Graph<T, MASK>::find_vertex_with_max_degree() const {
	const auto iter = std::max_element(edges_.begin(), edges_.end(),
		[](const EdgesList& lhs, const EdgesList& rhs) {
		return lhs.size() < rhs.size();
	});
	return static_cast<size_t>(std::distance(edges_.begin(), iter));
}

template<typename T, size_t MASK>
bool Graph<T, MASK>::is_bipartite(std::vector<size_t>& partition) const {
	const size_t kNone = std::numeric_limits<size_t>::max();
	partition.assign(vertices_count_, kNone);
	Queue<size_t> q(vertices_count_);
	for (size_t i = 0; i < vertices_count_; ++i) {
		if (partition[i] == kNone) {
			q.clear();
			q.push(i);
			partition[i] = 0;
			while (!q.empty()) {
				const size_t vertex = q.pop_front();
				const size_t color = partition[vertex];
				for (const auto& it : edges(vertex)) {
					const size_t to_vertex = it.to();
					if (partition[to_vertex] == kNone) {
						partition[to_vertex] = color ^ 1;
						q.push(to_vertex);
						continue;
					}
					if (partition[to_vertex] == color) {
						return false;
					}
				}
			}
		}
	}
	return true;
}
<|endoftext|>


<commit_before>// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "components/message_port/web_message_port_channel_impl.h"

#include "base/bind.h"
#include "base/logging.h"
#include "base/strings/string16.h"
#include "third_party/WebKit/public/platform/WebMessagePortChannelClient.h"
#include "third_party/WebKit/public/platform/WebString.h"
#include "third_party/mojo/src/mojo/public/cpp/system/message_pipe.h"

using blink::WebMessagePortChannel;
using blink::WebMessagePortChannelArray;
using blink::WebMessagePortChannelClient;
using blink::WebString;

namespace message_port {

void WebMessagePortChannelImpl::CreatePair(
    blink::WebMessagePortChannel** channel1,
    blink::WebMessagePortChannel** channel2) {
  mojo::ScopedMessagePipeHandle pipe1;
  mojo::ScopedMessagePipeHandle pipe2;
  MojoResult result = mojo::CreateMessagePipe(nullptr, &pipe1, &pipe2);
  if (result != MOJO_RESULT_OK) {
    NOTREACHED();
    return;
  }

  *channel1 = new WebMessagePortChannelImpl(pipe1.Pass());;
  *channel2 = new WebMessagePortChannelImpl(pipe2.Pass());
}

WebMessagePortChannelImpl::WebMessagePortChannelImpl(
    mojo::ScopedMessagePipeHandle pipe)
    : client_(nullptr), pipe_(pipe.Pass()) {
  WaitForNextMessage();
}

WebMessagePortChannelImpl::~WebMessagePortChannelImpl() {
}

void WebMessagePortChannelImpl::setClient(WebMessagePortChannelClient* client) {
  client_ = client;
}

void WebMessagePortChannelImpl::destroy() {
  setClient(nullptr);
  delete this;
}

void WebMessagePortChannelImpl::postMessage(
    const WebString& message_as_string,
    WebMessagePortChannelArray* channels) {
  base::string16 string = message_as_string;

  std::vector<MojoHandle> handles;
  if (channels) {
    for (size_t i = 0; i < channels->size(); ++i) {
      WebMessagePortChannelImpl* channel =
          static_cast<WebMessagePortChannelImpl*>((*channels)[i]);
      handles.push_back(channel->pipe_.release().value());
      channel->handle_watcher_.Stop();
    }
    delete channels;
  }

  uint32_t num_handles = static_cast<uint32_t>(handles.size());
  MojoHandle* handles_ptr = handles.empty() ? nullptr : &handles[0];

  MojoResult result = MojoWriteMessage(
      pipe_.get().value(), string.c_str(),
      static_cast<uint32_t>(string.length() * sizeof(base::char16)),
      handles_ptr, num_handles, MOJO_WRITE_MESSAGE_FLAG_NONE);
  DCHECK_EQ(MOJO_RESULT_OK, result);
}

bool WebMessagePortChannelImpl::tryGetMessage(
    WebString* message,
    WebMessagePortChannelArray& channels) {
  uint32_t num_bytes = 0;
  uint32_t num_handles = 0;
  MojoResult result = MojoReadMessage(
      pipe_.get().value(), nullptr, &num_bytes, nullptr, &num_handles,
      MOJO_READ_MESSAGE_FLAG_NONE);
  if (result != MOJO_RESULT_RESOURCE_EXHAUSTED)
    return false;

  base::string16 message16;
  CHECK(num_bytes % sizeof(base::char16) == 0);
  message16.resize(num_bytes / sizeof(base::char16));
  std::vector<MojoHandle> handles;
  handles.resize(num_handles);

  MojoHandle* handles_ptr = handles.empty() ? nullptr : &handles[0];
  result = MojoReadMessage(
      pipe_.get().value(), &message16[0], &num_bytes, handles_ptr, &num_handles,
      MOJO_READ_MESSAGE_FLAG_NONE);
  if (result != MOJO_RESULT_OK) {
    NOTREACHED();
    return false;
  }

  *message = message16;
  WebMessagePortChannelArray ports(handles.size());
  for (size_t i = 0; i < handles.size(); ++i) {
    mojo::MessagePipeHandle mph(handles[i]);
    mojo::ScopedMessagePipeHandle handle(mph);
    ports[i] = new WebMessagePortChannelImpl(handle.Pass());
  }
  channels = ports;
  return true;
}

void WebMessagePortChannelImpl::WaitForNextMessage() {
  handle_watcher_.Start(
      pipe_.get(),
      MOJO_HANDLE_SIGNAL_READABLE,
      MOJO_DEADLINE_INDEFINITE,
      base::Bind(&WebMessagePortChannelImpl::OnMessageAvailable,
                 base::Unretained(this)));
}

void WebMessagePortChannelImpl::OnMessageAvailable(MojoResult result) {
  DCHECK_EQ(MOJO_RESULT_OK, result);
  if (!client_)
    return;
  client_->messageAvailable();
  WaitForNextMessage();
}

}  // namespace message_port
<commit_msg>Fix dcheck in message port code on Mandoline shutdown.<commit_after>// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "components/message_port/web_message_port_channel_impl.h"

#include "base/bind.h"
#include "base/logging.h"
#include "base/strings/string16.h"
#include "third_party/WebKit/public/platform/WebMessagePortChannelClient.h"
#include "third_party/WebKit/public/platform/WebString.h"
#include "third_party/mojo/src/mojo/public/cpp/system/message_pipe.h"

using blink::WebMessagePortChannel;
using blink::WebMessagePortChannelArray;
using blink::WebMessagePortChannelClient;
using blink::WebString;

namespace message_port {

void WebMessagePortChannelImpl::CreatePair(
    blink::WebMessagePortChannel** channel1,
    blink::WebMessagePortChannel** channel2) {
  mojo::ScopedMessagePipeHandle pipe1;
  mojo::ScopedMessagePipeHandle pipe2;
  MojoResult result = mojo::CreateMessagePipe(nullptr, &pipe1, &pipe2);
  if (result != MOJO_RESULT_OK) {
    NOTREACHED();
    return;
  }

  *channel1 = new WebMessagePortChannelImpl(pipe1.Pass());;
  *channel2 = new WebMessagePortChannelImpl(pipe2.Pass());
}

WebMessagePortChannelImpl::WebMessagePortChannelImpl(
    mojo::ScopedMessagePipeHandle pipe)
    : client_(nullptr), pipe_(pipe.Pass()) {
  WaitForNextMessage();
}

WebMessagePortChannelImpl::~WebMessagePortChannelImpl() {
}

void WebMessagePortChannelImpl::setClient(WebMessagePortChannelClient* client) {
  client_ = client;
}

void WebMessagePortChannelImpl::destroy() {
  setClient(nullptr);
  delete this;
}

void WebMessagePortChannelImpl::postMessage(
    const WebString& message_as_string,
    WebMessagePortChannelArray* channels) {
  base::string16 string = message_as_string;

  std::vector<MojoHandle> handles;
  if (channels) {
    for (size_t i = 0; i < channels->size(); ++i) {
      WebMessagePortChannelImpl* channel =
          static_cast<WebMessagePortChannelImpl*>((*channels)[i]);
      handles.push_back(channel->pipe_.release().value());
      channel->handle_watcher_.Stop();
    }
    delete channels;
  }

  uint32_t num_handles = static_cast<uint32_t>(handles.size());
  MojoHandle* handles_ptr = handles.empty() ? nullptr : &handles[0];

  MojoResult result = MojoWriteMessage(
      pipe_.get().value(), string.c_str(),
      static_cast<uint32_t>(string.length() * sizeof(base::char16)),
      handles_ptr, num_handles, MOJO_WRITE_MESSAGE_FLAG_NONE);
  DCHECK_EQ(MOJO_RESULT_OK, result);
}

bool WebMessagePortChannelImpl::tryGetMessage(
    WebString* message,
    WebMessagePortChannelArray& channels) {
  uint32_t num_bytes = 0;
  uint32_t num_handles = 0;
  MojoResult result = MojoReadMessage(
      pipe_.get().value(), nullptr, &num_bytes, nullptr, &num_handles,
      MOJO_READ_MESSAGE_FLAG_NONE);
  if (result != MOJO_RESULT_RESOURCE_EXHAUSTED)
    return false;

  base::string16 message16;
  CHECK(num_bytes % sizeof(base::char16) == 0);
  message16.resize(num_bytes / sizeof(base::char16));
  std::vector<MojoHandle> handles;
  handles.resize(num_handles);

  MojoHandle* handles_ptr = handles.empty() ? nullptr : &handles[0];
  result = MojoReadMessage(
      pipe_.get().value(), &message16[0], &num_bytes, handles_ptr, &num_handles,
      MOJO_READ_MESSAGE_FLAG_NONE);
  if (result != MOJO_RESULT_OK) {
    NOTREACHED();
    return false;
  }

  *message = message16;
  WebMessagePortChannelArray ports(handles.size());
  for (size_t i = 0; i < handles.size(); ++i) {
    mojo::MessagePipeHandle mph(handles[i]);
    mojo::ScopedMessagePipeHandle handle(mph);
    ports[i] = new WebMessagePortChannelImpl(handle.Pass());
  }
  channels = ports;
  return true;
}

void WebMessagePortChannelImpl::WaitForNextMessage() {
  handle_watcher_.Start(
      pipe_.get(),
      MOJO_HANDLE_SIGNAL_READABLE,
      MOJO_DEADLINE_INDEFINITE,
      base::Bind(&WebMessagePortChannelImpl::OnMessageAvailable,
                 base::Unretained(this)));
}

void WebMessagePortChannelImpl::OnMessageAvailable(MojoResult result) {
  // Called when the message loop shuts down.
  if (result == MOJO_RESULT_ABORTED)
    return;

  DCHECK_EQ(MOJO_RESULT_OK, result);
  if (!client_)
    return;
  client_->messageAvailable();
  WaitForNextMessage();
}

}  // namespace message_port
<|endoftext|>


<commit_before>#pragma once
#include <cmath>
#include <vector>

#include "random.hpp"

template<typename T>
inline bool is_prime(const T& n)
// Straightforward check in O(sqrt(N))
{
	if (n < 2) {
		return false;
	}
	const T floored_square_root = static_cast<T>(sqrt(n));
	for (T i = 2; i <= floored_square_root; ++i) {
		if (n % i == 0) {
			return false;
		}
	}
	return true;
}

template<typename T>
inline T next_prime(const T& n) {
	for (T candidate = n; ; ++candidate) {
		if (is_prime(candidate)) {
			return candidate;
		}
	}
}

template<typename T>
inline T random_prime(const T from, const T to)
// note that resulting prime is not necessary from [from, to] interval
// [from, to] sets an interval to select a random integer to get next_prime()
{
	return next_prime(Random::get(from, to));
}

template<typename T = uint32_t>
inline T random_big_prime(const T from = 1000000000, const T to = INF) {
	return random_prime(from, to);
}

inline std::vector<bool> eratosthenes_sieve(const size_t n) {
	if (n < 2) {
		return std::vector<bool>(n, false);
	}
	std::vector<bool> prime(n, true);
	prime[0] = false;
	prime[1] = false;
	for (size_t i = 4; i < n; i += 2) {
		prime[i] = false;
	}
	for (size_t i = 3; i * i < n; i += 2) {
		if (prime[i]) {
			const size_t delta = i * 2;
			for (size_t j = i * i; j < n; j += delta) {
				prime[j] = false;
			}
		}
	}
	return prime;
}

template<typename T = uint32_t>
inline std::vector<T> primes_vector(const size_t n) {
	if (n < 2) {
		return {};
	}
	const std::vector<bool> prime = eratosthenes_sieve(n);
	std::vector<T> result = {2};
	for (size_t i = 3; i < n; i += 2) {
		if (prime[i]) {
			result.emplace_back(i);
		}
	}
	return result;
}

template<typename T = uint32_t>
inline std::vector<T> min_prime_div_vector(const size_t n) {
	std::vector<T> result(n, 0);
	result[0] = 1;
	result[1] = 1;
	for (size_t i = 2; i < n; i += 2) {
		result[i] = 2;
	}
	size_t index = 3;
	while (index * index < n) {
		if (result[index] == 0) {
			result[index] = index;
			const size_t delta = index * 2;
			for (size_t j = index * index; j < n; j += delta) {
				if (result[j] == 0) {
					result[j] = index;
				}
			}
		}
		index += 2;
	}
	while (index < n) {
		if (result[index] == 0) {
			result[index] = index;
		}
		++index;
	}
	return result;
}
<commit_msg>Implemented get_prime_divisors_vector() method in 2 variants.<commit_after>#pragma once
#include <cmath>
#include <vector>

#include "random.hpp"

template<typename T>
inline bool is_prime(const T& n)
// Straightforward check in O(sqrt(N))
{
	if (n < 2) {
		return false;
	}
	const T floored_square_root = static_cast<T>(sqrt(n));
	for (T i = 2; i <= floored_square_root; ++i) {
		if (n % i == 0) {
			return false;
		}
	}
	return true;
}

template<typename T>
inline T next_prime(const T& n) {
	for (T candidate = n; ; ++candidate) {
		if (is_prime(candidate)) {
			return candidate;
		}
	}
}

template<typename T>
inline T random_prime(const T from, const T to)
// note that resulting prime is not necessary from [from, to] interval
// [from, to] sets an interval to select a random integer to get next_prime()
{
	return next_prime(Random::get(from, to));
}

template<typename T = uint32_t>
inline T random_big_prime(const T from = 1000000000, const T to = INF) {
	return random_prime(from, to);
}

inline std::vector<bool> eratosthenes_sieve(const size_t n) {
	if (n < 2) {
		return std::vector<bool>(n, false);
	}
	std::vector<bool> prime(n, true);
	prime[0] = false;
	prime[1] = false;
	for (size_t i = 4; i < n; i += 2) {
		prime[i] = false;
	}
	for (size_t i = 3; i * i < n; i += 2) {
		if (prime[i]) {
			const size_t delta = i * 2;
			for (size_t j = i * i; j < n; j += delta) {
				prime[j] = false;
			}
		}
	}
	return prime;
}

template<typename T = uint32_t>
inline std::vector<T> primes_vector(const size_t n) {
	if (n < 2) {
		return {};
	}
	const std::vector<bool> prime = eratosthenes_sieve(n);
	std::vector<T> result = {2};
	for (size_t i = 3; i < n; i += 2) {
		if (prime[i]) {
			result.emplace_back(i);
		}
	}
	return result;
}

template<typename T = uint32_t>
inline std::vector<T> min_prime_div_vector(const size_t n) {
	std::vector<T> result(n, 0);
	result[0] = 1;
	result[1] = 1;
	for (size_t i = 2; i < n; i += 2) {
		result[i] = 2;
	}
	size_t index = 3;
	while (index * index < n) {
		if (result[index] == 0) {
			result[index] = index;
			const size_t delta = index * 2;
			for (size_t j = index * index; j < n; j += delta) {
				if (result[j] == 0) {
					result[j] = index;
				}
			}
		}
		index += 2;
	}
	while (index < n) {
		if (result[index] == 0) {
			result[index] = index;
		}
		++index;
	}
	return result;
}

template<typename T, typename size_type = std::size_t>
std::vector<std::pair<T, size_type>> get_prime_divisors_vector(const T n, const std::vector<T>& min_prime_div_vector) {
	std::vector<std::pair<T, size_type>> prime_divisors;
	T cur = n;
	while (cur > 1) {
		const T min_div = min_prime_div_vector[cur];
		if (!prime_divisors.empty() && prime_divisors.back().first == min_div) {
			++prime_divisors.back().second;
		} else {
			prime_divisors.emplace_back(min_div, 1);
		}
		cur /= min_div;
	}
	return prime_divisors;
}

template<typename T, typename size_type = std::size_t>
std::vector<std::pair<T, size_type>> get_prime_divisors_vector(const T n) {
	std::vector<std::pair<T, size_type>> prime_divisors;
	T cur = n;
	for (T i = 2; static_cast<int64_t>(i) * i <= cur; ++i) {
		if (cur % i == 0) {
			size_type degree = 0;
			while (cur % i == 0) {
				++degree;
				cur /= i;
			}
			prime_divisors.emplace_back(i, degree);
		}
	}
	if (cur > 1) {
		prime_divisors.emplace_back(cur, 1);
	}
	return prime_divisors;
}
<|endoftext|>