<commit_before>/*
 * Copyright 2011, 2012 Esrille Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

// A test harness for the implementation report of
//       the CSS2.1 Conformance Test Suite
// http://test.csswg.org/suites/css2.1/20110323/

#include <unistd.h>
#include <sys/wait.h>

#include <cstring>
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <vector>

#include <boost/version.hpp>
#include <boost/iostreams/stream.hpp>
#include <boost/iostreams/device/file_descriptor.hpp>

enum {
    INTERACTIVE = 0,
    HEADLESS,
    REPORT,
    UPDATE,

    // exit status codes
    ES_PASS = 0,
    ES_FATAL,
    ES_FAIL,
    ES_INVALID,
    ES_NA,
    ES_SKIP,
    ES_UNCERTAIN
};

const char* StatusStrings[] = {
    "pass",
    "fatal",
    "fail",
    "invalid",
    "?",
    "skip",
    "uncertain",
};

struct ForkStatus {
    pid_t       pid;
    std::string url;
    int         code;
public:
    ForkStatus() : pid(-1), code(0) {}
};

size_t forkMax = 1;
size_t forkCount = 0;
std::vector<ForkStatus> forkStates(1);

int processOutput(std::istream& stream, std::string& result)
{
    std::string output;
    bool completed = false;
    while (std::getline(stream, output)) {
        if (!completed) {
            if (output == "## complete")
                completed = true;
            continue;
        }
        if (output == "##")
            break;
        result += output + '\n';
    }
    return 0;
}

int runTest(int argc, char* argv[], std::string userStyle, std::string testFonts, std::string url, std::string& result, unsigned timeout)
{
    int pipefd[2];
    pipe(pipefd);

    pid_t pid = fork();
    if (pid == -1) {
        std::cerr << "error: no more process to create\n";
        return -1;
    }
    if (pid == 0) {
        close(1);
        dup(pipefd[1]);
        close(pipefd[0]);
        int argi = argc - 1;
        if (!userStyle.empty())
            argv[argi++] = strdup(userStyle.c_str());
        if (testFonts == "on")
            argv[argi++] ="-testfonts";
        url = "http://localhost:8000/" + url;
        // url = "http://test.csswg.org/suites/css2.1/20110323/" + url;
        argv[argi++] = strdup(url.c_str());
        argv[argi] = 0;
        if (timeout)
            alarm(timeout); // Terminate the process if it does not complete in 'timeout' seconds.
        execvp(argv[0], argv);
        exit(EXIT_FAILURE);
    }
    close(pipefd[1]);

#if 104400 <= BOOST_VERSION
    boost::iostreams::stream<boost::iostreams::file_descriptor_source> stream(pipefd[0], boost::iostreams::close_handle);
#else
    boost::iostreams::stream<boost::iostreams::file_descriptor_source> stream(pipefd[0], true);
#endif
    processOutput(stream, result);
    return pid;
}

void killTest(int pid)
{
    int status;
    kill(pid, SIGTERM);
    if (wait(&status) == -1)
        std::cerr << "error: failed to wait for a test process to complete\n";
}

bool loadLog(const std::string& path, std::string& result, std::string& log)
{
    std::ifstream file(path.c_str());
    if (!file) {
        result = "?";
        return false;
    }
    std::string line;
    std::getline(file, line);
    size_t pos = line.find('\t');
    if (pos != std::string::npos)
        result = line.substr(pos + 1);
    else {
        result = "?";
        return false;
    }
    log.clear();
    while (std::getline(file, line))
        log += line + '\n';
    return true;
}

bool saveLog(const std::string& path, const std::string& url, const std::string& result, const std::string& log)
{
    std::ofstream file(path.c_str(), std::ios_base::out | std::ios_base::trunc);
    if (!file) {
        std::cerr << "error: failed to open the report file\n";
        return false;
    }
    file << "# " << url.c_str() << '\t' << result << '\n' << log;
    file.flush();
    file.close();
    return true;
}

std::string test(int mode, int argc, char* argv[], const std::string& url, const std::string& userStyle, const std::string& testFonts, unsigned timeout)
{
    std::string path(url);
    size_t pos = path.rfind('.');
    if (pos != std::string::npos) {
        path.erase(pos);
        path += ".log";
    }
    std::string evaluation;
    std::string log;
    loadLog(path, evaluation, log);

    pid_t pid = -1;
    std::string output;
    switch (mode) {
    case REPORT:
        break;
    case UPDATE:
        if (evaluation[0] == '?')
            break;
        // FALL THROUGH
    default:
        pid = runTest(argc, argv, userStyle, testFonts, url, output, timeout);
        break;
    }

    std::string result;
    if (0 < pid && output.empty())
        result = "fatal";
    else if (mode == INTERACTIVE) {
        std::cout << "## complete\n" << output;
        std::cout << '[' << url << "] ";
        if (evaluation.empty() || evaluation[0] == '?')
            std::cout << "pass? ";
        else {
            std::cout << evaluation << "? ";
            if (evaluation != "pass")
                std::cout << '\a';
        }
        std::getline(std::cin, result);
        if (result.empty()) {
            if (evaluation.empty() || evaluation[0] == '?')
                result = "pass";
            else
                result = evaluation;
        } else if (result == "p" || result == "\x1b")
            result = "pass";
        else if (result == "f")
            result = "fail";
        else if (result == "i")
            result = "invalid";
        else if (result == "k") // keep
            result = evaluation;
        else if (result == "n")
            result = "na";
        else if (result == "s")
            result = "skip";
        else if (result == "u")
            result = "uncertain";
        else if (result == "q" || result == "quit")
            exit(EXIT_FAILURE);
        else if (result == "z")
            result = "undo";
        if (result != "undo" && !saveLog(path, url, result, output)) {
            std::cerr << "error: failed to open the report file\n";
            exit(EXIT_FAILURE);
        }
    } else if (mode == HEADLESS) {
        if (evaluation != "?" && output != log)
            result = "uncertain";
        else
            result = evaluation;
    } else if (mode == REPORT) {
        result = evaluation;
    } else if (mode == UPDATE) {
        result = evaluation;
        if (result[0] != '?') {
            if (!saveLog(path, url, result, output)) {
                std::cerr << "error: failed to open the report file\n";
                exit(EXIT_FAILURE);
            }
        }
    }

    if (0 < pid)
        killTest(pid);
    if (mode != INTERACTIVE && result[0] != '?')
        std::cout << url << '\t' << result << '\n';
    return result;
}

void reduce(std::ostream& report)
{
    for (int i = 0; i < forkCount; ++i) {
        int status;
        pid_t pid = wait(&status);
        for (int j = 0; j < forkCount; ++j) {
            if (forkStates[j].pid == pid) {
                forkStates[j].pid = -1;
                forkStates[j].code = WIFEXITED(status) ? WEXITSTATUS(status) : ES_FATAL;
                break;
            }
        }
    }
    for (int i = 0; i < forkCount; ++i) {
        if (forkStates[i].code != ES_NA)
            std::cout << forkStates[i].url << '\t' << StatusStrings[forkStates[i].code] << '\n';
        report << forkStates[i].url << '\t' << StatusStrings[forkStates[i].code] << '\n';
    }
    forkCount = 0;
}

void map(std::ostream& report, int mode, int argc, char* argv[], const std::string& url, const std::string& userStyle, const std::string& testFonts, unsigned timeout)
{
    pid_t pid = fork();
    if (pid == -1) {
        std::cerr << "error: no more process to create\n";
        exit(EXIT_FAILURE);
    }
    if (pid == 0) {
        std::string path(url);
        size_t pos = path.rfind('.');
        if (pos != std::string::npos) {
            path.erase(pos);
            path += ".log";
        }
        std::string evaluation;
        std::string log;
        loadLog(path, evaluation, log);

        pid_t pid = -1;
        std::string output;
        switch (mode) {
        case UPDATE:
            if (evaluation[0] == '?')
                break;
            // FALL THROUGH
        default:
            pid = runTest(argc, argv, userStyle, testFonts, url, output, timeout);
            break;
        }

        std::string result;
        if (0 < pid && output.empty())
            result = "fatal";
        else if (mode == HEADLESS) {
            if (evaluation != "?" && output != log)
                result = "uncertain";
            else
                result = evaluation;
        } else if (mode == UPDATE) {
            result = evaluation;
            if (result[0] != '?') {
                if (!saveLog(path, url, result, output)) {
                    std::cerr << "error: failed to open the report file\n";
                    exit(EXIT_FAILURE);
                }
            }
        }
        if (0 < pid)
            killTest(pid);
        int status = ES_NA;
        if (!result.compare(0, 4, "pass"))
            status = ES_PASS;
        else if (!result.compare(0, 5, "fatal"))
            status = ES_FATAL;
        else if (!result.compare(0, 4, "fail"))
            status = ES_FAIL;
        else if (!result.compare(0, 7, "invalid"))
            status = ES_INVALID;
        else if (!result.compare(0, 4, "skip"))
            status = ES_SKIP;
        else if (!result.compare(0, 9, "uncertain"))
            status = ES_UNCERTAIN;
        exit(status);
    } else {
        forkStates[forkCount].url = url;
        forkStates[forkCount].pid = pid;
    }
    if (++forkCount == forkMax)
        reduce(report);
}

int main(int argc, char* argv[])
{
    int mode = HEADLESS;
    unsigned timeout = 10;

    int argi = 1;
    while (*argv[argi] == '-') {
        switch (argv[argi][1]) {
        case 'i':
            mode = INTERACTIVE;
            timeout = 0;
            break;
        case 'r':
            mode = REPORT;
            break;
        case 'u':
            mode = UPDATE;
            break;
        case 'j':
            forkMax = strtoul(argv[argi] + 2, 0, 10);
            if (forkMax == 0)
                forkMax = 1;
            forkStates.resize(forkMax);
            break;
        default:
            break;
        }
        ++argi;
    }

    if (argc < argi + 2) {
        std::cout << "usage: " << argv[0] << " [-i] report.data command [argument ...]\n";
        return EXIT_FAILURE;
    }

    std::ifstream data(argv[argi]);
    if (!data) {
        std::cerr << "error: " << argv[argi] << ": no such file\n";
        return EXIT_FAILURE;
    }

    std::ofstream report("report.data", std::ios_base::out | std::ios_base::trunc);
    if (!report) {
        std::cerr << "error: failed to open the report file\n";
        return EXIT_FAILURE;
    }

    char* args[argc - argi + 3];
    for (int i = 2; i < argc; ++i)
        args[i - 2] = argv[i + argi - 1];
    args[argc - argi] = args[argc - argi + 1] = args[argc - argi + 2] = 0;

    std::string result;
    std::string url;
    std::string undo;
    std::string userStyle;
    std::string testFonts;
    bool redo = false;
    while (data) {
        if (result == "undo") {
            std::swap(url, undo);
            redo = true;
        } else if (redo) {
            std::swap(url, undo);
            redo = false;
        } else {
            std::string line;
            std::getline(data, line);
            if (line.empty())
                continue;
            if (line == "testname    result  comment") {
                report << line << '\n';
                continue;
            }
            if (line[0] == '#') {
                if (line.compare(1, 9, "userstyle") == 0) {
                    if (10 < line.length()) {
                        std::stringstream s(line.substr(10), std::stringstream::in);
                        s >> userStyle;
                    } else
                        userStyle.clear();
                } else if (line.compare(1, 9, "testfonts") == 0) {
                    if (10 < line.length()) {
                        std::stringstream s(line.substr(10), std::stringstream::in);
                        s >> testFonts;
                    } else
                        testFonts.clear();
                }
                reduce(report);
                report << line << '\n';
                continue;
            }
            undo = url;
            std::stringstream s(line, std::stringstream::in);
            s >> url;
        }
        if (url.empty())
            continue;

        switch (mode) {
        case HEADLESS:
        case UPDATE:
            map(report, mode, argc - argi, args, url, userStyle, testFonts, timeout);
            break;
        default:
            result = test(mode, argc - argi, args, url, userStyle, testFonts, timeout);
            if (result != "undo")
                report << url << '\t' << result << '\n';
            break;
        }
    }
    if (mode == HEADLESS || mode == UPDATE)
        reduce(report);
    report.close();
}
<commit_msg>(harness) : Set the exit code to EXIT_SUCCESS when there's no changes, and EXIT_FAILURE otherwise in the headless and update mode.<commit_after>/*
 * Copyright 2011, 2012 Esrille Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

// A test harness for the implementation report of
//       the CSS2.1 Conformance Test Suite
// http://test.csswg.org/suites/css2.1/20110323/

#include <unistd.h>
#include <sys/wait.h>

#include <cstring>
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <vector>

#include <boost/version.hpp>
#include <boost/iostreams/stream.hpp>
#include <boost/iostreams/device/file_descriptor.hpp>

enum {
    INTERACTIVE = 0,
    HEADLESS,
    REPORT,
    UPDATE,

    // exit status codes
    ES_PASS = 0,
    ES_FATAL,
    ES_FAIL,
    ES_INVALID,
    ES_NA,
    ES_SKIP,
    ES_UNCERTAIN
};

const char* StatusStrings[] = {
    "pass",
    "fatal",
    "fail",
    "invalid",
    "?",
    "skip",
    "uncertain",
};

struct ForkStatus {
    pid_t       pid;
    std::string url;
    int         code;
public:
    ForkStatus() : pid(-1), code(0) {}
};

size_t forkMax = 1;
size_t forkCount = 0;
std::vector<ForkStatus> forkStates(1);

size_t uncertainCount = 0;

int processOutput(std::istream& stream, std::string& result)
{
    std::string output;
    bool completed = false;
    while (std::getline(stream, output)) {
        if (!completed) {
            if (output == "## complete")
                completed = true;
            continue;
        }
        if (output == "##")
            break;
        result += output + '\n';
    }
    return 0;
}

int runTest(int argc, char* argv[], std::string userStyle, std::string testFonts, std::string url, std::string& result, unsigned timeout)
{
    int pipefd[2];
    pipe(pipefd);

    pid_t pid = fork();
    if (pid == -1) {
        std::cerr << "error: no more process to create\n";
        return -1;
    }
    if (pid == 0) {
        close(1);
        dup(pipefd[1]);
        close(pipefd[0]);
        int argi = argc - 1;
        if (!userStyle.empty())
            argv[argi++] = strdup(userStyle.c_str());
        if (testFonts == "on")
            argv[argi++] ="-testfonts";
        url = "http://localhost:8000/" + url;
        // url = "http://test.csswg.org/suites/css2.1/20110323/" + url;
        argv[argi++] = strdup(url.c_str());
        argv[argi] = 0;
        if (timeout)
            alarm(timeout); // Terminate the process if it does not complete in 'timeout' seconds.
        execvp(argv[0], argv);
        exit(EXIT_FAILURE);
    }
    close(pipefd[1]);

#if 104400 <= BOOST_VERSION
    boost::iostreams::stream<boost::iostreams::file_descriptor_source> stream(pipefd[0], boost::iostreams::close_handle);
#else
    boost::iostreams::stream<boost::iostreams::file_descriptor_source> stream(pipefd[0], true);
#endif
    processOutput(stream, result);
    return pid;
}

void killTest(int pid)
{
    int status;
    kill(pid, SIGTERM);
    if (wait(&status) == -1)
        std::cerr << "error: failed to wait for a test process to complete\n";
}

bool loadLog(const std::string& path, std::string& result, std::string& log)
{
    std::ifstream file(path.c_str());
    if (!file) {
        result = "?";
        return false;
    }
    std::string line;
    std::getline(file, line);
    size_t pos = line.find('\t');
    if (pos != std::string::npos)
        result = line.substr(pos + 1);
    else {
        result = "?";
        return false;
    }
    log.clear();
    while (std::getline(file, line))
        log += line + '\n';
    return true;
}

bool saveLog(const std::string& path, const std::string& url, const std::string& result, const std::string& log)
{
    std::ofstream file(path.c_str(), std::ios_base::out | std::ios_base::trunc);
    if (!file) {
        std::cerr << "error: failed to open the report file\n";
        return false;
    }
    file << "# " << url.c_str() << '\t' << result << '\n' << log;
    file.flush();
    file.close();
    return true;
}

std::string test(int mode, int argc, char* argv[], const std::string& url, const std::string& userStyle, const std::string& testFonts, unsigned timeout)
{
    std::string path(url);
    size_t pos = path.rfind('.');
    if (pos != std::string::npos) {
        path.erase(pos);
        path += ".log";
    }
    std::string evaluation;
    std::string log;
    loadLog(path, evaluation, log);

    pid_t pid = -1;
    std::string output;
    switch (mode) {
    case REPORT:
        break;
    case UPDATE:
        if (evaluation[0] == '?')
            break;
        // FALL THROUGH
    default:
        pid = runTest(argc, argv, userStyle, testFonts, url, output, timeout);
        break;
    }

    std::string result;
    if (0 < pid && output.empty())
        result = "fatal";
    else if (mode == INTERACTIVE) {
        std::cout << "## complete\n" << output;
        std::cout << '[' << url << "] ";
        if (evaluation.empty() || evaluation[0] == '?')
            std::cout << "pass? ";
        else {
            std::cout << evaluation << "? ";
            if (evaluation != "pass")
                std::cout << '\a';
        }
        std::getline(std::cin, result);
        if (result.empty()) {
            if (evaluation.empty() || evaluation[0] == '?')
                result = "pass";
            else
                result = evaluation;
        } else if (result == "p" || result == "\x1b")
            result = "pass";
        else if (result == "f")
            result = "fail";
        else if (result == "i")
            result = "invalid";
        else if (result == "k") // keep
            result = evaluation;
        else if (result == "n")
            result = "na";
        else if (result == "s")
            result = "skip";
        else if (result == "u")
            result = "uncertain";
        else if (result == "q" || result == "quit")
            exit(EXIT_FAILURE);
        else if (result == "z")
            result = "undo";
        if (result != "undo" && !saveLog(path, url, result, output)) {
            std::cerr << "error: failed to open the report file\n";
            exit(EXIT_FAILURE);
        }
    } else if (mode == HEADLESS) {
        if (evaluation != "?" && output != log)
            result = "uncertain";
        else
            result = evaluation;
    } else if (mode == REPORT) {
        result = evaluation;
    } else if (mode == UPDATE) {
        result = evaluation;
        if (result[0] != '?') {
            if (!saveLog(path, url, result, output)) {
                std::cerr << "error: failed to open the report file\n";
                exit(EXIT_FAILURE);
            }
        }
    }

    if (0 < pid)
        killTest(pid);
    if (mode != INTERACTIVE && result[0] != '?')
        std::cout << url << '\t' << result << '\n';
    return result;
}

void reduce(std::ostream& report)
{
    for (int i = 0; i < forkCount; ++i) {
        int status;
        pid_t pid = wait(&status);
        for (int j = 0; j < forkCount; ++j) {
            if (forkStates[j].pid == pid) {
                forkStates[j].pid = -1;
                forkStates[j].code = WIFEXITED(status) ? WEXITSTATUS(status) : ES_FATAL;
                break;
            }
        }
    }
    for (int i = 0; i < forkCount; ++i) {
        if (forkStates[i].code == ES_UNCERTAIN)
            ++uncertainCount;
        if (forkStates[i].code != ES_NA)
            std::cout << forkStates[i].url << '\t' << StatusStrings[forkStates[i].code] << '\n';
        report << forkStates[i].url << '\t' << StatusStrings[forkStates[i].code] << '\n';
    }
    forkCount = 0;
}

void map(std::ostream& report, int mode, int argc, char* argv[], const std::string& url, const std::string& userStyle, const std::string& testFonts, unsigned timeout)
{
    pid_t pid = fork();
    if (pid == -1) {
        std::cerr << "error: no more process to create\n";
        exit(EXIT_FAILURE);
    }
    if (pid == 0) {
        std::string path(url);
        size_t pos = path.rfind('.');
        if (pos != std::string::npos) {
            path.erase(pos);
            path += ".log";
        }
        std::string evaluation;
        std::string log;
        loadLog(path, evaluation, log);

        pid_t pid = -1;
        std::string output;
        switch (mode) {
        case UPDATE:
            if (evaluation[0] == '?')
                break;
            // FALL THROUGH
        default:
            pid = runTest(argc, argv, userStyle, testFonts, url, output, timeout);
            break;
        }

        std::string result;
        if (0 < pid && output.empty())
            result = "fatal";
        else if (mode == HEADLESS) {
            if (evaluation != "?" && output != log)
                result = "uncertain";
            else
                result = evaluation;
        } else if (mode == UPDATE) {
            result = evaluation;
            if (result[0] != '?') {
                if (!saveLog(path, url, result, output)) {
                    std::cerr << "error: failed to open the report file\n";
                    exit(EXIT_FAILURE);
                }
            }
        }
        if (0 < pid)
            killTest(pid);
        int status = ES_NA;
        if (!result.compare(0, 4, "pass"))
            status = ES_PASS;
        else if (!result.compare(0, 5, "fatal"))
            status = ES_FATAL;
        else if (!result.compare(0, 4, "fail"))
            status = ES_FAIL;
        else if (!result.compare(0, 7, "invalid"))
            status = ES_INVALID;
        else if (!result.compare(0, 4, "skip"))
            status = ES_SKIP;
        else if (!result.compare(0, 9, "uncertain"))
            status = ES_UNCERTAIN;
        exit(status);
    } else {
        forkStates[forkCount].url = url;
        forkStates[forkCount].pid = pid;
    }
    if (++forkCount == forkMax)
        reduce(report);
}

int main(int argc, char* argv[])
{
    int mode = HEADLESS;
    unsigned timeout = 10;

    int argi = 1;
    while (*argv[argi] == '-') {
        switch (argv[argi][1]) {
        case 'i':
            mode = INTERACTIVE;
            timeout = 0;
            break;
        case 'r':
            mode = REPORT;
            break;
        case 'u':
            mode = UPDATE;
            break;
        case 'j':
            forkMax = strtoul(argv[argi] + 2, 0, 10);
            if (forkMax == 0)
                forkMax = 1;
            forkStates.resize(forkMax);
            break;
        default:
            break;
        }
        ++argi;
    }

    if (argc < argi + 2) {
        std::cout << "usage: " << argv[0] << " [-i] report.data command [argument ...]\n";
        return EXIT_FAILURE;
    }

    std::ifstream data(argv[argi]);
    if (!data) {
        std::cerr << "error: " << argv[argi] << ": no such file\n";
        return EXIT_FAILURE;
    }

    std::ofstream report("report.data", std::ios_base::out | std::ios_base::trunc);
    if (!report) {
        std::cerr << "error: failed to open the report file\n";
        return EXIT_FAILURE;
    }

    char* args[argc - argi + 3];
    for (int i = 2; i < argc; ++i)
        args[i - 2] = argv[i + argi - 1];
    args[argc - argi] = args[argc - argi + 1] = args[argc - argi + 2] = 0;

    std::string result;
    std::string url;
    std::string undo;
    std::string userStyle;
    std::string testFonts;
    bool redo = false;
    while (data) {
        if (result == "undo") {
            std::swap(url, undo);
            redo = true;
        } else if (redo) {
            std::swap(url, undo);
            redo = false;
        } else {
            std::string line;
            std::getline(data, line);
            if (line.empty())
                continue;
            if (line == "testname    result  comment") {
                report << line << '\n';
                continue;
            }
            if (line[0] == '#') {
                if (line.compare(1, 9, "userstyle") == 0) {
                    if (10 < line.length()) {
                        std::stringstream s(line.substr(10), std::stringstream::in);
                        s >> userStyle;
                    } else
                        userStyle.clear();
                } else if (line.compare(1, 9, "testfonts") == 0) {
                    if (10 < line.length()) {
                        std::stringstream s(line.substr(10), std::stringstream::in);
                        s >> testFonts;
                    } else
                        testFonts.clear();
                }
                reduce(report);
                report << line << '\n';
                continue;
            }
            undo = url;
            std::stringstream s(line, std::stringstream::in);
            s >> url;
        }
        if (url.empty())
            continue;

        switch (mode) {
        case HEADLESS:
        case UPDATE:
            map(report, mode, argc - argi, args, url, userStyle, testFonts, timeout);
            break;
        default:
            result = test(mode, argc - argi, args, url, userStyle, testFonts, timeout);
            if (result != "undo")
                report << url << '\t' << result << '\n';
            break;
        }
    }
    if (mode == HEADLESS || mode == UPDATE)
        reduce(report);
    report.close();

    return (0 < uncertainCount) ? EXIT_FAILURE : EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>/*
 * Copyright 2011, 2012 Esrille Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "URI.h"

#include <assert.h>
#include <unicode/uidna.h>

#include "utf.h"

namespace org { namespace w3c { namespace dom { namespace bootstrap {

std::string URI::percentEncode(const std::u16string& string, size_t pos, size_t n)
{
    std::string encoding;
    if (n == std::string::npos)
        n = string.length();
    const char16_t* p = string.c_str() + pos;
    for (const char16_t* s = p; s < p + n; ) {
        char32_t utf32;
        s = utf16to32(s, &utf32);
        assert(s);
        char utf8[5];
        char* end = utf32to8(utf32, utf8);
        assert(end);
        for (const char* p = utf8; p < end; ++p) {
            if (*p <= 0x20 || (*p < 127 && strchr("\"#%<>[\\]^{|}", *p))) {
                encoding += '%';
                char hex[3];
                sprintf(hex, "%02X", *p & 0xff);
                encoding += hex;
            } else
                encoding += *p;
        }
    }
    return encoding;
}

std::string URI::percentDecode(const std::string& string, size_t pos, size_t n)
{
    std::string decoding;
    if (n == std::string::npos)
        n = string.length();
    const char* p = string.c_str() + pos;
    const char* end = p + n;
    while (p < end) {
        char c = *p++;
        if (c == '%' && p + 2 <= end) {
            int x0 = isHexDigit(p[0]);
            int x1 = isHexDigit(p[1]);
            if (x0 && x1)
                decoding += static_cast<char>(((p[0] - x0) << 4) | (p[1] - x1));
            else {
                decoding += '%';
                decoding += p[0];
                decoding += p[1];
            }
            p += 2;
        } else
            decoding += c;
    }
    return decoding;
}

void URI::clear()
{
    protocolEnd = 0;
    hostStart = hostEnd = 0;
    hostnameStart = hostnameEnd = 0;
    portStart = portEnd = 0;
    pathnameStart = pathnameEnd = 0;
    searchStart = searchEnd = 0;
    hashStart = hashEnd = 0;
    uri.clear();
}

URI::URI(const URL& url)
{
    if (url.isEmpty()) {
        protocolEnd = 0;
        hostStart = hostEnd = 0;
        hostnameStart = hostnameEnd = 0;
        portStart = portEnd = 0;
        pathnameStart = pathnameEnd = 0;
        searchStart = searchEnd = 0;
        hashStart = hashEnd = 0;
        return;
    }

    uri += percentEncode(url.url, 0, url.protocolEnd);
    protocolEnd = uri.length();

    if (url.hostnameStart == url.hostnameEnd)
        hostStart = hostnameStart = 0;
    else {
        uri += "//";
        hostStart = hostnameStart = uri.length();
        UChar idn[256];
        int32_t len;
        UErrorCode status = U_ZERO_ERROR;
        len = uidna_IDNToASCII(reinterpret_cast<const UChar*>(url.url.c_str()) + url.hostnameStart, url.hostnameEnd - url.hostnameStart,
                               idn, 256, UIDNA_DEFAULT, 0, &status);
        if (status != U_ZERO_ERROR) {
            // TODO: error
            clear();
            return;
        }
        for (int32_t i = 0; i < len; ++i)
            uri += static_cast<char>(idn[i]);
    }
    hostnameEnd = uri.length();
    if (url.portStart < url.portEnd) {
        uri += ':';
        portStart = uri.length();
        uri += percentEncode(url.url, url.portStart, url.portEnd - url.portStart);
        portEnd = uri.length();
    } else
        portStart = portEnd = 0;
    pathnameStart = hostEnd = uri.length();
    uri += percentEncode(url.url, url.pathnameStart, url.pathnameEnd - url.pathnameStart);
    pathnameEnd = uri.length();
    if (url.searchStart < url.searchEnd) {
        searchStart = uri.length();
        uri += percentEncode(url.url, url.searchStart, url.searchEnd - url.searchStart);
        searchEnd = uri.length();
    } else
        searchStart = searchEnd = 0;
    if (url.hashStart < url.hashEnd) {
        hashStart = uri.length();
        uri += percentEncode(url.url, url.hashStart, url.hashEnd - url.hashStart);
        hashEnd = uri.length();
    } else
        hashStart = hashEnd = 0;
}

std::string URI::getPort() const
{
    if (portStart < portEnd)
        return uri.substr(portStart, portEnd - portStart);
    if (!uri.compare(0, 5, "http:"))
        return "80";
    if (!uri.compare(0, 6, "https:"))
        return "443";
    return "";
}

}}}}  // org::w3c::dom::bootstrap
<commit_msg>(URI::percentEncode) : Fix a bug.<commit_after>/*
 * Copyright 2011, 2012 Esrille Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "URI.h"

#include <assert.h>
#include <unicode/uidna.h>

#include "utf.h"

namespace org { namespace w3c { namespace dom { namespace bootstrap {

std::string URI::percentEncode(const std::u16string& string, size_t pos, size_t n)
{
    std::string encoding;
    if (n == std::string::npos)
        n = string.length();
    const char16_t* p = string.c_str() + pos;
    for (const char16_t* s = p; s < p + n; ) {
        char32_t utf32;
        s = utf16to32(s, &utf32);
        assert(s);
        char utf8[5];
        char* end = utf32to8(utf32, utf8);
        assert(end);
        for (const char* p = utf8; p < end; ++p) {
            // Note percent-encoding characters in the original URL value must be preserved.
            if (isalnum(*p) || strchr("%" "!*'();:@&=+$,/?#[]-_.~", *p))
                encoding += *p;
            else {
                encoding += '%';
                char hex[3];
                sprintf(hex, "%02X", *p & 0xff);
                encoding += hex;
            }
        }
    }
    return encoding;
}

std::string URI::percentDecode(const std::string& string, size_t pos, size_t n)
{
    std::string decoding;
    if (n == std::string::npos)
        n = string.length();
    const char* p = string.c_str() + pos;
    const char* end = p + n;
    while (p < end) {
        char c = *p++;
        if (c == '%' && p + 2 <= end) {
            int x0 = isHexDigit(p[0]);
            int x1 = isHexDigit(p[1]);
            if (x0 && x1)
                decoding += static_cast<char>(((p[0] - x0) << 4) | (p[1] - x1));
            else {
                decoding += '%';
                decoding += p[0];
                decoding += p[1];
            }
            p += 2;
        } else
            decoding += c;
    }
    return decoding;
}

void URI::clear()
{
    protocolEnd = 0;
    hostStart = hostEnd = 0;
    hostnameStart = hostnameEnd = 0;
    portStart = portEnd = 0;
    pathnameStart = pathnameEnd = 0;
    searchStart = searchEnd = 0;
    hashStart = hashEnd = 0;
    uri.clear();
}

URI::URI(const URL& url)
{
    if (url.isEmpty()) {
        protocolEnd = 0;
        hostStart = hostEnd = 0;
        hostnameStart = hostnameEnd = 0;
        portStart = portEnd = 0;
        pathnameStart = pathnameEnd = 0;
        searchStart = searchEnd = 0;
        hashStart = hashEnd = 0;
        return;
    }

    uri += percentEncode(url.url, 0, url.protocolEnd);
    protocolEnd = uri.length();

    if (url.hostnameStart == url.hostnameEnd)
        hostStart = hostnameStart = 0;
    else {
        uri += "//";
        hostStart = hostnameStart = uri.length();
        UChar idn[256];
        int32_t len;
        UErrorCode status = U_ZERO_ERROR;
        len = uidna_IDNToASCII(reinterpret_cast<const UChar*>(url.url.c_str()) + url.hostnameStart, url.hostnameEnd - url.hostnameStart,
                               idn, 256, UIDNA_DEFAULT, 0, &status);
        if (status != U_ZERO_ERROR) {
            // TODO: error
            clear();
            return;
        }
        for (int32_t i = 0; i < len; ++i)
            uri += static_cast<char>(idn[i]);
    }
    hostnameEnd = uri.length();
    if (url.portStart < url.portEnd) {
        uri += ':';
        portStart = uri.length();
        uri += percentEncode(url.url, url.portStart, url.portEnd - url.portStart);
        portEnd = uri.length();
    } else
        portStart = portEnd = 0;
    pathnameStart = hostEnd = uri.length();
    uri += percentEncode(url.url, url.pathnameStart, url.pathnameEnd - url.pathnameStart);
    pathnameEnd = uri.length();
    if (url.searchStart < url.searchEnd) {
        searchStart = uri.length();
        uri += percentEncode(url.url, url.searchStart, url.searchEnd - url.searchStart);
        searchEnd = uri.length();
    } else
        searchStart = searchEnd = 0;
    if (url.hashStart < url.hashEnd) {
        hashStart = uri.length();
        uri += percentEncode(url.url, url.hashStart, url.hashEnd - url.hashStart);
        hashEnd = uri.length();
    } else
        hashStart = hashEnd = 0;
}

std::string URI::getPort() const
{
    if (portStart < portEnd)
        return uri.substr(portStart, portEnd - portStart);
    if (!uri.compare(0, 5, "http:"))
        return "80";
    if (!uri.compare(0, 6, "https:"))
        return "443";
    return "";
}

}}}}  // org::w3c::dom::bootstrap
<|endoftext|>


<commit_before>#include <iostream>		//Always needed
#include <random>		//PRNG stuff
#include <algorithm>	//Transform function
#include <fstream>		//File I/O
#include <iomanip>		//Convenient spacing
#include <string>		//Manipulate strings
using namespace std;

void MakeLine(int lineLength);
void PrintAttempt(int attemptAmount);
void EndProgram(string givenReason);
bool Prompt(string type, bool& choice);
void GeneratePass(int passLength, int runAmount, bool wantLower, bool wantUpper, bool wantSymbols, ostream& outstream);

int main()
{
	//Declare and initialize variables
	int length = 0;						//Length of password to be generated
	int attempts = 0;					//Amount of attempts for length input
	int amountGen = 0;					//Amount of passwords to generate
	bool failure = false;				//Failure to input the length
	bool smallAlpha = false;			//Inclusion of lowercase letters
	bool largeAlpha = false;			//Inclusion of uppercase letters
	bool symbols = false;				//Whether or not to include symbols
	ofstream outFile;					//The stream for the output file
	char outName[80] = { '\0' };		//The name of the output file

	//Give the header for the program
	MakeLine(35);
	cout << endl << "==== RANDOM PASSWORD GENERATOR ====" << endl;
	MakeLine(35);

	//Request password length
	cout << endl << "Input integer (8 to 256) for length" << endl;

	while (attempts <= 6)
	{
		cin.clear();
		cin.sync();
		MakeLine(35);
		cout << endl;

		//Line for amount of attempts
		PrintAttempt(attempts);
		cout << "> ";

		if (!(cin >> length))
		{
			if (attempts < 6)
			{
				cerr << "ERROR: Not an integer!" << endl << endl;
				attempts++;
				continue;
			}
			else
			{
				failure = true;
				break;
			}

		}
		else if (length < 8 || length > 256)
		{
			if (attempts < 6)
			{
				cerr << "ERROR: Not within specified range!" << endl << endl;
				attempts++;
				continue;
			}
			else
			{
				failure = true;
				break;
			}
		}
		else break;
	}

	//Check if too many attempts have been performed
	if (failure == true)
	{
		EndProgram("Too many attempts!");
		return -1;
	}

	//Check for wanting letters and symbols
	smallAlpha = Prompt("lowercase letters", smallAlpha);
	largeAlpha = Prompt("uppercase letters", largeAlpha);
	symbols = Prompt("symbols", symbols);

	//Request amount of passwords to generate
	while (amountGen < 1 || amountGen > 100)
	{
		cin.clear();
		cin.sync();

		//Prints the prompt
		cout << endl;
		MakeLine(35);
		cout << endl << "Passwords to generate (1 to 100)" << endl;
		MakeLine(35);
		cout << endl;
		PrintAttempt(attempts);
		cout << "> ";
		cin >> amountGen;

		//Check range
		if (amountGen < 1 || amountGen > 100)
		{
			if (attempts < 6)
			{
				cerr << "ERROR: Not within specified range!" << endl;
				attempts++;
				continue;
			}
			else
			{
				failure = true;
				break;
			}
		}
		else break;
	}

	//Check if too many attempts have been performed
	if (failure == true)
	{
		EndProgram("Too many attempts!");
		return -1;
	}
	//Request output file name
	MakeLine(35);
	cout << endl << "Input an output file name: ";
	cin >> outName;

	//Try to create the file specified
	outFile.open(outName, ios::app);
	if (outFile.fail())
	{
		MakeLine(35);
		cerr << endl << "ERROR: Failed to create file " << outName << endl;
		MakeLine(35);
		EndProgram("Couldn't create file!");
		return -1;
	}

	//Send to function
	for (int pass = 1; pass <= amountGen; pass++)
	{
		if (pass == 1)
		{
			cout << endl;
			outFile << "= " << "Length: " << setw(4) << length << " ==== Amount: " << setw(4) << amountGen << ' ';
			for (int equalism = 33; equalism < (length - 1); equalism++)
			{
				outFile << '=';
			}
			outFile << '=' << endl;
		}
		GeneratePass(length, pass, smallAlpha, largeAlpha, symbols, outFile);
		MakeLine(13);
		cout << "Generated: " << setw(4) << pass << " / " << setw(4) << amountGen << endl;
	}
	outFile << endl;
	outFile.close();
	EndProgram("Success, enjoy your file.\n");
	return 0;
}

//Produces lines across screen
void MakeLine(int lineLength)
{
	for (int i = 0; i < lineLength; i++)
	{
		cout << '=';
	}
	cout << ' ';
}

void PrintAttempt(int attemptAmount)
{
	MakeLine(19);
	cout << "Attempts: " << attemptAmount << " / 6" << endl;
	if (attemptAmount == 6)
	{
		cout << "[FINAL] ";
	}
}

//Prints failure message and ends program
void EndProgram(string givenReason)
{
	//Ensure nothing remains in the input stream
	cin.clear();
	cin.sync();

	cout << endl << givenReason << endl
		<< "Press Enter / Return key";
	cin.get();
}

bool Prompt(string type, bool& choice)
{
	//Initialize variable
	string ask = "\0";

	//Print prompt
	cout << endl;
	MakeLine(35);
	cout << endl << "Should " << type << " be included?" << endl << "> ";
	cin.clear();
	cin.sync();
	while (ask == "\0") {
		getline(cin, ask);
	}

	//Convert input to lowercase
	transform(ask.begin(), ask.end(), ask.begin(), ::tolower);

	//Convert type to capital letters
	transform(type.begin(), type.end(), type.begin(), ::toupper);

	cout << "[STATUS: " << type;

	//Check input
	try {
		if (ask == "true" || ask == "yes" || ask == "affirmative" || ask == "yeah" || ask.at(0) == 'y')
		{
			cout << " ENABLED]" << endl;
			return true;
		}
		else if (ask == "ayy lmao")
		{
			cout << " ARE FOR HUMANS]" << endl
				<< "[THEREFORE, NOT INCLUDED]" << endl;
			return false;
		}
		else
		{
			cout << " DISABLED]" << endl;
			return false;
		}
	}
	catch (...)
	{
		cerr << "[ERROR - DEFAULTING TO FALSE]" << endl;
		return false;
	}
}

//Function to generate password
void GeneratePass(int passLength, int runAmount, bool wantLower, bool wantUpper, bool wantSymbols, ostream& outstream)
{
	//Initializes random number generator
	random_device rd;
	mt19937 mt(rd());

	//Provides boundaries for where to distribute numbers
	uniform_int_distribution<int> numDist(0, 9);		//Random distribution for numbers
	uniform_int_distribution<int> letDist(0, 25);		//Random distribution for letters
	uniform_int_distribution<int> symDist(0, 13);		//Random distribution for symbols

	//Determines which options can be used for the output
	vector<int> choices = {1};				//Always include numbers
	if (wantLower) choices.push_back(2);	//Include lowercase
	if (wantUpper) choices.push_back(3);	//Include uppercase
	if (wantSymbols) choices.push_back(4);	//Include symbols
	uniform_int_distribution<int> typeDist(0, choices.size() - 1);

	//Storage of characters available
	char lowerCase[26] = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z' };
	char upperCase[26] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z' };
	char symbo[14] = { '!', '#', '@', '~', '$', '^', '.', ',', '-', '+', '%', '?', '*', '=' };

	//Prints to output file
	for (int p = 0; p < passLength; p++)
	{
		switch (choices[typeDist(mt)])
		{
		case 1:			//Numbers
			outstream << numDist(mt);
			break;
		case 2:			//Lowercase
			outstream << lowerCase[letDist(mt)];
			break;
		case 3:			//Uppercase
			outstream << upperCase[letDist(mt)];
			break;
		case 4:			//Symbols
			outstream << symbo[symDist(mt)];
			break;
		}
	}
	outstream << endl;
}<commit_msg>Revisions<commit_after>#include <iostream>		//Always needed
#include <random>		//PRNG stuff
#include <algorithm>	//Transform function
#include <fstream>		//File I/O
#include <iomanip>		//Convenient spacing
#include <string>		//Manipulate strings

void MakeLine(int lineLength);
void PrintAttempt(int attemptAmount);
void EndProgram(std::string givenReason);
bool Prompt(std::string type, bool &choice);
void GeneratePass(int passLength, int runAmount, bool wantLower, bool wantUpper, bool wantSymbols, std::ostream &outstream);

int main()
{
	//Declare and initialize variables
	int length = 0;						//Length of password to be generated
	int attempts = 0;					//Amount of attempts for length input
	int amountGen = 0;					//Amount of passwords to generate
	bool failure = false;				//Failure to input the length
	bool smallAlpha = false;			//Inclusion of lowercase letters
	bool largeAlpha = false;			//Inclusion of uppercase letters
	bool symbols = false;				//Whether or not to include symbols
	bool correctAmount = false;			//Whether or not valid amount was given
	std::ofstream outFile;				//The stream for the output file
	char outName[80] = { '\0' };		//The name of the output file

	//Give the header for the program
	MakeLine(35);
	std::cout << std::endl << "==== RANDOM PASSWORD GENERATOR ====" << std::endl;
	MakeLine(35);

	//Request password length
	std::cout << std::endl << "Input integer (8 to 256) for length" << std::endl;

	while (attempts <= 6)
	{
		std::cin.clear();
		std::cin.sync();
		MakeLine(35);
		std::cout << std::endl;

		//Line for amount of attempts
		PrintAttempt(attempts);
		std::cout << "> ";

		if (!(std::cin >> length))
		{
			if (attempts < 6)
			{
				std::cerr << "ERROR: Not an integer!" << std::endl << std::endl;
				attempts++;
				continue;
			}
			else
			{
				failure = true;
				break;
			}

		}
		else if (length < 8 || length > 256)
		{
			if (attempts < 6)
			{
				std::cerr << "ERROR: Not within specified range!" << std::endl << std::endl;
				attempts++;
				continue;
			}
			else
			{
				failure = true;
				break;
			}
		}
		else break;
	}

	//Check if too many attempts have been performed
	if (failure == true)
	{
		EndProgram("Too many attempts!");
		return -1;
	}

	//Check for wanting letters and symbols
	smallAlpha = Prompt("lowercase letters", smallAlpha);
	largeAlpha = Prompt("uppercase letters", largeAlpha);
	symbols = Prompt("symbols", symbols);

	//Request amount of passwords to generate
	do
	{
		//Reset for loop
		correctAmount = false;
		std::cin.clear();
		std::cin.sync();

		//Prints the prompt
		std::cout << std::endl;
		MakeLine(35);
		std::cout << std::endl << "How many passwords to generate " << std::endl
			<< "Input an integer (1 to 100)" << std::endl;
		MakeLine(35);
		std::cout << std::endl;
		PrintAttempt(attempts);
		std::cout << "> ";
		try
		{
			std::cin >> amountGen;

			//Check range
			if (amountGen < 1 || amountGen > 100)
			{
				if (attempts < 6)
				{
					std::cerr << "ERROR: Not within specified range!" << std::endl;
					attempts++;
					continue;
				}
				else
				{
					failure = true;
					break;
				}
			}
			else correctAmount = true;
		}
		catch (...)
		{
			std::cerr << "ERROR: Could not understand input!" << std::endl;
			attempts++;
			if (attempts >= 6)
			{
				failure = true;
				break;
			}
		}
	} while (correctAmount == false);

	//Check if too many attempts have been performed
	if (failure == true)
	{
		EndProgram("Too many attempts!");
		return -1;
	}
	//Request output file name
	MakeLine(35);
	std::cout << std::endl << "Input a file name to use for output" << std::endl << "> ";
	try
	{
		std::cin >> outName;

		//Try to create the file specified
		outFile.open(outName, std::ios::app);
		if (outFile.fail())
		{
			outFile.close();
			std::cerr << "ERROR: Failed to create file " << outName << std::endl;
			MakeLine(35);
			EndProgram("Couldn't create file!");
			return -1;
		}
	}
	catch (...)
	{
		outFile.close();
		std::cerr << "ERROR: Critical failure, shutting down" << std::endl;
		EndProgram("Critical failure!");
		return -1;
	}

	//Send to function
	for (int pass = 1; pass <= amountGen; pass++)
	{
		if (pass == 1)
		{
			std::cout << std::endl;
			outFile << "= " << "Length: " << std::setw(4) << length << " ==== Amount: " << std::setw(4) << amountGen << ' ';
			for (int equalism = 33; equalism < (length - 1); equalism++)
			{
				outFile << '=';
			}
			outFile << '=' << std::endl;
		}
		GeneratePass(length, pass, smallAlpha, largeAlpha, symbols, outFile);
		MakeLine(13);
		std::cout << "Generated: " << std::setw(4) << pass << " / " << std::setw(4) << amountGen << std::endl;
	}
	outFile << std::endl;
	outFile.close();
	EndProgram("Success, enjoy your file.\n");
	return 0;
}

//Produces lines across screen
void MakeLine(int lineLength)
{
	for (int i = 0; i < lineLength; i++)
	{
		std::cout << '=';
	}
	std::cout << ' ';
}

void PrintAttempt(int attemptAmount)
{
	MakeLine(19);
	std::cout << "Attempts: " << attemptAmount << " / 6" << std::endl;
	if (attemptAmount == 6)
	{
		std::cout << "[FINAL] ";
	}
}

//Prints failure message and ends program
void EndProgram(std::string givenReason)
{
	//Ensure nothing remains in the input stream
	std::cin.clear();
	std::cin.sync();

	std::cout << std::endl << givenReason << std::endl
		<< "Press Enter / Return key";
	std::cin.get();
}

//Asks if a type is desired
bool Prompt(std::string type, bool &choice)
{
	//Initialize variable
	std::string ask = "\0";

	//Print prompt
	std::cout << std::endl;
	MakeLine(35);
	std::cout << std::endl << "Should " << type << " be included?" << std::endl << "> ";
	std::cin.clear();
	std::cin.sync();
	while (ask == "\0") {
		getline(std::cin, ask);
	}

	//Convert input to lowercase
	transform(ask.begin(), ask.end(), ask.begin(), ::tolower);

	//Convert type to capital letters
	transform(type.begin(), type.end(), type.begin(), ::toupper);

	std::cout << "[STATUS: " << type;

	//Check input
	try {
		if (ask == "true" || ask == "yes" || ask == "affirmative" || ask == "yeah" || ask.at(0) == 'y')
		{
			std::cout << " ENABLED]" << std::endl;
			return true;
		}
		else
		{
			std::cout << " DISABLED]" << std::endl;
			return false;
		}
	}
	catch (...)
	{
		std::cerr << "[ERROR - DEFAULTING TO FALSE]" << std::endl;
		return false;
	}
}

//Function to generate password
void GeneratePass(int passLength, int runAmount, bool wantLower, bool wantUpper, bool wantSymbols, std::ostream &outstream)
{
	//Initializes random number generator
	std::random_device rd;
	std::mt19937 mt(rd());

	//Provides boundaries for where to distribute numbers
	std::uniform_int_distribution<int> numDist(0, 9);		//Random distribution for numbers
	std::uniform_int_distribution<int> letDist(0, 25);		//Random distribution for letters
	std::uniform_int_distribution<int> symDist(0, 13);		//Random distribution for symbols

	//Determines which options can be used for the output
	std::vector<int> choices = {1};				//Always include numbers
	if (wantLower) choices.push_back(2);	//Include lowercase
	if (wantUpper) choices.push_back(3);	//Include uppercase
	if (wantSymbols) choices.push_back(4);	//Include symbols
	std::uniform_int_distribution<int> typeDist(0, choices.size() - 1);

	//Storage of characters available
	char lowerCase[26] = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z' };
	char upperCase[26] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z' };
	char symbo[14] = { '!', '#', '@', '~', '$', '^', '.', ',', '-', '+', '%', '?', '*', '=' };

	//Prints to output file
	for (int p = 0; p < passLength; p++)
	{
		switch (choices[typeDist(mt)])
		{
		case 1:			//Numbers
			outstream << numDist(mt);
			break;
		case 2:			//Lowercase
			outstream << lowerCase[letDist(mt)];
			break;
		case 3:			//Uppercase
			outstream << upperCase[letDist(mt)];
			break;
		case 4:			//Symbols
			outstream << symbo[symDist(mt)];
			break;
		}
	}
	outstream << std::endl;
}<|endoftext|>


<commit_before>// $Id$
// Main authors: Matevz Tadel & Alja Mrak-Tadel: 2006, 2007

/**************************************************************************
 * Copyright(c) 1998-2008, ALICE Experiment at CERN, all rights reserved. *
 * See http://aliceinfo.cern.ch/Offline/AliRoot/License.html for          *
 * full copyright notice.                                                 *
 **************************************************************************/

#if !defined(__CINT__) || defined(__MAKECINT__)
#include <TFile.h>
#include <TGLViewer.h>
#include <TEveManager.h>
#include <TEveElement.h>
#include <TEveGeoShape.h>
#include <TEveGeoShapeExtract.h>
#endif

TEveGeoShape* geom_gentle_trd()
{
  TFile f("$ALICE_ROOT/EVE/alice-data/gentle_geo_trd.root");
  TEveGeoShapeExtract* gse = (TEveGeoShapeExtract*) f.Get("Gentle TRD");
  TEveGeoShape* gsre = TEveGeoShape::ImportShapeExtract(gse);
  gEve->AddGlobalElement(gsre);
  f.Close();

  const Int_t smInstalled[]={0, 1, 7, 8, 9, 10, 11, 15, 16, 17};
  const Int_t nInstalled = static_cast<Int_t>(sizeof(smInstalled)/sizeof(Int_t));
  Int_t sm = 0;
  // Fix visibility, color and transparency
  gsre->SetRnrSelf(kFALSE);
  for (TEveElement::List_i i = gsre->BeginChildren(); i != gsre->EndChildren(); ++i)
  {
    TEveGeoShape* lvl1 = (TEveGeoShape*) *i;
    lvl1->SetRnrSelf(kFALSE);
    for (TEveElement::List_i j = lvl1->BeginChildren(); j != lvl1->EndChildren(); ++j)
    {
      TEveGeoShape* lvl2 = (TEveGeoShape*) *j;
      lvl2->SetRnrSelf(kFALSE);
      for(Int_t ism(nInstalled); ism--;){
        if ( sm == smInstalled[ism] ){
          lvl2->SetRnrSelf(kTRUE);
          break;
        }
      }
      lvl2->SetMainColor(3);
      lvl2->SetMainTransparency(80);

      ++sm;
    }
  }

  return gsre;
}
<commit_msg>update installed supermodules for 2013<commit_after>// $Id$
// Main authors: Matevz Tadel & Alja Mrak-Tadel: 2006, 2007

/**************************************************************************
 * Copyright(c) 1998-2008, ALICE Experiment at CERN, all rights reserved. *
 * See http://aliceinfo.cern.ch/Offline/AliRoot/License.html for          *
 * full copyright notice.                                                 *
 **************************************************************************/

#if !defined(__CINT__) || defined(__MAKECINT__)
#include <TFile.h>
#include <TGLViewer.h>
#include <TEveManager.h>
#include <TEveElement.h>
#include <TEveGeoShape.h>
#include <TEveGeoShapeExtract.h>
#endif

TEveGeoShape* geom_gentle_trd()
{
  TFile f("$ALICE_ROOT/EVE/alice-data/gentle_geo_trd.root");
  TEveGeoShapeExtract* gse = (TEveGeoShapeExtract*) f.Get("Gentle TRD");
  TEveGeoShape* gsre = TEveGeoShape::ImportShapeExtract(gse);
  gEve->AddGlobalElement(gsre);
  f.Close();

  const Int_t smInstalled[]={0, 1, 2, 3, 6, 7, 8, 9, 10, 11, 15, 16, 17};
  const Int_t nInstalled = static_cast<Int_t>(sizeof(smInstalled)/sizeof(Int_t));
  Int_t sm = 0;
  // Fix visibility, color and transparency
  gsre->SetRnrSelf(kFALSE);
  for (TEveElement::List_i i = gsre->BeginChildren(); i != gsre->EndChildren(); ++i)
  {
    TEveGeoShape* lvl1 = (TEveGeoShape*) *i;
    lvl1->SetRnrSelf(kFALSE);
    for (TEveElement::List_i j = lvl1->BeginChildren(); j != lvl1->EndChildren(); ++j)
    {
      TEveGeoShape* lvl2 = (TEveGeoShape*) *j;
      lvl2->SetRnrSelf(kFALSE);
      for(Int_t ism(nInstalled); ism--;){
        if ( sm == smInstalled[ism] ){
          lvl2->SetRnrSelf(kTRUE);
          break;
        }
      }
      lvl2->SetMainColor(3);
      lvl2->SetMainTransparency(80);

      ++sm;
    }
  }

  return gsre;
}
<|endoftext|>


<commit_before>///
/// @file  S2LoadBalancer.cpp
/// @brief The S2LoadBalancer evenly distributes the work load between
///        the threads in the computation of the special leaves.
///
/// Simply parallelizing the computation of the special leaves in the
/// Lagarias-Miller-Odlyzko and Deleglise-Rivat algorithms by
/// subdividing the sieve interval by the number of threads into
/// equally sized subintervals does not scale because the distribution
/// of the special leaves is highly skewed and most special leaves are
/// in the first few segments whereas later on there are very few
/// special leaves.
///
/// Based on the above observations it is clear that we need some kind
/// of load balancing in order to scale our parallel algorithm for
/// computing special leaves. Below are the ideas I used to develop a
/// load balancing algorithm that achieves a high load balance by
/// dynamically increasing or decreasing the interval size based on
/// the relative standard deviation of the thread run-times.
///
/// 1) Start with a tiny segment size of x^(1/3) / (log x * log log x)
///    and one segment per thread. Our algorithm uses equally sized
///    intervals, for each thread the interval_size is
///    segment_size * segments_per_thread and the threads process
///    adjacent intervals i.e.
///    [base + interval_size * thread_id, base + interval_size * (thread_id + 1)].
///
/// 2) If the relative standard deviation of the thread run-times is
///    large then we know the special leaves are distributed unevenly,
///    else if the relative standard deviation is low the special
///    leaves are more evenly distributed.
///
/// 3) If the special leaves are distributed unevenly then we can
///    increase the load balance by decreasing the interval_size.
///    Contrary if the special leaves are more evenly distributed
///    we can increase the interval_size in order to improve the
///    algorithm's efficiency.
///
/// 4) We can't use a static threshold for as to when the relative
///    standard deviation is low or large as this threshold varies for
///    different PC architectures. So instead we compare the current
///    relative standard deviation to the previous one in order to
///    decide whether to increase or decrease the interval_size.
///
/// Copyright (C) 2016 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#include <S2LoadBalancer.hpp>
#include <primecount-internal.hpp>
#include <aligned_vector.hpp>
#include <pmath.hpp>
#include <int128.hpp>

#include <stdint.h>
#include <algorithm>
#include <cmath>

using namespace std;
using namespace primecount;

namespace {

double get_average(aligned_vector<double>& timings)
{
  size_t n = timings.size();
  double sum = 0;

  for (size_t i = 0; i < n; i++)
    sum += timings[i];

  return sum / n;
}

double relative_standard_deviation(aligned_vector<double>& timings)
{
  size_t n = timings.size();
  double average = get_average(timings);
  double sum = 0;

  if (average == 0)
    return 0;

  for (size_t i = 0; i < n; i++)
  {
    double mean = timings[i] - average;
    sum += mean * mean;
  }

  double std_dev = sqrt(sum / max(1.0, n - 1.0));
  double rsd = 100 * std_dev / average;

  return rsd;
}

} // namespace

namespace primecount {

S2LoadBalancer::S2LoadBalancer(maxint_t x,
                               int64_t y,
                               int64_t z,
                               int64_t threads) :
  x_((double) x),
  y_((double) y),
  z_((double) z),
  rsd_(40),
  avg_seconds_(0),
  count_(0),
  sqrtz_(isqrt(z))
{
  init(threads);
}

S2LoadBalancer::S2LoadBalancer(maxint_t x,
                               int64_t y,
                               int64_t z,
                               int64_t threads,
                               double rsd) :
  x_((double) x),
  y_((double) y),
  z_((double) z),
  rsd_(rsd),
  avg_seconds_(0),
  count_(0),
  sqrtz_(isqrt(z))
{
  init(threads);
}

void S2LoadBalancer::init(int64_t threads)
{
  // determined by benchmarking
  double log_threads = max(1.0, log((double) threads));
  decrease_dividend_ = max(0.5, log_threads / 3);
  min_seconds_ = 0.02 * log_threads;
  update_min_size(log(x_) * log(log(x_)));

  double alpha = get_alpha(x_, y_);
  smallest_hard_leaf_ = (int64_t) (x_ / (y_ * sqrt(alpha) * iroot<6>(x_)));
}

double S2LoadBalancer::get_rsd() const
{
  return rsd_;
}

int64_t S2LoadBalancer::get_min_segment_size() const
{
  return min_size_;
}

bool S2LoadBalancer::decrease_size(double seconds,
                                   double decrease) const
{
  return seconds > min_seconds_ &&
         rsd_ > decrease;
}

bool S2LoadBalancer::increase_size(double seconds,
                                   double decrease) const
{
  return seconds < avg_seconds_ &&
        !decrease_size(seconds, decrease);
}

/// Used to decide whether to use a smaller or larger
/// segment_size and/or segments_per_thread.
///
double S2LoadBalancer::get_decrease_threshold(double seconds) const
{
  double log_seconds = max(min_seconds_, log(seconds));
  double dont_decrease = min(decrease_dividend_ / (seconds * log_seconds), rsd_);
  return rsd_ + dont_decrease;
}

void S2LoadBalancer::update_avg_seconds(double seconds)
{
  seconds = max(seconds, min_seconds_);
  double dividend = avg_seconds_ * count_ + seconds;
  avg_seconds_ = dividend / ++count_;
}

void S2LoadBalancer::update_min_size(double divisor)
{
  int64_t size = (int64_t) (sqrtz_ / max(1.0, divisor));
  int64_t min_size = 1 << 9;
  min_size_ = max(size, min_size);
  min_size_ = next_power_of_2(min_size_);
}

/// Balance the load in the computation of the special leaves
/// by dynamically adjusting the segment_size and segments_per_thread.
/// @param timings  Timings of the threads.
///
void S2LoadBalancer::update(int64_t low,
                            int64_t threads,
                            int64_t* segment_size,
                            int64_t* segments_per_thread,
                            aligned_vector<double>& timings)
{
  double seconds = get_average(timings);
  update_avg_seconds(seconds);
  double decrease_threshold = get_decrease_threshold(seconds);
  rsd_ = max(0.1, relative_standard_deviation(timings));

  // 1 segment per thread
  if (*segment_size < sqrtz_)
  {
    if (increase_size(seconds, decrease_threshold))
      *segment_size <<= 1;
    else if (decrease_size(seconds, decrease_threshold))
      if (*segment_size > min_size_)
        *segment_size >>= 1;
  }
  // many segments per thread
  else if (low > smallest_hard_leaf_)
  {
    double factor = decrease_threshold / rsd_;
    factor = in_between(0.5, factor, 2);
    double n = *segments_per_thread * factor;
    n = max(1.0, n);

    if ((n < *segments_per_thread && seconds > min_seconds_) ||
        (n > *segments_per_thread && seconds < avg_seconds_))
    {
      *segments_per_thread = (int) n;
    }
  }

  int64_t high = low + *segment_size * *segments_per_thread * threads;

  // near smallest_hard_leaf_ the hard special leaves
  // are distributed unevenly so use min_size_
  if (low <= smallest_hard_leaf_ &&
      high > smallest_hard_leaf_)
  {
    *segment_size = min_size_;
    high = low + *segment_size * *segments_per_thread * threads;
  }

  // slightly increase min_size_
  if (high >= smallest_hard_leaf_)
  {
    update_min_size(log(y_));
    *segment_size = max(min_size_, *segment_size);
  }
}

} // namespace
<commit_msg>Refactoring<commit_after>///
/// @file  S2LoadBalancer.cpp
/// @brief The S2LoadBalancer evenly distributes the work load between
///        the threads in the computation of the special leaves.
///
/// Simply parallelizing the computation of the special leaves in the
/// Lagarias-Miller-Odlyzko and Deleglise-Rivat algorithms by
/// subdividing the sieve interval by the number of threads into
/// equally sized subintervals does not scale because the distribution
/// of the special leaves is highly skewed and most special leaves are
/// in the first few segments whereas later on there are very few
/// special leaves.
///
/// Based on the above observations it is clear that we need some kind
/// of load balancing in order to scale our parallel algorithm for
/// computing special leaves. Below are the ideas I used to develop a
/// load balancing algorithm that achieves a high load balance by
/// dynamically increasing or decreasing the interval size based on
/// the relative standard deviation of the thread run-times.
///
/// 1) Start with a tiny segment size of x^(1/3) / (log x * log log x)
///    and one segment per thread. Our algorithm uses equally sized
///    intervals, for each thread the interval_size is
///    segment_size * segments_per_thread and the threads process
///    adjacent intervals i.e.
///    [base + interval_size * thread_id, base + interval_size * (thread_id + 1)].
///
/// 2) If the relative standard deviation of the thread run-times is
///    large then we know the special leaves are distributed unevenly,
///    else if the relative standard deviation is low the special
///    leaves are more evenly distributed.
///
/// 3) If the special leaves are distributed unevenly then we can
///    increase the load balance by decreasing the interval_size.
///    Contrary if the special leaves are more evenly distributed
///    we can increase the interval_size in order to improve the
///    algorithm's efficiency.
///
/// 4) We can't use a static threshold for as to when the relative
///    standard deviation is low or large as this threshold varies for
///    different PC architectures. So instead we compare the current
///    relative standard deviation to the previous one in order to
///    decide whether to increase or decrease the interval_size.
///
/// Copyright (C) 2016 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#include <S2LoadBalancer.hpp>
#include <primecount-internal.hpp>
#include <aligned_vector.hpp>
#include <pmath.hpp>
#include <int128.hpp>

#include <stdint.h>
#include <algorithm>
#include <cmath>

using namespace std;
using namespace primecount;

namespace {

double get_average(aligned_vector<double>& timings)
{
  size_t n = timings.size();
  double sum = 0;

  for (size_t i = 0; i < n; i++)
    sum += timings[i];

  return sum / n;
}

double relative_standard_deviation(aligned_vector<double>& timings)
{
  size_t n = timings.size();
  double average = get_average(timings);
  double sum = 0;

  if (average == 0)
    return 0;

  for (size_t i = 0; i < n; i++)
  {
    double mean = timings[i] - average;
    sum += mean * mean;
  }

  double std_dev = sqrt(sum / max(1.0, n - 1.0));
  double rsd = 100 * std_dev / average;

  return rsd;
}

} // namespace

namespace primecount {

S2LoadBalancer::S2LoadBalancer(maxint_t x,
                               int64_t y,
                               int64_t z,
                               int64_t threads) :
  x_((double) x),
  y_((double) y),
  z_((double) z),
  rsd_(40),
  avg_seconds_(0),
  count_(0),
  sqrtz_(isqrt(z))
{
  init(threads);
}

S2LoadBalancer::S2LoadBalancer(maxint_t x,
                               int64_t y,
                               int64_t z,
                               int64_t threads,
                               double rsd) :
  x_((double) x),
  y_((double) y),
  z_((double) z),
  rsd_(rsd),
  avg_seconds_(0),
  count_(0),
  sqrtz_(isqrt(z))
{
  init(threads);
}

void S2LoadBalancer::init(int64_t threads)
{
  // determined by benchmarking
  double log_threads = max(1.0, log((double) threads));
  decrease_dividend_ = max(0.5, log_threads / 3);
  min_seconds_ = 0.02 * log_threads;
  update_min_size(log(x_) * log(log(x_)));

  double alpha = get_alpha(x_, y_);
  smallest_hard_leaf_ = (int64_t) (x_ / (y_ * sqrt(alpha) * iroot<6>(x_)));
}

double S2LoadBalancer::get_rsd() const
{
  return rsd_;
}

int64_t S2LoadBalancer::get_min_segment_size() const
{
  return min_size_;
}

bool S2LoadBalancer::decrease_size(double seconds,
                                   double decrease) const
{
  return seconds > min_seconds_ &&
         rsd_ > decrease;
}

bool S2LoadBalancer::increase_size(double seconds,
                                   double decrease) const
{
  return seconds < avg_seconds_ &&
        !decrease_size(seconds, decrease);
}

/// Used to decide whether to use a smaller or larger
/// segment_size and/or segments_per_thread.
///
double S2LoadBalancer::get_decrease_threshold(double seconds) const
{
  double log_seconds = max(min_seconds_, log(seconds));
  double dont_decrease = min(decrease_dividend_ / (seconds * log_seconds), rsd_);
  return rsd_ + dont_decrease;
}

void S2LoadBalancer::update_avg_seconds(double seconds)
{
  seconds = max(seconds, min_seconds_);
  double dividend = avg_seconds_ * count_ + seconds;
  avg_seconds_ = dividend / ++count_;
}

void S2LoadBalancer::update_min_size(double divisor)
{
  int64_t size = (int64_t) (sqrtz_ / max(1.0, divisor));
  int64_t min_size = 1 << 9;
  min_size_ = max(size, min_size);
  min_size_ = next_power_of_2(min_size_);
}

/// Balance the load in the computation of the special leaves
/// by dynamically adjusting the segment_size and segments_per_thread.
/// @param timings  Timings of the threads.
///
void S2LoadBalancer::update(int64_t low,
                            int64_t threads,
                            int64_t* segment_size,
                            int64_t* segments_per_thread,
                            aligned_vector<double>& timings)
{
  double seconds = get_average(timings);
  update_avg_seconds(seconds);
  double decrease_threshold = get_decrease_threshold(seconds);
  rsd_ = max(0.1, relative_standard_deviation(timings));

  // 1 segment per thread
  if (*segment_size < sqrtz_)
  {
    if (increase_size(seconds, decrease_threshold))
      *segment_size <<= 1;
    else if (decrease_size(seconds, decrease_threshold))
      if (*segment_size > min_size_)
        *segment_size >>= 1;
  }
  // many segments per thread
  else if (low > smallest_hard_leaf_)
  {
    double factor = decrease_threshold / rsd_;
    factor = in_between(0.5, factor, 2);
    double n = *segments_per_thread * factor;
    n = max(1.0, n);

    if ((n < *segments_per_thread && seconds > min_seconds_) ||
        (n > *segments_per_thread && seconds < avg_seconds_))
    {
      *segments_per_thread = (int) n;
    }
  }

  int64_t interval_per_thread = *segment_size * *segments_per_thread;
  int64_t high = low + interval_per_thread * threads;

  // near smallest_hard_leaf_ the hard special leaves
  // are distributed unevenly so use min_size_
  if (low <= smallest_hard_leaf_ &&
      high > smallest_hard_leaf_)
  {
    *segment_size = min_size_;
    interval_per_thread = *segment_size * *segments_per_thread;
    high = low + interval_per_thread * threads;
  }

  // slightly increase min_size_
  if (high >= smallest_hard_leaf_)
  {
    update_min_size(log(y_));
    *segment_size = max(min_size_, *segment_size);
  }
}

} // namespace
<|endoftext|>


<commit_before>///
/// @file  S2LoadBalancer.cpp
/// @brief Dynamically increase or decrease the segment_size or the
///        segments_per_thread in order to improve the load balancing
///        in the computation of the special leaves. The algorithm
///        calculates the relative standard deviation of the timings
///        of the individual threads and then decides whether to
///        assign more work (low relative standard deviation) or less
///        work (large relative standard deviation) to the threads.
///
/// Copyright (C) 2014 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#include <S2LoadBalancer.hpp>
#include <primecount-internal.hpp>
#include <aligned_vector.hpp>
#include <pmath.hpp>
#include <int128.hpp>

#include <stdint.h>
#include <algorithm>
#include <cmath>

using namespace std;
using namespace primecount;

namespace {

double get_average(aligned_vector<double>& timings)
{
  size_t n = timings.size();
  double sum = 0;

  for (size_t i = 0; i < n; i++)
    sum += timings[i];

  return sum / n;
}

double relative_standard_deviation(aligned_vector<double>& timings)
{
  size_t n = timings.size();
  double average = get_average(timings);
  double sum = 0;

  if (average == 0)
    return 0;

  for (size_t i = 0; i < n; i++)
  {
    double mean = timings[i] - average;
    sum += mean * mean;
  }

  double std_dev = sqrt(sum / max(1.0, n - 1.0));
  double rsd = 100 * std_dev / average;

  return rsd;
}

} // namespace

namespace primecount {

S2LoadBalancer::S2LoadBalancer(maxint_t x, int64_t z, int64_t threads) :
  x_((double) x),
  z_((double) z),
  rsd_(40),
  avg_seconds_(0),
  count_(0)
{
  double log_threads = max(1.0, log((double) threads));
  min_seconds_ = 0.02 * log_threads;
  max_size_ = next_power_of_2(isqrt(z));
  update_min_size(log(x_) * log(log(x_)));
}

double S2LoadBalancer::get_rsd() const
{
  return rsd_;
}

int64_t S2LoadBalancer::get_min_segment_size() const
{
  return min_size_;
}

bool S2LoadBalancer::decrease_size(double seconds, double decrease) const
{
  return seconds > min_seconds_ &&
         rsd_ > decrease;
}

bool S2LoadBalancer::increase_size(double seconds, double decrease) const
{
  return seconds < avg_seconds_ &&
        !decrease_size(seconds, decrease);
}

void S2LoadBalancer::update_avg_seconds(double seconds)
{
  seconds = max(seconds, min_seconds_);
  double dividend = avg_seconds_ * count_ + seconds;
  avg_seconds_ = dividend / (count_ + 1);
  count_++;
}

void S2LoadBalancer::update_min_size(double divisor)
{
  double size = sqrt(z_) / max(1.0, divisor);
  min_size_ = max((int64_t) (1 << 9), (int64_t) size);
  min_size_ = next_power_of_2(min_size_);
}

/// Used to decide whether to use a smaller or larger
/// segment_size and/or segments_per_thread.
///
double S2LoadBalancer::get_decrease_threshold(double seconds, int64_t threads) const
{
  double log_threads = log((double) threads);
  double log_seconds = max(min_seconds_, log(seconds));
  double dividend = max(0.1, log_threads / 4.0);
  double dont_decrease = min(dividend / (seconds * log_seconds), rsd_);
  return rsd_ + dont_decrease;
}

/// Balance the load in the computation of the special leaves
/// by dynamically adjusting the segment_size and segments_per_thread.
/// @param timings  Timings of the threads.
///
void S2LoadBalancer::update(int64_t low,
                            int64_t threads,
                            int64_t* segment_size,
                            int64_t* segments_per_thread,
                            aligned_vector<double>& timings)
{
  double seconds = get_average(timings);
  update_avg_seconds(seconds);
  double decrease_threshold = get_decrease_threshold(seconds, threads);
  rsd_ = max(0.1, relative_standard_deviation(timings));

  // if low > sqrt(z) we use a larger min_size_ as the
  // special leaves are distributed more evenly
  if (low > max_size_)
    update_min_size(log(x_));

  // 1 segment per thread
  if (*segment_size < max_size_)
  {
    if (increase_size(seconds, decrease_threshold))
      *segment_size <<= 1;
    else if (decrease_size(seconds, decrease_threshold))
      if (*segment_size > min_size_)
        *segment_size >>= 1;

    // near sqrt(z) there is a short peak of special
    // leaves so we use the minium segment size
    int64_t high = low + *segment_size * *segments_per_thread * threads;
    if (low <= max_size_ && high > max_size_)
      *segment_size = min_size_;
  }
  else // many segments per thread
  {
    double factor = decrease_threshold / rsd_;
    factor = in_between(0.5, factor, 2);
    double n = *segments_per_thread * factor;
    n = max(1.0, n);

    if ((n < *segments_per_thread && seconds > min_seconds_) ||
        (n > *segments_per_thread && seconds < avg_seconds_))
    {
      *segments_per_thread = (int) n;
    }
  }
}

} //namespace
<commit_msg>Improved minimum segment size<commit_after>///
/// @file  S2LoadBalancer.cpp
/// @brief Dynamically increase or decrease the segment_size or the
///        segments_per_thread in order to improve the load balancing
///        in the computation of the special leaves. The algorithm
///        calculates the relative standard deviation of the timings
///        of the individual threads and then decides whether to
///        assign more work (low relative standard deviation) or less
///        work (large relative standard deviation) to the threads.
///
/// Copyright (C) 2014 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#include <S2LoadBalancer.hpp>
#include <primecount-internal.hpp>
#include <aligned_vector.hpp>
#include <pmath.hpp>
#include <int128.hpp>

#include <stdint.h>
#include <algorithm>
#include <cmath>

using namespace std;
using namespace primecount;

namespace {

double get_average(aligned_vector<double>& timings)
{
  size_t n = timings.size();
  double sum = 0;

  for (size_t i = 0; i < n; i++)
    sum += timings[i];

  return sum / n;
}

double relative_standard_deviation(aligned_vector<double>& timings)
{
  size_t n = timings.size();
  double average = get_average(timings);
  double sum = 0;

  if (average == 0)
    return 0;

  for (size_t i = 0; i < n; i++)
  {
    double mean = timings[i] - average;
    sum += mean * mean;
  }

  double std_dev = sqrt(sum / max(1.0, n - 1.0));
  double rsd = 100 * std_dev / average;

  return rsd;
}

} // namespace

namespace primecount {

S2LoadBalancer::S2LoadBalancer(maxint_t x, int64_t z, int64_t threads) :
  x_((double) x),
  z_((double) z),
  rsd_(40),
  avg_seconds_(0),
  count_(0)
{
  double log_threads = max(1.0, log((double) threads));
  min_seconds_ = 0.02 * log_threads;
  max_size_ = next_power_of_2(isqrt(z));
  update_min_size(log(x_) * log(log(x_)));
}

double S2LoadBalancer::get_rsd() const
{
  return rsd_;
}

int64_t S2LoadBalancer::get_min_segment_size() const
{
  return min_size_;
}

bool S2LoadBalancer::decrease_size(double seconds, double decrease) const
{
  return seconds > min_seconds_ &&
         rsd_ > decrease;
}

bool S2LoadBalancer::increase_size(double seconds, double decrease) const
{
  return seconds < avg_seconds_ &&
        !decrease_size(seconds, decrease);
}

void S2LoadBalancer::update_avg_seconds(double seconds)
{
  seconds = max(seconds, min_seconds_);
  double dividend = avg_seconds_ * count_ + seconds;
  avg_seconds_ = dividend / (count_ + 1);
  count_++;
}

void S2LoadBalancer::update_min_size(double divisor)
{
  double size = sqrt(z_) / max(1.0, divisor);
  min_size_ = max((int64_t) (1 << 9), (int64_t) size);
  min_size_ = next_power_of_2(min_size_);
}

/// Used to decide whether to use a smaller or larger
/// segment_size and/or segments_per_thread.
///
double S2LoadBalancer::get_decrease_threshold(double seconds, int64_t threads) const
{
  double log_threads = log((double) threads);
  double log_seconds = max(min_seconds_, log(seconds));
  double dividend = max(0.1, log_threads / 4.0);
  double dont_decrease = min(dividend / (seconds * log_seconds), rsd_);
  return rsd_ + dont_decrease;
}

/// Balance the load in the computation of the special leaves
/// by dynamically adjusting the segment_size and segments_per_thread.
/// @param timings  Timings of the threads.
///
void S2LoadBalancer::update(int64_t low,
                            int64_t threads,
                            int64_t* segment_size,
                            int64_t* segments_per_thread,
                            aligned_vector<double>& timings)
{
  double seconds = get_average(timings);
  update_avg_seconds(seconds);
  double decrease_threshold = get_decrease_threshold(seconds, threads);
  rsd_ = max(0.1, relative_standard_deviation(timings));

  // if low > sqrt(z) we use a larger min_size_ as the
  // special leaves are distributed more evenly
  if (low > max_size_)
  {
    update_min_size(log(x_));
    *segment_size = max(*segment_size, min_size_);
  }

  // 1 segment per thread
  if (*segment_size < max_size_)
  {
    if (increase_size(seconds, decrease_threshold))
      *segment_size <<= 1;
    else if (decrease_size(seconds, decrease_threshold))
      if (*segment_size > min_size_)
        *segment_size >>= 1;

    // near sqrt(z) there is a short peak of special
    // leaves so we use the minium segment size
    int64_t high = low + *segment_size * *segments_per_thread * threads;
    if (low <= max_size_ && high > max_size_)
      *segment_size = min_size_;
  }
  else // many segments per thread
  {
    double factor = decrease_threshold / rsd_;
    factor = in_between(0.5, factor, 2);
    double n = *segments_per_thread * factor;
    n = max(1.0, n);

    if ((n < *segments_per_thread && seconds > min_seconds_) ||
        (n > *segments_per_thread && seconds < avg_seconds_))
    {
      *segments_per_thread = (int) n;
    }
  }
}

} //namespace
<|endoftext|>


<commit_before>//
// Created by Zal on 11/19/16.
//

#include <assert.h>
#include <utility>
#include "BinaryMatrix.h"

void BinaryMatrix::BinaryMatrix(int w, int h) {
    this->width = w;
    this->height = h;
    this->baseSize = sizeof(char) * 8;

    int n = w*h;
    this->dataLength = (n % baseSize == 0)? n/baseSize : n/baseSize +1;
    this->data = new char[dataLength];
}

void BinaryMatrix::~BinaryMatrix() {
    delete[] data;
}

void BinaryMatrix::T() {
    this->transposed = !this->transposed;
}

BinaryMatrix BinaryMatrix::binMultiply(const BinaryMatrix& other) {
    BinaryMatrix res(this->width, this->height);
    for(int i = 0; i < this->dataLength; ++i) {
        res.data[i] = !(this->data[i] ^ other.data[i]);
    }
    return res;
}

std::pair<int, int> BinaryMatrix::elem_accessor(int i, int rows, int cols, bool transposed) {
    if (transposed) {
        return std::make_pair(i % rows, i / rows);
    } else {
        return std::make_pair(i / cols, i % cols);
    }
}

char BinaryMatrix::get_bit(char elem, int bit_id) {
    return (elem >> (this->baseSize - bit_id)) & 1;
}

char BinaryMatrix::set_bit(char elem, int bit_id, char bit) {
    // assumes originally the bit is set to 0
    char mask = 1 << (this->baseSize - bit_id);
    return (elem | (bit << mask));
}

BinaryMatrix BinaryMatrix::tBinMultiply(const BinaryMatrix& other) {
    int w = this->width;
    int h = this->height;
    if (this->transposed) {
        w = other.width;
        h = other.height;
    }
    int this_n = this->dataLength;
    int other_n = other.dataLength;
    int res_n = res.dataLength;
    BinaryMatrix res(w, h);
    for (int bit_id = 0; bit_id < (w * h); ++bit_id) {
        std::pair<int, int> this_rc = elem_accessor(bit_id, this_n, this->baseSize, this->transposed);
        std::pair<int, int> other_rc = elem_accessor(bit_id, other_n, other->baseSize, other.transposed);
        std::pair<int, int> res_rc = elem_accessor(bit_id, res_n, res->baseSize, res.transposed);
        char this_c = this->data[this_rc.first];
        char other_c = other.data[other_rc.first];
        char res_c = res.data[res_rc.first];

        char answer = !(get_bit(this_c, this_rc.second) ^ get_bit(other_c, other_rc.second)) & 1;
        res.data[res_rc.first] = set_bit(res_c, res_rc.second, answer);
    }
    return res;
}

double BinaryMatrix::doubleMultiply(const double& other) {

}

BinaryMatrix BinaryMatrix::operator*(const BinaryMatrix& other ) {
    if(this->transposed != other.transposed) {
        assert(this->width == other.height);
        assert(this->height == other.width);
        return this->tBinMultiply(other);
    }
    else {
        assert(this->width == other.width);
        assert(this->height == other.height);
        return this->binMultiply(other);
    }
}
<commit_msg>Fixed set_bit to work with no assumptions on original bit<commit_after>//
// Created by Zal on 11/19/16.
//

#include <assert.h>
#include <utility>
#include "BinaryMatrix.h"

void BinaryMatrix::BinaryMatrix(int w, int h) {
    this->width = w;
    this->height = h;
    this->baseSize = sizeof(char) * 8;

    int n = w*h;
    this->dataLength = (n % baseSize == 0)? n/baseSize : n/baseSize +1;
    this->data = new char[dataLength];
}

void BinaryMatrix::~BinaryMatrix() {
    delete[] data;
}

void BinaryMatrix::T() {
    this->transposed = !this->transposed;
}

BinaryMatrix BinaryMatrix::binMultiply(const BinaryMatrix& other) {
    BinaryMatrix res(this->width, this->height);
    for(int i = 0; i < this->dataLength; ++i) {
        res.data[i] = !(this->data[i] ^ other.data[i]);
    }
    return res;
}

std::pair<int, int> BinaryMatrix::elem_accessor(int i, int rows, int cols, bool transposed) {
    if (transposed) {
        return std::make_pair(i % rows, i / rows);
    } else {
        return std::make_pair(i / cols, i % cols);
    }
}

char BinaryMatrix::get_bit(char elem, int bit_id) {
    return (elem >> (this->baseSize - bit_id)) & 1;
}

char BinaryMatrix::set_bit(char elem, int bit_id, char bit) {
    // assumes originally the bit is set to 0
    char mask = 1 << (this->baseSize - bit_id);
    if (get_bit(elem, bit_id) == 1 && bit == 0) {
        return (elem & !(1 << mask));
    } else {
        return (elem | (bit << mask));
    }
}

BinaryMatrix BinaryMatrix::tBinMultiply(const BinaryMatrix& other) {
    int w = this->width;
    int h = this->height;
    if (this->transposed) {
        w = other.width;
        h = other.height;
    }
    int this_n = this->dataLength;
    int other_n = other.dataLength;
    int res_n = res.dataLength;
    BinaryMatrix res(w, h);
    for (int bit_id = 0; bit_id < (w * h); ++bit_id) {
        std::pair<int, int> this_rc = elem_accessor(bit_id, this_n, this->baseSize, this->transposed);
        std::pair<int, int> other_rc = elem_accessor(bit_id, other_n, other->baseSize, other.transposed);
        std::pair<int, int> res_rc = elem_accessor(bit_id, res_n, res->baseSize, res.transposed);
        char this_c = this->data[this_rc.first];
        char other_c = other.data[other_rc.first];
        char res_c = res.data[res_rc.first];

        char answer = !(get_bit(this_c, this_rc.second) ^ get_bit(other_c, other_rc.second)) & 1;
        res.data[res_rc.first] = set_bit(res_c, res_rc.second, answer);
    }
    return res;
}

double BinaryMatrix::doubleMultiply(const double& other) {

}

BinaryMatrix BinaryMatrix::operator*(const BinaryMatrix& other ) {
    if(this->transposed != other.transposed) {
        assert(this->width == other.height);
        assert(this->height == other.width);
        return this->tBinMultiply(other);
    }
    else {
        assert(this->width == other.width);
        assert(this->height == other.height);
        return this->binMultiply(other);
    }
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: EDriver.hxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-08 07:12:19 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    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; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef _CONNECTIVITY_FLAT_EDRIVER_HXX_
#define _CONNECTIVITY_FLAT_EDRIVER_HXX_

#ifndef _CPPUHELPER_COMPBASE2_HXX_
#include <cppuhelper/compbase2.hxx>
#endif
#ifndef _CONNECTIVITY_COMMONTOOLS_HXX_
#include "connectivity/CommonTools.hxx"
#endif
#ifndef _CONNECTIVITY_FILE_ODRIVER_HXX_
#include "file/FDriver.hxx"
#endif

namespace connectivity
{
    namespace flat
    {

        ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL ODriver_CreateInstance(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxFactory) throw( ::com::sun::star::uno::Exception );

        class ODriver : public file::OFileDriver
        {
        public:
            ODriver(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxFactory) : file::OFileDriver(_rxFactory){}

            // XInterface
            static ::rtl::OUString getImplementationName_Static(  ) throw(::com::sun::star::uno::RuntimeException);
            //  static ::com::sun::star::uno::Sequence< ::rtl::OUString > getSupportedServiceNames_Static(  ) throw (::com::sun::star::uno::RuntimeException);

            ::rtl::OUString SAL_CALL getImplementationName(  ) throw(::com::sun::star::uno::RuntimeException);
            // XDriver
            virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection > SAL_CALL connect( const ::rtl::OUString& url, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& info ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException);
            virtual sal_Bool SAL_CALL acceptsURL( const ::rtl::OUString& url ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException);
            virtual ::com::sun::star::uno::Sequence< ::com::sun::star::sdbc::DriverPropertyInfo > SAL_CALL getPropertyInfo( const ::rtl::OUString& url, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& info ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException);
        };
    }

}
#endif //_CONNECTIVITY_FLAT_DDRIVER_HXX_

<commit_msg>INTEGRATION: CWS changefileheader (1.3.372); FILE MERGED 2008/04/01 15:09:12 thb 1.3.372.3: #i85898# Stripping all external header guards 2008/04/01 10:53:29 thb 1.3.372.2: #i85898# Stripping all external header guards 2008/03/28 15:24:21 rt 1.3.372.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: EDriver.hxx,v $
 * $Revision: 1.4 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#ifndef _CONNECTIVITY_FLAT_EDRIVER_HXX_
#define _CONNECTIVITY_FLAT_EDRIVER_HXX_

#include <cppuhelper/compbase2.hxx>
#include "connectivity/CommonTools.hxx"
#include "file/FDriver.hxx"

namespace connectivity
{
    namespace flat
    {

        ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL ODriver_CreateInstance(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxFactory) throw( ::com::sun::star::uno::Exception );

        class ODriver : public file::OFileDriver
        {
        public:
            ODriver(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxFactory) : file::OFileDriver(_rxFactory){}

            // XInterface
            static ::rtl::OUString getImplementationName_Static(  ) throw(::com::sun::star::uno::RuntimeException);
            //  static ::com::sun::star::uno::Sequence< ::rtl::OUString > getSupportedServiceNames_Static(  ) throw (::com::sun::star::uno::RuntimeException);

            ::rtl::OUString SAL_CALL getImplementationName(  ) throw(::com::sun::star::uno::RuntimeException);
            // XDriver
            virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection > SAL_CALL connect( const ::rtl::OUString& url, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& info ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException);
            virtual sal_Bool SAL_CALL acceptsURL( const ::rtl::OUString& url ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException);
            virtual ::com::sun::star::uno::Sequence< ::com::sun::star::sdbc::DriverPropertyInfo > SAL_CALL getPropertyInfo( const ::rtl::OUString& url, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& info ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException);
        };
    }

}
#endif //_CONNECTIVITY_FLAT_DDRIVER_HXX_

<|endoftext|>