<commit_before>#include "Utility.h"

#include <vector>
#include <random>
#include <chrono>
#include <fstream>
#include <algorithm>
#include <string>
#include <cctype>
#include <iostream>
#include <cmath>

namespace String
{
    namespace
    {
        const auto whitespace = " \t\n";
    }
}

std::vector<std::string> String::split(std::string s, std::string delim, size_t count)
{
    if(delim.empty())
    {
        s = remove_extra_whitespace(s);
        delim = " ";
    }

    std::vector<std::string> result;
    size_t start_index = 0;
    size_t end_index = 0;
    size_t split_count = 0;
    while(end_index < s.size() && split_count < count)
    {
        end_index = s.find(delim, start_index);
        result.push_back(s.substr(start_index, end_index-start_index));
        start_index = end_index + (end_index < s.size() ? delim.size() : 0);
        ++split_count;
    }

    if(start_index < s.size())
    {
        result.push_back(s.substr(start_index));
    }

    return result;
}

bool String::starts_with(const std::string& s, const std::string& beginning)
{
    return (beginning.size() <= s.size()) && std::equal(beginning.begin(), beginning.end(), s.begin());
}

bool String::ends_with(const std::string& s, const std::string& ending)
{
    return (ending.size() <= s.size()) && std::equal(ending.rbegin(), ending.rend(), s.rbegin());
}

std::string String::trim_outer_whitespace(const std::string& s)
{
    auto text_start = s.find_first_not_of(whitespace);
    if(text_start == std::string::npos)
    {
        return {};
    }

    auto text_end = s.find_last_not_of(whitespace);
    return s.substr(text_start, text_end - text_start + 1);
}

std::string String::remove_extra_whitespace(const std::string& s)
{
    auto inside_word = false;
    std::string result;

    for(auto c : s)
    {
        if(contains(whitespace, c))
        {
            inside_word = false;
        }
        else
        {
            if( ! inside_word && ! result.empty())
            {
                result.push_back(' ');
            }
            inside_word = true;
            result.push_back(c);
        }
    }

    return result;
}

std::string String::strip_comments(const std::string& str, char comment)
{
    return trim_outer_whitespace(str.substr(0, str.find(comment)));
}

std::string String::strip_block_comment(const std::string& str, char start, char end)
{
    auto start_comment_index = str.find(start);
    auto end_comment_index = str.find(end);
    if(start_comment_index == std::string::npos || end_comment_index == std::string::npos)
    {
        return remove_extra_whitespace(str);
    }

    auto first_part = str.substr(0, start_comment_index);
    auto last_part = str.substr(end_comment_index + 1);
    return strip_block_comment(first_part + " " + last_part, start, end);
}

std::string String::lowercase(std::string s)
{
    std::transform(s.begin(), s.end(), s.begin(), [](char c) -> char { return std::tolower(c); });
    return s;
}

int Random::random_integer(int min, int max)
{
    thread_local static std::mt19937_64 generator(std::random_device{}());
    using uid = std::uniform_int_distribution<int>;
    thread_local static auto dist = uid{};
    return dist(generator, uid::param_type{min, max});
}

double Random::random_laplace(double width)
{
    thread_local static std::mt19937_64 generator(std::random_device{}());
    using ed = std::exponential_distribution<double>;
    thread_local static auto dist = ed{};
    return (coin_flip() ? 1 : -1)*dist(generator, ed::param_type{1.0/width});
}

double Random::random_real(double min, double max)
{
    thread_local static std::mt19937_64 generator(std::random_device{}());
    using urd = std::uniform_real_distribution<double>;
    thread_local static auto dist = urd{};
    return dist(generator, urd::param_type{min, max});
}

uint64_t Random::random_unsigned_int64()
{
    thread_local static std::mt19937_64 generator(std::random_device{}());
    thread_local static std::uniform_int_distribution<uint64_t> dist;
    return dist(generator);
}

bool Random::coin_flip()
{
    return random_integer(0, 1) == 1;
}

bool Random::success_probability(double probability)
{
    return random_real(0.0, 1.0) < probability;
}

// Mean moves left in game given that a number of moves have been made already.
double Math::average_moves_left(double mean_moves, double width, size_t moves_so_far)
{
    // Assumes the number of moves in a game has a log-normal distribution.
    //
    // A = Sum(x = moves_so_far + 1 to infinity) P(x)*x = average number of moves
    //                                                    given game has already progressed
    //                                                    moves_so_far
    //
    // B = Sum(x = moves_so_far + 1 to infinity) P(x) = renormalization of P(x) for a
    //                                                  truncated range
    //
    // The calculations below for A and B use integrals on continuous functions as a
    // faster approximation.

    auto M = std::log(mean_moves);
    auto S = width;
    auto S2 = std::pow(S, 2);
    auto Sr2 = S*std::sqrt(2);
    auto ln_x = std::log(moves_so_far);

    auto A = std::exp(M + S2/2)*(1 + std::erf((M + S2 - ln_x)/Sr2));
    auto B = 1 + std::erf((M-ln_x)/Sr2);

    auto expected_mean = A/B;

    // If moves_so_far is much greater than mean_moves with a small
    // width in the log-normal distribution, A and B can end up
    // being zero, resulting in an undefined answer (NaN most likely).
    // This represents an extremely long game, so expect the game to end
    // soon.
    if( ! std::isfinite(expected_mean))
    {
        return 1.0;
    }

    return expected_mean - moves_so_far;
}

Configuration_File::Configuration_File(const std::string& file_name)
{
    std::ifstream ifs(file_name);
    std::string line;
    while(std::getline(ifs, line))
    {
        line = String::strip_comments(line, '#');
        if(line.empty())
        {
            continue;
        }
        if( ! String::contains(line, '='))
        {
            throw std::runtime_error("Configuration file lines must be of form \"Name = Value\"\n" + line);
        }
        auto line_split = String::split(line, "=", 1);
        auto parameter = standardize_text(line_split[0]);
        parameters[parameter] = String::trim_outer_whitespace(line_split[1]);
        used[parameter] = false;
    }
}

std::string Configuration_File::as_text(const std::string& parameter) const
{
    try
    {
        used.at(parameter) = true;
        return parameters.at(standardize_text(parameter));
    }
    catch(const std::out_of_range&)
    {
        for(const auto& key_value : parameters)
        {
            std::cerr << "\"" << key_value.first << "\" --> \"" << key_value.second << "\"" << std::endl;
        }
        throw std::runtime_error("Configuration parameter not found: " + parameter);
    }
}

double Configuration_File::as_number(const std::string& parameter) const
{
    try
    {
        return std::stod(as_text(parameter));
    }
    catch(const std::invalid_argument&)
    {
        throw std::runtime_error("Invalid number for \"" + parameter + "\" : " + as_text(parameter));
    }
}

bool Configuration_File::as_boolean(const std::string& parameter, const std::string& affirmative, const std::string& negative) const
{
    auto response = standardize_text(as_text(parameter));
    if(response == standardize_text(affirmative))
    {
        return true;
    }
    else if(response == standardize_text(negative))
    {
        return false;
    }
    else
    {
        throw std::runtime_error("Invalid value for \"" + parameter + "\" : \"" + as_text(parameter) + "\"" +
                                 "\nExpected \"" + affirmative + "\" or \"" + negative + "\".");
    }
}

std::string Configuration_File::standardize_text(const std::string& input)
{
    return String::lowercase(String::remove_extra_whitespace(input));
}

void Configuration_File::print_unused_parameters() const
{
    auto header_printed = false;
    for(const auto& param_value : parameters)
    {
        if( ! used[param_value.first])
        {
            if( ! header_printed)
            {
                std::cout << "Unused configuration parameters:\n";
                header_printed = true;
            }
            std::cout << param_value.first << " --> " << param_value.second << std::endl;
        }
    }
}

std::ofstream Scoped_Stopwatch::out_file;
std::mutex Scoped_Stopwatch::write_lock;

Scoped_Stopwatch::Scoped_Stopwatch(const std::string& name) :
    place_name(name),
    start_time(std::chrono::steady_clock::now()),
    stopped(place_name.empty())
{
}

Scoped_Stopwatch::~Scoped_Stopwatch()
{
    stop();
}

void Scoped_Stopwatch::stop()
{
    auto end_time = std::chrono::steady_clock::now();

    if(stopped)
    {
        return;
    }

    std::lock_guard<std::mutex> write_lock_guard(write_lock);

    if( ! out_file.is_open())
    {
        out_file.open("timings-" + std::to_string(Random::random_unsigned_int64()) + ".txt");
    }

    out_file << place_name << "|"
             << std::chrono::duration_cast<std::chrono::duration<double>>
                (end_time - start_time).count()
             << '\n';

    stopped = true;
}

void Scoped_Stopwatch::add_info(const std::string& info)
{
    place_name += info;
}

void Scoped_Stopwatch::reject()
{
    stopped = true;
}

double Scoped_Stopwatch::time_so_far() const
{
    auto end_time = std::chrono::steady_clock::now();
    return std::chrono::duration_cast<std::chrono::duration<double>>
                (end_time - start_time).count();
}
<commit_msg>Simplify string operations<commit_after>#include "Utility.h"

#include <vector>
#include <random>
#include <chrono>
#include <fstream>
#include <algorithm>
#include <string>
#include <cctype>
#include <iostream>
#include <cmath>

namespace String
{
    namespace
    {
        const auto whitespace = " \t\n";
    }
}

std::vector<std::string> String::split(std::string s, std::string delim, size_t count)
{
    if(delim.empty())
    {
        s = remove_extra_whitespace(s);
        delim = " ";
    }

    std::vector<std::string> result;
    size_t start_index = 0;
    size_t end_index = 0;
    size_t split_count = 0;
    while(end_index < s.size() && split_count < count)
    {
        end_index = s.find(delim, start_index);
        result.push_back(s.substr(start_index, end_index-start_index));
        start_index = std::max(end_index, end_index + delim.size());
        ++split_count;
    }

    if(start_index < s.size())
    {
        result.push_back(s.substr(start_index));
    }

    return result;
}

bool String::starts_with(const std::string& s, const std::string& beginning)
{
    return (beginning.size() <= s.size()) && std::equal(beginning.begin(), beginning.end(), s.begin());
}

bool String::ends_with(const std::string& s, const std::string& ending)
{
    return (ending.size() <= s.size()) && std::equal(ending.rbegin(), ending.rend(), s.rbegin());
}

std::string String::trim_outer_whitespace(const std::string& s)
{
    auto text_start = s.find_first_not_of(whitespace);
    if(text_start == std::string::npos)
    {
        return {};
    }

    auto text_end = s.find_last_not_of(whitespace);
    return s.substr(text_start, text_end - text_start + 1);
}

std::string String::remove_extra_whitespace(const std::string& s)
{
    std::string result;

    for(auto c : trim_outer_whitespace(s))
    {
        if(contains(whitespace, c))
        {
            if(result.back() != ' ')
            {
                result.push_back(' ');
            }
        }
        else
        {
            result.push_back(c);
        }
    }

    return result;
}

std::string String::strip_comments(const std::string& str, char comment)
{
    return trim_outer_whitespace(str.substr(0, str.find(comment)));
}

std::string String::strip_block_comment(const std::string& str, char start, char end)
{
    auto start_comment_index = str.find(start);
    auto end_comment_index = str.find(end);
    if(start_comment_index == std::string::npos || end_comment_index == std::string::npos)
    {
        return remove_extra_whitespace(str);
    }

    auto first_part = str.substr(0, start_comment_index);
    auto last_part = str.substr(end_comment_index + 1);
    return strip_block_comment(first_part + " " + last_part, start, end);
}

std::string String::lowercase(std::string s)
{
    std::transform(s.begin(), s.end(), s.begin(), [](char c) -> char { return std::tolower(c); });
    return s;
}

int Random::random_integer(int min, int max)
{
    thread_local static std::mt19937_64 generator(std::random_device{}());
    using uid = std::uniform_int_distribution<int>;
    thread_local static auto dist = uid{};
    return dist(generator, uid::param_type{min, max});
}

double Random::random_laplace(double width)
{
    thread_local static std::mt19937_64 generator(std::random_device{}());
    using ed = std::exponential_distribution<double>;
    thread_local static auto dist = ed{};
    return (coin_flip() ? 1 : -1)*dist(generator, ed::param_type{1.0/width});
}

double Random::random_real(double min, double max)
{
    thread_local static std::mt19937_64 generator(std::random_device{}());
    using urd = std::uniform_real_distribution<double>;
    thread_local static auto dist = urd{};
    return dist(generator, urd::param_type{min, max});
}

uint64_t Random::random_unsigned_int64()
{
    thread_local static std::mt19937_64 generator(std::random_device{}());
    thread_local static std::uniform_int_distribution<uint64_t> dist;
    return dist(generator);
}

bool Random::coin_flip()
{
    return random_integer(0, 1) == 1;
}

bool Random::success_probability(double probability)
{
    return random_real(0.0, 1.0) < probability;
}

// Mean moves left in game given that a number of moves have been made already.
double Math::average_moves_left(double mean_moves, double width, size_t moves_so_far)
{
    // Assumes the number of moves in a game has a log-normal distribution.
    //
    // A = Sum(x = moves_so_far + 1 to infinity) P(x)*x = average number of moves
    //                                                    given game has already progressed
    //                                                    moves_so_far
    //
    // B = Sum(x = moves_so_far + 1 to infinity) P(x) = renormalization of P(x) for a
    //                                                  truncated range
    //
    // The calculations below for A and B use integrals on continuous functions as a
    // faster approximation.

    auto M = std::log(mean_moves);
    auto S = width;
    auto S2 = std::pow(S, 2);
    auto Sr2 = S*std::sqrt(2);
    auto ln_x = std::log(moves_so_far);

    auto A = std::exp(M + S2/2)*(1 + std::erf((M + S2 - ln_x)/Sr2));
    auto B = 1 + std::erf((M-ln_x)/Sr2);

    auto expected_mean = A/B;

    // If moves_so_far is much greater than mean_moves with a small
    // width in the log-normal distribution, A and B can end up
    // being zero, resulting in an undefined answer (NaN most likely).
    // This represents an extremely long game, so expect the game to end
    // soon.
    if( ! std::isfinite(expected_mean))
    {
        return 1.0;
    }

    return expected_mean - moves_so_far;
}

Configuration_File::Configuration_File(const std::string& file_name)
{
    std::ifstream ifs(file_name);
    std::string line;
    while(std::getline(ifs, line))
    {
        line = String::strip_comments(line, '#');
        if(line.empty())
        {
            continue;
        }
        if( ! String::contains(line, '='))
        {
            throw std::runtime_error("Configuration file lines must be of form \"Name = Value\"\n" + line);
        }
        auto line_split = String::split(line, "=", 1);
        auto parameter = standardize_text(line_split[0]);
        parameters[parameter] = String::trim_outer_whitespace(line_split[1]);
        used[parameter] = false;
    }
}

std::string Configuration_File::as_text(const std::string& parameter) const
{
    try
    {
        used.at(parameter) = true;
        return parameters.at(standardize_text(parameter));
    }
    catch(const std::out_of_range&)
    {
        for(const auto& key_value : parameters)
        {
            std::cerr << "\"" << key_value.first << "\" --> \"" << key_value.second << "\"" << std::endl;
        }
        throw std::runtime_error("Configuration parameter not found: " + parameter);
    }
}

double Configuration_File::as_number(const std::string& parameter) const
{
    try
    {
        return std::stod(as_text(parameter));
    }
    catch(const std::invalid_argument&)
    {
        throw std::runtime_error("Invalid number for \"" + parameter + "\" : " + as_text(parameter));
    }
}

bool Configuration_File::as_boolean(const std::string& parameter, const std::string& affirmative, const std::string& negative) const
{
    auto response = standardize_text(as_text(parameter));
    if(response == standardize_text(affirmative))
    {
        return true;
    }
    else if(response == standardize_text(negative))
    {
        return false;
    }
    else
    {
        throw std::runtime_error("Invalid value for \"" + parameter + "\" : \"" + as_text(parameter) + "\"" +
                                 "\nExpected \"" + affirmative + "\" or \"" + negative + "\".");
    }
}

std::string Configuration_File::standardize_text(const std::string& input)
{
    return String::lowercase(String::remove_extra_whitespace(input));
}

void Configuration_File::print_unused_parameters() const
{
    auto header_printed = false;
    for(const auto& param_value : parameters)
    {
        if( ! used[param_value.first])
        {
            if( ! header_printed)
            {
                std::cout << "Unused configuration parameters:\n";
                header_printed = true;
            }
            std::cout << param_value.first << " --> " << param_value.second << std::endl;
        }
    }
}

std::ofstream Scoped_Stopwatch::out_file;
std::mutex Scoped_Stopwatch::write_lock;

Scoped_Stopwatch::Scoped_Stopwatch(const std::string& name) :
    place_name(name),
    start_time(std::chrono::steady_clock::now()),
    stopped(place_name.empty())
{
}

Scoped_Stopwatch::~Scoped_Stopwatch()
{
    stop();
}

void Scoped_Stopwatch::stop()
{
    auto end_time = std::chrono::steady_clock::now();

    if(stopped)
    {
        return;
    }

    std::lock_guard<std::mutex> write_lock_guard(write_lock);

    if( ! out_file.is_open())
    {
        out_file.open("timings-" + std::to_string(Random::random_unsigned_int64()) + ".txt");
    }

    out_file << place_name << "|"
             << std::chrono::duration_cast<std::chrono::duration<double>>
                (end_time - start_time).count()
             << '\n';

    stopped = true;
}

void Scoped_Stopwatch::add_info(const std::string& info)
{
    place_name += info;
}

void Scoped_Stopwatch::reject()
{
    stopped = true;
}

double Scoped_Stopwatch::time_so_far() const
{
    auto end_time = std::chrono::steady_clock::now();
    return std::chrono::duration_cast<std::chrono::duration<double>>
                (end_time - start_time).count();
}
<|endoftext|>


<commit_before>/*  cbr
 *  main.cpp
 *
 *  Copyright (c) 2009, Ewen Cheslack-Postava
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are
 *  met:
 *  * Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *  * Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *  * Neither the name of cbr nor the names of its contributors may
 *    be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef _CBR_UTILITY_HPP_
#define _CBR_UTILITY_HPP_

#include <sirikata/util/Platform.hpp>
#include <sirikata/util/Vector3.hpp>
#include <sirikata/util/Vector4.hpp>
#include <sirikata/util/UUID.hpp>

namespace CBR {

typedef Sirikata::int8 int8;
typedef Sirikata::uint8 uint8;
typedef Sirikata::int16 int16;
typedef Sirikata::uint16 uint16;
typedef Sirikata::int32 int32;
typedef Sirikata::uint32 uint32;
typedef Sirikata::int64 int64;
typedef Sirikata::uint64 uint64;

typedef Sirikata::float32 float32;
typedef Sirikata::float64 float64;

typedef Sirikata::Vector3f Vector3f;
typedef Sirikata::Vector3d Vector3d;

typedef Sirikata::Vector4f Vector4f;
typedef Sirikata::Vector4d Vector4d;

typedef Sirikata::Quaternion Quaternion;

typedef Sirikata::UUID UUID;

} // namespace CBR

#endif //_CBR_UTILITY_HPP_
<commit_msg>Add a couple of typedefs for integer vector types.<commit_after>/*  cbr
 *  main.cpp
 *
 *  Copyright (c) 2009, Ewen Cheslack-Postava
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are
 *  met:
 *  * Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *  * Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *  * Neither the name of cbr nor the names of its contributors may
 *    be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef _CBR_UTILITY_HPP_
#define _CBR_UTILITY_HPP_

#include <sirikata/util/Platform.hpp>
#include <sirikata/util/Vector3.hpp>
#include <sirikata/util/Vector4.hpp>
#include <sirikata/util/UUID.hpp>

namespace CBR {

typedef Sirikata::int8 int8;
typedef Sirikata::uint8 uint8;
typedef Sirikata::int16 int16;
typedef Sirikata::uint16 uint16;
typedef Sirikata::int32 int32;
typedef Sirikata::uint32 uint32;
typedef Sirikata::int64 int64;
typedef Sirikata::uint64 uint64;

typedef Sirikata::float32 float32;
typedef Sirikata::float64 float64;

typedef Sirikata::Vector3f Vector3f;
typedef Sirikata::Vector3d Vector3d;

typedef Sirikata::Vector3<uint32> Vector3ui32;
typedef Sirikata::Vector3<int32> Vector3i32;

typedef Sirikata::Vector4f Vector4f;
typedef Sirikata::Vector4d Vector4d;

typedef Sirikata::Vector4<uint32> Vector4ui32;
typedef Sirikata::Vector4<int32> Vector4i32;

typedef Sirikata::Quaternion Quaternion;

typedef Sirikata::UUID UUID;

} // namespace CBR

#endif //_CBR_UTILITY_HPP_
<|endoftext|>


<commit_before>#include "Vector2.h"

#include <assert.h>

Vector2::Vector2() : x(0), y(0) {}

Vector2::Vector2(const Vector2& v) : x(v[0]), y(v[1]) {}

Vector2::Vector2(double _x, double _y) : x(_x), y(_y) {}

Vector2& Vector2::operator=(const Vector2& a) {
    x = a[0];
    y = a[1];
    return *this;
}

const double& Vector2::operator[](int n) const {
	return (&x)[n];
}

double& Vector2::operator[](int n) {
	return (&x)[n];
}

Vector2& Vector2::operator+=(const Vector2& a) {
    x += a[0];
    y += a[1];
    return *this;
}

Vector2& Vector2::operator-=(const Vector2& a) {
    x -= a[0];
    y -= a[1];
    return *this;
}

Vector2& Vector2::operator*=(double s) {
    x *= s;
    y *= s;
    return *this;
}

Vector2 Vector2::operator-() const {
    return Vector2(-x, -y);
}

Vector2 Vector2::operator+() const {
    return *this;
}

Vector2 Vector2::operator+(const Vector2 &v) const {
    return Vector2( x + v.x, y + v.y);
}

Vector2 Vector2::operator-(const Vector2 &v) const {
    return Vector2( x - v.x, y - v.y);
}

Vector2 Vector2::operator/(const double s) const {
    assert( s > 0.0 );
    return Vector2( x / s, y / s);
}

Vector2 Vector2::operator*(const double s) const {
    return Vector2( x * s, y * s);
}

// Dot Product
double Vector2::operator*(const Vector2 &v) const {
    return x * v.x + y * v.y;
}

double Vector2::length() const {
    return (double) sqrt(x * x + y * y);
}

double Vector2::lengthSquared() const {
    return x * x + y * y;
}

void Vector2::normalize() {
    double s = 1.0 / (double) sqrt(x * x + y * y);
    x *= s;
    y *= s;
}

bool Vector2::operator==(const Vector2 &v) const {
    return x == v.x && y == v.y;
}

bool Vector2::operator!=(const Vector2 &v) const {
    return x != v.x || y != v.y;
}

void Vector2::print() const {
    std::cout << x << " " << y << "\n";
}
<commit_msg>ssh testing<commit_after>#include "Vector2.h"

#include <assert.h>

Vector2::Vector2() : x(0), y(0) {}

Vector2::Vector2(const Vector2& v) : x(v[0]), y(v[1]) {}

Vector2::Vector2(double _x, double _y) : x(_x), y(_y) {}

Vector2& Vector2::operator=(const Vector2& a) {
    x = a[0];
    y = a[1];
    return *this;
}

const double& Vector2::operator[](int n) const {
	return (&x)[n];
}

double& Vector2::operator[](int n) {
	return (&x)[n];
}

Vector2& Vector2::operator+=(const Vector2& a) {
    x += a[0];
    y += a[1];
    return *this;
}

Vector2& Vector2::operator-=(const Vector2& a) {
    x -= a[0];
    y -= a[1];
    return *this;
}

Vector2& Vector2::operator*=(double s) {
    x *= s;
    y *= s;
    return *this;
}

Vector2 Vector2::operator-() const {
    return Vector2(-x, -y);
}

Vector2 Vector2::operator+() const {
    return *this;
}

Vector2 Vector2::operator+(const Vector2 &v) const {
    return Vector2( x + v.x, y + v.y);
}

Vector2 Vector2::operator-(const Vector2 &v) const {
    return Vector2( x - v.x, y - v.y);
}

Vector2 Vector2::operator/(const double s) const {
    assert( s > 0.0 );
    return Vector2( x / s, y / s);
}

Vector2 Vector2::operator*(const double s) const {
    return Vector2( x * s, y * s);
}

// Dot Product
double Vector2::operator*(const Vector2 &v) const {
    return x * v.x + y * v.y;
}

double Vector2::length() const {
    return (double) sqrt(x * x + y * y);
}

double Vector2::lengthSquared() const {
    return x * x + y * y;
}

void Vector2::normalize() {
    double s = 1.0 / (double) sqrt(x * x + y * y);
    x *= s;
    y *= s;
}

bool Vector2::operator==(const Vector2 &v) const {
    return x == v.x && y == v.y;
}

bool Vector2::operator!=(const Vector2 &v) const {
    return x != v.x || y != v.y;
}

void Vector2::print() const {
    std::cout << x << " " << y << "\n";
}

<|endoftext|>


<commit_before>/* Copyright (C) Teemu Suutari */

#include <cstring>
#include <memory>
#include <algorithm>

#include "common/SubBuffer.hpp"

#include "XPKMain.hpp"
#include "XPKDecompressor.hpp"

bool XPKMain::detectHeader(uint32_t hdr) noexcept
{
	return hdr==FourCC("XPKF");
}

std::unique_ptr<Decompressor> XPKMain::create(const Buffer &packedData,bool verify,bool exactSizeKnown)
{
	return std::make_unique<XPKMain>(packedData,verify,0);
}

std::vector<std::pair<bool(*)(uint32_t),std::unique_ptr<XPKDecompressor>(*)(uint32_t,uint32_t,const Buffer&,std::unique_ptr<XPKDecompressor::State>&,bool)>> *XPKMain::_XPKDecompressors=nullptr;

void XPKMain::registerDecompressor(bool(*detect)(uint32_t),std::unique_ptr<XPKDecompressor>(*create)(uint32_t,uint32_t,const Buffer&,std::unique_ptr<XPKDecompressor::State>&,bool))
{
	static std::vector<std::pair<bool(*)(uint32_t),std::unique_ptr<XPKDecompressor>(*)(uint32_t,uint32_t,const Buffer&,std::unique_ptr<XPKDecompressor::State>&,bool)>> _list;
	if (!_XPKDecompressors) _XPKDecompressors=&_list;
	_XPKDecompressors->emplace_back(detect,create);
}

XPKMain::XPKMain(const Buffer &packedData,bool verify,uint32_t recursionLevel) :
	_packedData(packedData)
{
	if (packedData.size()<44) throw Decompressor::InvalidFormatError();
	uint32_t hdr=packedData.readBE32(0);
	if (!detectHeader(hdr)) throw Decompressor::InvalidFormatError();

	_packedSize=packedData.readBE32(4);
	_type=packedData.readBE32(8);
	_rawSize=packedData.readBE32(12);

	if (!_rawSize || !_packedSize) throw Decompressor::InvalidFormatError();
	if (_rawSize>getMaxRawSize() || _packedSize>getMaxPackedSize()) throw Decompressor::InvalidFormatError();

	uint8_t flags=packedData.read8(32);
	_longHeaders=(flags&1)?true:false;
	if (flags&2) throw Decompressor::InvalidFormatError();	// needs password. we do not support that
	if (flags&4)						// extra header
	{
		_headerSize=38+uint32_t(packedData.readBE16(36));
	} else {
		_headerSize=36;
	}

	if (size_t(_packedSize)+8>packedData.size()) throw Decompressor::InvalidFormatError();

	bool found=false;
	for (auto &it : *_XPKDecompressors)
	{
		if (it.first(_type))
		{
			if (recursionLevel>=getMaxRecursionLevel()) throw Decompressor::InvalidFormatError();
			else {
				found=true;
				break;
			}
		}
	}
	if (!found) throw Decompressor::InvalidFormatError();

	auto headerChecksum=[](const Buffer &buffer,size_t offset,size_t len)->bool
	{
		if (!len || offset+len>buffer.size()) return false;
		const uint8_t *ptr=buffer.data()+offset;
		uint8_t tmp=0;
		for (size_t i=0;i<len;i++)
			tmp^=ptr[i];
		return !tmp;
	};

	// this implementation assumes align padding is zeros
	auto chunkChecksum=[](const Buffer &buffer,size_t offset,size_t len,uint16_t checkValue)->bool
	{
		if (!len || offset+len>buffer.size()) return false;
		const uint8_t *ptr=buffer.data()+offset;
		uint8_t tmp[2]={0,0};
		for (size_t i=0;i<len;i++)
			tmp[i&1]^=ptr[i];
		return tmp[0]==(checkValue>>8) && tmp[1]==(checkValue&0xff);
	};

	if (verify)
	{
		if (!headerChecksum(_packedData,0,36)) throw Decompressor::VerificationError();

		std::unique_ptr<XPKDecompressor::State> state;
		forEachChunk([&](const Buffer &header,const Buffer &chunk,uint32_t rawChunkSize,uint8_t chunkType)->bool
		{
			if (!headerChecksum(header,0,header.size())) throw Decompressor::VerificationError();

			uint16_t hdrCheck=header.readBE16(2);
			if (chunk.size() && !chunkChecksum(chunk,0,chunk.size(),hdrCheck)) throw Decompressor::VerificationError();

			if (chunkType==1)
			{
				auto sub=createDecompressor(_type,_recursionLevel,chunk,state,true);
			} else if (chunkType!=0 && chunkType!=15) throw Decompressor::InvalidFormatError();
			return true;
		});
	}
}

XPKMain::~XPKMain()
{
	// nothing needed
}

const std::string &XPKMain::getName() const noexcept
{
	std::unique_ptr<XPKDecompressor> sub;
	std::unique_ptr<XPKDecompressor::State> state;
	try
	{
		forEachChunk([&](const Buffer &header,const Buffer &chunk,uint32_t rawChunkSize,uint8_t chunkType)->bool
		{
			try
			{
				sub=createDecompressor(_type,_recursionLevel,chunk,state,false);
			} catch (const Error&) {
				// should not happen since the code is already tried out,
				// however, lets handle the case gracefully
			}
			return false;
		});
	} catch (const Buffer::Error&) {
		// ditto
	}
	static std::string invName="<invalid>";
	return (sub)?sub->getSubName():invName;
}

size_t XPKMain::getPackedSize() const noexcept
{
	return _packedSize+8;
}

size_t XPKMain::getRawSize() const noexcept
{
	return _rawSize;
}

void XPKMain::decompressImpl(Buffer &rawData,bool verify)
{
	if (rawData.size()<_rawSize) throw Decompressor::DecompressionError();

	uint32_t destOffset=0;
	std::unique_ptr<XPKDecompressor::State> state;
	forEachChunk([&](const Buffer &header,const Buffer &chunk,uint32_t rawChunkSize,uint8_t chunkType)->bool
	{
		if (size_t(destOffset)+size_t(rawChunkSize)>rawData.size()) throw Decompressor::DecompressionError();
		if (!rawChunkSize) return true;

		ConstSubBuffer previousBuffer(rawData,0,destOffset);
		SubBuffer DestBuffer(rawData,destOffset,rawChunkSize);
		switch (chunkType)
		{
			case 0:
			if (rawChunkSize!=chunk.size()) throw Decompressor::DecompressionError();;
			std::memcpy(DestBuffer.data(),chunk.data(),rawChunkSize);
			break;

			case 1:
			{
				try
				{
					auto sub=createDecompressor(_type,_recursionLevel,chunk,state,false);
					sub->decompressImpl(DestBuffer,previousBuffer,verify);
				} catch (const InvalidFormatError&) {
					// we should throw a correct error
					throw DecompressionError();
				}
			}
			break;

			case 15:
			break;

			default:
			return false;
		}

		destOffset+=rawChunkSize;
		return true;
	});

	if (destOffset!=_rawSize) throw Decompressor::DecompressionError();

	if (verify)
	{
		if (std::memcmp(_packedData.data()+16,rawData.data(),std::min(_rawSize,16U))) throw Decompressor::DecompressionError();
	}
}

std::unique_ptr<XPKDecompressor> XPKMain::createDecompressor(uint32_t type,uint32_t recursionLevel,const Buffer &buffer,std::unique_ptr<XPKDecompressor::State> &state,bool verify)
{
	// since this method is used externally, better check recursion level
	if (recursionLevel>=getMaxRecursionLevel()) throw Decompressor::InvalidFormatError();
	for (auto &it : *_XPKDecompressors)
	{
		if (it.first(type)) return it.second(type,recursionLevel,buffer,state,verify);
	}
	throw Decompressor::InvalidFormatError();
}

template <typename F>
void XPKMain::forEachChunk(F func) const
{
	uint32_t currentOffset=0,rawSize,packedSize;
	bool isLast=false;

	while (currentOffset<_packedSize+8 && !isLast)
	{
		auto readDualValue=[&](uint32_t offsetShort,uint32_t offsetLong,uint32_t &value)
		{
			if (_longHeaders)
			{
				value=_packedData.readBE32(currentOffset+offsetLong);
			} else {
				value=uint32_t(_packedData.readBE16(currentOffset+offsetShort));
			}
		};

		uint32_t chunkHeaderLen=_longHeaders?12:8;
		if (!currentOffset)
		{
			// return first;
			currentOffset=_headerSize;
		} else {
			uint32_t tmp;
			readDualValue(4,4,tmp);
			currentOffset+=chunkHeaderLen+((tmp+3)&~3U);
		}
		readDualValue(4,4,packedSize);
		readDualValue(6,8,rawSize);

		ConstSubBuffer hdr(_packedData,currentOffset,chunkHeaderLen);
		ConstSubBuffer chunk(_packedData,currentOffset+chunkHeaderLen,packedSize);

		uint8_t type=_packedData.read8(currentOffset);
		if (!func(hdr,chunk,rawSize,type)) return;

		if (type==15) isLast=true;
	}
}

Decompressor::Registry<XPKMain> XPKMain::_registration;
<commit_msg>Fuzzing fix for Xpk<commit_after>/* Copyright (C) Teemu Suutari */

#include <cstring>
#include <memory>
#include <algorithm>

#include "common/SubBuffer.hpp"

#include "XPKMain.hpp"
#include "XPKDecompressor.hpp"

bool XPKMain::detectHeader(uint32_t hdr) noexcept
{
	return hdr==FourCC("XPKF");
}

std::unique_ptr<Decompressor> XPKMain::create(const Buffer &packedData,bool verify,bool exactSizeKnown)
{
	return std::make_unique<XPKMain>(packedData,verify,0);
}

std::vector<std::pair<bool(*)(uint32_t),std::unique_ptr<XPKDecompressor>(*)(uint32_t,uint32_t,const Buffer&,std::unique_ptr<XPKDecompressor::State>&,bool)>> *XPKMain::_XPKDecompressors=nullptr;

void XPKMain::registerDecompressor(bool(*detect)(uint32_t),std::unique_ptr<XPKDecompressor>(*create)(uint32_t,uint32_t,const Buffer&,std::unique_ptr<XPKDecompressor::State>&,bool))
{
	static std::vector<std::pair<bool(*)(uint32_t),std::unique_ptr<XPKDecompressor>(*)(uint32_t,uint32_t,const Buffer&,std::unique_ptr<XPKDecompressor::State>&,bool)>> _list;
	if (!_XPKDecompressors) _XPKDecompressors=&_list;
	_XPKDecompressors->emplace_back(detect,create);
}

XPKMain::XPKMain(const Buffer &packedData,bool verify,uint32_t recursionLevel) :
	_packedData(packedData)
{
	if (packedData.size()<44) throw InvalidFormatError();
	uint32_t hdr=packedData.readBE32(0);
	if (!detectHeader(hdr)) throw InvalidFormatError();

	_packedSize=packedData.readBE32(4);
	_type=packedData.readBE32(8);
	_rawSize=packedData.readBE32(12);

	if (!_rawSize || !_packedSize) throw InvalidFormatError();
	if (_rawSize>getMaxRawSize() || _packedSize>getMaxPackedSize()) throw InvalidFormatError();

	uint8_t flags=packedData.read8(32);
	_longHeaders=(flags&1)?true:false;
	if (flags&2) throw InvalidFormatError();	// needs password. we do not support that
	if (flags&4)						// extra header
	{
		_headerSize=38+uint32_t(packedData.readBE16(36));
	} else {
		_headerSize=36;
	}

	if (size_t(_packedSize)+8>packedData.size()) throw InvalidFormatError();

	bool found=false;
	for (auto &it : *_XPKDecompressors)
	{
		if (it.first(_type))
		{
			if (recursionLevel>=getMaxRecursionLevel()) throw InvalidFormatError();
			else {
				found=true;
				break;
			}
		}
	}
	if (!found) throw InvalidFormatError();

	auto headerChecksum=[](const Buffer &buffer,size_t offset,size_t len)->bool
	{
		if (!len || offset+len>buffer.size()) return false;
		const uint8_t *ptr=buffer.data()+offset;
		uint8_t tmp=0;
		for (size_t i=0;i<len;i++)
			tmp^=ptr[i];
		return !tmp;
	};

	// this implementation assumes align padding is zeros
	auto chunkChecksum=[](const Buffer &buffer,size_t offset,size_t len,uint16_t checkValue)->bool
	{
		if (!len || offset+len>buffer.size()) return false;
		const uint8_t *ptr=buffer.data()+offset;
		uint8_t tmp[2]={0,0};
		for (size_t i=0;i<len;i++)
			tmp[i&1]^=ptr[i];
		return tmp[0]==(checkValue>>8) && tmp[1]==(checkValue&0xff);
	};

	if (verify)
	{
		if (!headerChecksum(_packedData,0,36)) throw VerificationError();

		std::unique_ptr<XPKDecompressor::State> state;
		forEachChunk([&](const Buffer &header,const Buffer &chunk,uint32_t rawChunkSize,uint8_t chunkType)->bool
		{
			if (!headerChecksum(header,0,header.size())) throw VerificationError();

			uint16_t hdrCheck=header.readBE16(2);
			if (chunk.size() && !chunkChecksum(chunk,0,chunk.size(),hdrCheck)) throw VerificationError();

			if (chunkType==1)
			{
				auto sub=createDecompressor(_type,_recursionLevel,chunk,state,true);
			} else if (chunkType!=0 && chunkType!=15) throw InvalidFormatError();
			return true;
		});
	}
}

XPKMain::~XPKMain()
{
	// nothing needed
}

const std::string &XPKMain::getName() const noexcept
{
	std::unique_ptr<XPKDecompressor> sub;
	std::unique_ptr<XPKDecompressor::State> state;
	try
	{
		forEachChunk([&](const Buffer &header,const Buffer &chunk,uint32_t rawChunkSize,uint8_t chunkType)->bool
		{
			try
			{
				sub=createDecompressor(_type,_recursionLevel,chunk,state,false);
			} catch (const Error&) {
				// should not happen since the code is already tried out,
				// however, lets handle the case gracefully
			}
			return false;
		});
	} catch (const Buffer::Error&) {
		// ditto
	}
	static std::string invName="<invalid>";
	return (sub)?sub->getSubName():invName;
}

size_t XPKMain::getPackedSize() const noexcept
{
	return _packedSize+8;
}

size_t XPKMain::getRawSize() const noexcept
{
	return _rawSize;
}

void XPKMain::decompressImpl(Buffer &rawData,bool verify)
{
	if (rawData.size()<_rawSize) throw DecompressionError();

	uint32_t destOffset=0;
	std::unique_ptr<XPKDecompressor::State> state;
	forEachChunk([&](const Buffer &header,const Buffer &chunk,uint32_t rawChunkSize,uint8_t chunkType)->bool
	{
		if (size_t(destOffset)+size_t(rawChunkSize)>rawData.size()) throw DecompressionError();
		if (!rawChunkSize) return true;

		ConstSubBuffer previousBuffer(rawData,0,destOffset);
		SubBuffer DestBuffer(rawData,destOffset,rawChunkSize);
		switch (chunkType)
		{
			case 0:
			if (rawChunkSize!=chunk.size()) throw DecompressionError();;
			std::memcpy(DestBuffer.data(),chunk.data(),rawChunkSize);
			break;

			case 1:
			{
				try
				{
					auto sub=createDecompressor(_type,_recursionLevel,chunk,state,false);
					sub->decompressImpl(DestBuffer,previousBuffer,verify);
				} catch (const InvalidFormatError&) {
					// we should throw a correct error
					throw DecompressionError();
				}
			}
			break;

			case 15:
			break;

			default:
			return false;
		}

		destOffset+=rawChunkSize;
		return true;
	});

	if (destOffset!=_rawSize) throw DecompressionError();

	if (verify)
	{
		if (std::memcmp(_packedData.data()+16,rawData.data(),std::min(_rawSize,16U))) throw DecompressionError();
	}
}

std::unique_ptr<XPKDecompressor> XPKMain::createDecompressor(uint32_t type,uint32_t recursionLevel,const Buffer &buffer,std::unique_ptr<XPKDecompressor::State> &state,bool verify)
{
	// since this method is used externally, better check recursion level
	if (recursionLevel>=getMaxRecursionLevel()) throw InvalidFormatError();
	for (auto &it : *_XPKDecompressors)
	{
		if (it.first(type)) return it.second(type,recursionLevel,buffer,state,verify);
	}
	throw InvalidFormatError();
}

template <typename F>
void XPKMain::forEachChunk(F func) const
{
	uint32_t currentOffset=0,rawSize,packedSize;
	bool isLast=false;

	while (currentOffset<_packedSize+8 && !isLast)
	{
		auto readDualValue=[&](uint32_t offsetShort,uint32_t offsetLong,uint32_t &value)
		{
			if (_longHeaders)
			{
				value=_packedData.readBE32(currentOffset+offsetLong);
			} else {
				value=uint32_t(_packedData.readBE16(currentOffset+offsetShort));
			}
		};

		uint32_t chunkHeaderLen=_longHeaders?12:8;
		if (!currentOffset)
		{
			// return first;
			currentOffset=_headerSize;
		} else {
			uint32_t tmp;
			readDualValue(4,4,tmp);
			tmp=((tmp+3U)&~3U);
			if (size_t(tmp)+size_t(currentOffset)>packedSize)
				throw InvalidFormatError();
			currentOffset+=chunkHeaderLen+tmp;
		}
		readDualValue(4,4,packedSize);
		readDualValue(6,8,rawSize);

		ConstSubBuffer hdr(_packedData,currentOffset,chunkHeaderLen);
		ConstSubBuffer chunk(_packedData,currentOffset+chunkHeaderLen,packedSize);

		uint8_t type=_packedData.read8(currentOffset);
		if (!func(hdr,chunk,rawSize,type)) return;

		if (type==15) isLast=true;
	}
	if (!isLast) throw InvalidFormatError();
}

Decompressor::Registry<XPKMain> XPKMain::_registration;
<|endoftext|>


<commit_before>//
// Created by burso on 3/22/16.
//

#include <iostream>
#include "../include/ssllabs/ssllabs.h"
#include "../include/rapidjson/document.h"

int SSLlabs::analyze(const std::string domain, const std::string &data,
                     bool publish, bool startNew, bool fromCache, bool ignoreMismatch) {
    std::string command("/analyze?host=");

    command += domain;
    if (publish) {
        command += "&publish=on";
    }

    if (startNew && fromCache) {
        std::cerr << "could not use startNew and fromCache at the same time\n";
        return -1;
    }

    return curl_read(command, data);
}

int SSLlabs::analyze(const std::string domain, labsReport_t &report,
                     bool publish, bool startNew, bool fromCache, bool ignoreMismatch) {
    std::string command("/analyze?host=");
    std::string data = {};
    rapidjson::Document document;
    labsEndpoint_t endpoint;

    command += domain;
    if (publish) {
        command += "&publish=on";
    }

    if (startNew && fromCache) {
        std::cerr << "could not use startNew and fromCache at the same time\n";
        return -1;
    }

    curl_read(command, data);

    if (document.Parse<0>(data.c_str()).HasParseError()) {
        std::cerr << "could not parse json document\n";
        return -1;
    }

    report.RawJson.assign(data);

    if (document.HasMember("host") && document["host"].IsString()) {
        report.Host.assign(document["host"].GetString());
    }

    if (document.HasMember("port") && document["port"].IsInt()) {
        report.Port = document["port"].GetInt();
    }

    if (document.HasMember("protocol") && document["protocol"].IsString()) {
        report.Protocol.assign(document["protocol"].GetString());
    }

    if (document.HasMember("isPublic") && document["isPublic"].IsBool()) {
        report.IsPublic = document["isPublic"].GetBool();
    }

    if (document.HasMember("status") && document["status"].IsString()) {
        report.Status.assign(document["status"].GetString());
    }

    if (document.HasMember("startTime") && document["startTime"].IsInt64()) {
        report.StartTime = document["startTime"].GetInt64();
    }

    if (document.HasMember("testTime") && document["testTime"].IsInt64()) {
        report.TestTime = document["testTime"].GetInt64();
    }

    if (document.HasMember("engineVersion") && document["engineVersion"].IsString()) {
        report.EngineVersion.assign(document["engineVersion"].GetString());
    }

    if (document.HasMember("criteriaVersion") && document["criteriaVersion"].IsString()) {
        report.CriteriaVersion.assign(document["criteriaVersion"].GetString());
    }

    return 0;
}<commit_msg>added new parameters to analyze command<commit_after>//
// Created by burso on 3/22/16.
//

#include <iostream>
#include "../include/ssllabs/ssllabs.h"
#include "../include/rapidjson/document.h"

int SSLlabs::analyze(const std::string domain, const std::string &data,
                     bool publish, bool startNew, bool fromCache, bool ignoreMismatch) {
    std::string command("/analyze?host=");

    command += domain;
    if (startNew && fromCache) {
        std::cerr << "could not use startNew and fromCache at the same time\n";
        return -1;
    }

    if (publish) {
        command += "&publish=on";
    }

    if (startNew) {
        command += "&startNew=on";
    }

    if (fromCache) {
        command += "&fromCache=on";
    }
    else {
        if (ignoreMismatch) {
            command += "&ignoreMismatch=on";
        }
    }

    return curl_read(command, data);
}

int SSLlabs::analyze(const std::string domain, labsReport_t &report,
                     bool publish, bool startNew, bool fromCache, bool ignoreMismatch) {
    std::string command("/analyze?host=");
    std::string data = {};
    rapidjson::Document document;
    labsEndpoint_t endpoint;

    command += domain;
    if (startNew && fromCache) {
        std::cerr << "could not use startNew and fromCache at the same time\n";
        return -1;
    }

    if (publish) {
        command += "&publish=on";
    }

    if (startNew) {
        command += "&startNew=on";
    }

    if (fromCache) {
        command += "&fromCache=on";
    }
    else {
        if (ignoreMismatch) {
            command += "&ignoreMismatch=on";
        }
    }

    if (curl_read(command, data) != 0) {
        return -1;
    }

    if (document.Parse<0>(data.c_str()).HasParseError()) {
        std::cerr << "could not parse json document\n";
        return -1;
    }

    report.RawJson.assign(data);

    if (document.HasMember("host") && document["host"].IsString()) {
        report.Host.assign(document["host"].GetString());
    }

    if (document.HasMember("port") && document["port"].IsInt()) {
        report.Port = document["port"].GetInt();
    }

    if (document.HasMember("protocol") && document["protocol"].IsString()) {
        report.Protocol.assign(document["protocol"].GetString());
    }

    if (document.HasMember("isPublic") && document["isPublic"].IsBool()) {
        report.IsPublic = document["isPublic"].GetBool();
    }

    if (document.HasMember("status") && document["status"].IsString()) {
        report.Status.assign(document["status"].GetString());
    }

    if (document.HasMember("startTime") && document["startTime"].IsInt64()) {
        report.StartTime = document["startTime"].GetInt64();
    }

    if (document.HasMember("testTime") && document["testTime"].IsInt64()) {
        report.TestTime = document["testTime"].GetInt64();
    }

    if (document.HasMember("engineVersion") && document["engineVersion"].IsString()) {
        report.EngineVersion.assign(document["engineVersion"].GetString());
    }

    if (document.HasMember("criteriaVersion") && document["criteriaVersion"].IsString()) {
        report.CriteriaVersion.assign(document["criteriaVersion"].GetString());
    }

    return 0;
}<|endoftext|>


<commit_before>#include "ghost/config.h"
#include "ghost/autogen.h"
#include "ghost/util.h"
#include <string>
#include <vector>
#include <algorithm>
#include <map>
#include <set>

using namespace std;

static map<string, set<string>> autogen_str_map;
static string autogen_str;
static int missingConfs = 0;

ghost_error ghost_autogen_kacz_nvecs(int **nvecs, int *n, int chunkheight, int nshifts)
{
    string configurations = GHOST_AUTOGEN_KACZ;
    if (configurations[configurations.length() - 1] != ';') {
        configurations += ";";
    }

    size_t pos = 0, commapos = 0;
    int cfg_chunkheight, cfg_nvecs, cfg_nshifts;
    string configuration;
    vector<int> nvecs_vec;

    while ((pos = configurations.find(";")) != string::npos) {
        configuration = configurations.substr(0, pos);

        commapos = configuration.find(",");
        string cfg_chunkheight_str = configuration.substr(0, commapos);

        if (!cfg_chunkheight_str.compare("*")) {
            cfg_chunkheight = chunkheight;
        } else {
            cfg_chunkheight = atoi(cfg_chunkheight_str.c_str());
        }
        configuration.erase(0, commapos + 1);

        commapos = configuration.find(",");
        string cfg_nvecs_str = configuration.substr(0, commapos);
        if (!cfg_nvecs_str.compare("*")) {
            configurations.erase(0, pos + 1);
            continue;
        } else {
            cfg_nvecs = atoi(cfg_nvecs_str.c_str());
        }
        configuration.erase(0, commapos + 1);

        string cfg_nshifts_str = configuration;
        if (!cfg_nshifts_str.compare("*")) {
            cfg_nshifts = nshifts;
        } else {
            cfg_nshifts = atoi(cfg_nshifts_str.c_str());
        }

        if (chunkheight == cfg_chunkheight && nshifts == cfg_nshifts) {
            nvecs_vec.push_back(cfg_nvecs);
        }

        configurations.erase(0, pos + 1);
    }

    sort(nvecs_vec.begin(), nvecs_vec.end());
    *n = nvecs_vec.size();
    ghost_malloc((void **)nvecs, sizeof(int) * (*n));

    int i;
    for (i = 0; i < *n; i++) {
        (*nvecs)[i] = nvecs_vec[i];
    }

    return GHOST_SUCCESS;
}

ghost_error ghost_autogen_spmmv_nvecs(int **nvecs, int *n, int chunkheight)
{
    string configurations;
    ghost_type mytype;
    ghost_type_get(&mytype);

    if (mytype == GHOST_TYPE_CUDA) {
        configurations = GHOST_AUTOGEN_SPMMV_CUDA;
    } else {
        configurations = GHOST_AUTOGEN_SPMMV;
    }

    if (configurations[configurations.length() - 1] != ';') {
        configurations += ";";
    }

    size_t pos = 0, commapos = 0;
    int cfg_chunkheight, cfg_nvecs;
    string configuration;
    vector<int> nvecs_vec;

    while ((pos = configurations.find(";")) != string::npos) {
        configuration = configurations.substr(0, pos);

        commapos = configuration.find(",");
        string cfg_chunkheight_str = configuration.substr(0, commapos);

        if (!cfg_chunkheight_str.compare("*")) {
            cfg_chunkheight = chunkheight;
        } else {
            cfg_chunkheight = atoi(cfg_chunkheight_str.c_str());
        }
        configuration.erase(0, commapos + 1);

        commapos = configuration.find(",");
        string cfg_nvecs_str = configuration.substr(0, commapos);
        if (!cfg_nvecs_str.compare("*")) {
            configurations.erase(0, pos + 1);
            continue;
        } else {
            cfg_nvecs = atoi(cfg_nvecs_str.c_str());
        }
        if (chunkheight == cfg_chunkheight) {
            nvecs_vec.push_back(cfg_nvecs);
        }
        configurations.erase(0, pos + 1);
    }

    sort(nvecs_vec.begin(), nvecs_vec.end());
    *n = nvecs_vec.size();
    ghost_malloc((void **)nvecs, sizeof(int) * (*n));

    int i;
    for (i = 0; i < *n; i++) {
        (*nvecs)[i] = nvecs_vec[i];
    }

    return GHOST_SUCCESS;
}

int ghost_autogen_spmmv_next_nvecs(int desired_nvecs, int chunkheight)
{
    int *nvecs = NULL;
    int n, i, found_nvecs = 0;

    if (ghost_autogen_spmmv_nvecs(&nvecs, &n, chunkheight) != GHOST_SUCCESS) {
        return 0;
    }
    if (n == 0) {
        free(nvecs);
        return 0;
    }
    for (i = n - 1; i >= 0; i--) {
        if (nvecs[i] <= desired_nvecs) {
            found_nvecs = nvecs[i];
            break;
        }
    }

    free(nvecs);

    return found_nvecs;
}

ghost_error ghost_autogen_string_add(const char *func, const char *par)
{
    /*    size_t funcpos = autogen_str.find(func);
      if (funcpos == string::npos) {
          autogen_str.append(" -DGHOST_AUTOGEN_");
          autogen_str.append(func);
          autogen_str.append("=\"");
          autogen_str.append(par);
          autogen_str.append("\"");
      } else {
          string funcstr = autogen_str.substr(funcpos+strlen(func)+1,autogen_str.find(" ",funcpos));
          string findpar_inner = ";"+string(par)+";";
          string findpar_last = ";"+string(par)+"\"";
          string findpar_first = "\""+string(par)+";";
          string findpar_only = "\""+string(par)+"\"";
          if ((funcstr.find(findpar_inner) == string::npos)
                  && (funcstr.find(findpar_last) == string::npos)
                  && (funcstr.find(findpar_first) == string::npos)
                  && (funcstr.find(findpar_only) == string::npos)) {
              autogen_str.insert(funcpos+strlen(func)+2,string(par)+";");
          }
      }
    */

    autogen_str_map[string(func)].insert(string(par));
    return GHOST_SUCCESS;
}

const char *ghost_autogen_string()
{
    autogen_str = "";

    for (auto &func : autogen_str_map) {
        autogen_str += string("-DGHOST_AUTOGEN") + func.first + "=\"";
        for (auto &par : func.second) {
            autogen_str += par + ";";
        }
        autogen_str += string("\" ");
    }
    return autogen_str.c_str();
}

void ghost_autogen_set_missing() { missingConfs = 1; }

int ghost_autogen_missing() { return missingConfs; }
<commit_msg>autogen notification string: add missing underscore<commit_after>#include "ghost/config.h"
#include "ghost/autogen.h"
#include "ghost/util.h"
#include <string>
#include <vector>
#include <algorithm>
#include <map>
#include <set>

using namespace std;

static map<string, set<string>> autogen_str_map;
static string autogen_str;
static int missingConfs = 0;

ghost_error ghost_autogen_kacz_nvecs(int **nvecs, int *n, int chunkheight, int nshifts)
{
    string configurations = GHOST_AUTOGEN_KACZ;
    if (configurations[configurations.length() - 1] != ';') {
        configurations += ";";
    }

    size_t pos = 0, commapos = 0;
    int cfg_chunkheight, cfg_nvecs, cfg_nshifts;
    string configuration;
    vector<int> nvecs_vec;

    while ((pos = configurations.find(";")) != string::npos) {
        configuration = configurations.substr(0, pos);

        commapos = configuration.find(",");
        string cfg_chunkheight_str = configuration.substr(0, commapos);

        if (!cfg_chunkheight_str.compare("*")) {
            cfg_chunkheight = chunkheight;
        } else {
            cfg_chunkheight = atoi(cfg_chunkheight_str.c_str());
        }
        configuration.erase(0, commapos + 1);

        commapos = configuration.find(",");
        string cfg_nvecs_str = configuration.substr(0, commapos);
        if (!cfg_nvecs_str.compare("*")) {
            configurations.erase(0, pos + 1);
            continue;
        } else {
            cfg_nvecs = atoi(cfg_nvecs_str.c_str());
        }
        configuration.erase(0, commapos + 1);

        string cfg_nshifts_str = configuration;
        if (!cfg_nshifts_str.compare("*")) {
            cfg_nshifts = nshifts;
        } else {
            cfg_nshifts = atoi(cfg_nshifts_str.c_str());
        }

        if (chunkheight == cfg_chunkheight && nshifts == cfg_nshifts) {
            nvecs_vec.push_back(cfg_nvecs);
        }

        configurations.erase(0, pos + 1);
    }

    sort(nvecs_vec.begin(), nvecs_vec.end());
    *n = nvecs_vec.size();
    ghost_malloc((void **)nvecs, sizeof(int) * (*n));

    int i;
    for (i = 0; i < *n; i++) {
        (*nvecs)[i] = nvecs_vec[i];
    }

    return GHOST_SUCCESS;
}

ghost_error ghost_autogen_spmmv_nvecs(int **nvecs, int *n, int chunkheight)
{
    string configurations;
    ghost_type mytype;
    ghost_type_get(&mytype);

    if (mytype == GHOST_TYPE_CUDA) {
        configurations = GHOST_AUTOGEN_SPMMV_CUDA;
    } else {
        configurations = GHOST_AUTOGEN_SPMMV;
    }

    if (configurations[configurations.length() - 1] != ';') {
        configurations += ";";
    }

    size_t pos = 0, commapos = 0;
    int cfg_chunkheight, cfg_nvecs;
    string configuration;
    vector<int> nvecs_vec;

    while ((pos = configurations.find(";")) != string::npos) {
        configuration = configurations.substr(0, pos);

        commapos = configuration.find(",");
        string cfg_chunkheight_str = configuration.substr(0, commapos);

        if (!cfg_chunkheight_str.compare("*")) {
            cfg_chunkheight = chunkheight;
        } else {
            cfg_chunkheight = atoi(cfg_chunkheight_str.c_str());
        }
        configuration.erase(0, commapos + 1);

        commapos = configuration.find(",");
        string cfg_nvecs_str = configuration.substr(0, commapos);
        if (!cfg_nvecs_str.compare("*")) {
            configurations.erase(0, pos + 1);
            continue;
        } else {
            cfg_nvecs = atoi(cfg_nvecs_str.c_str());
        }
        if (chunkheight == cfg_chunkheight) {
            nvecs_vec.push_back(cfg_nvecs);
        }
        configurations.erase(0, pos + 1);
    }

    sort(nvecs_vec.begin(), nvecs_vec.end());
    *n = nvecs_vec.size();
    ghost_malloc((void **)nvecs, sizeof(int) * (*n));

    int i;
    for (i = 0; i < *n; i++) {
        (*nvecs)[i] = nvecs_vec[i];
    }

    return GHOST_SUCCESS;
}

int ghost_autogen_spmmv_next_nvecs(int desired_nvecs, int chunkheight)
{
    int *nvecs = NULL;
    int n, i, found_nvecs = 0;

    if (ghost_autogen_spmmv_nvecs(&nvecs, &n, chunkheight) != GHOST_SUCCESS) {
        return 0;
    }
    if (n == 0) {
        free(nvecs);
        return 0;
    }
    for (i = n - 1; i >= 0; i--) {
        if (nvecs[i] <= desired_nvecs) {
            found_nvecs = nvecs[i];
            break;
        }
    }

    free(nvecs);

    return found_nvecs;
}

ghost_error ghost_autogen_string_add(const char *func, const char *par)
{
    autogen_str_map[string(func)].insert(string(par));
    return GHOST_SUCCESS;
}

const char *ghost_autogen_string()
{
    autogen_str = "";

    for (auto &func : autogen_str_map) {
        autogen_str += string("-DGHOST_AUTOGEN_") + func.first + "=\"";
        for (auto &par : func.second) {
            autogen_str += par + ";";
        }
        autogen_str += string("\" ");
    }
    return autogen_str.c_str();
}

void ghost_autogen_set_missing() { missingConfs = 1; }

int ghost_autogen_missing() { return missingConfs; }
<|endoftext|>


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

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

#include <mettle/driver/cmd_line.hpp>
#include <mettle/driver/log/child.hpp>
#include <mettle/driver/log/summary.hpp>
#include <mettle/driver/log/term.hpp>
#include <mettle/driver/subprocess_test_runner.hpp>

#include "cmd_line.hpp"
#include "run_test_files.hpp"
#include "test_compiler.hpp"

namespace caliber {

namespace {
  struct all_options : mettle::generic_options, mettle::driver_options,
                       mettle::output_options {
    all_options() {
      auto cxx = getenv("CXX");
      tool = cxx ? cxx : "c++";
    }

    std::string suite_name = "compilation tests";
    std::string tool;
    METTLE_OPTIONAL_NS::optional<int> output_fd;
    std::vector<std::string> files;
  };

  const char program_name[] = "caliber";
  void report_error(const std::string &message) {
    std::cerr << program_name << ": " << message << std::endl;
  }
}

} // namespace caliber

int main(int argc, const char *argv[]) {
  using namespace mettle;
  namespace opts = boost::program_options;

  auto factory = make_logger_factory();

  caliber::all_options args;
  auto generic = make_generic_options(args);
  auto driver = make_driver_options(args);
  auto output = make_output_options(args, factory);

  driver.add_options()
    ("suite-name,S", opts::value(&args.suite_name)->value_name("NAME"),
     "the name of the suite containing these tests")
    ("tool", opts::value(&args.tool)->value_name("TOOL"),
     "the tool to use for these tests")
  ;

  opts::options_description hidden("Hidden options");
  hidden.add_options()
    ("output-fd", opts::value(&args.output_fd),
     "pipe the results to this file descriptor")
    ("file", opts::value(&args.files), "input file")
  ;
  opts::positional_options_description pos;
  pos.add("file", -1);

  opts::variables_map vm;
  try {
    opts::options_description all;
    all.add(generic).add(driver).add(output).add(hidden);
    auto parsed = opts::command_line_parser(argc, argv)
      .options(all).positional(pos).run();

    opts::store(parsed, vm);
    opts::notify(vm);
  } catch(const std::exception &e) {
    caliber::report_error(e.what());
    return 2;
  }

  if(args.show_help) {
    caliber::per_file_options tmp;
    auto per_file = caliber::make_per_file_options(tmp);
    per_file.add(caliber::make_compiler_options());

    opts::options_description displayed;
    displayed.add(generic).add(driver).add(output).add(per_file);
    std::cout << displayed << std::endl;
    return 0;
  }

  if(args.files.empty()) {
    caliber::report_error("no inputs specified");
    return 1;
  }

  try {
    caliber::test_compiler compiler(args.tool, args.timeout);

    if(args.output_fd) {
      if(auto output_opt = has_option(output, vm)) {
        using namespace opts::command_line_style;
        caliber::report_error(output_opt->canonical_display_name(allow_long) +
                              " can't be used with --output-fd");
        return 2;
      }

      make_fd_private(*args.output_fd);
      namespace io = boost::iostreams;
      io::stream<io::file_descriptor_sink> fds(
        *args.output_fd, io::never_close_handle
      );
      log::child logger(fds);
      caliber::run_test_files(args.suite_name, args.files, logger, compiler,
                              args.filters);
      return 0;
    }

    term::enable(std::cout, color_enabled(args.color));
    indenting_ostream out(std::cout);

    log::summary logger(
      out, factory.make(args.output, out, args), args.show_time,
      args.show_terminal
    );
    caliber::run_test_files(args.suite_name, args.files, logger, compiler,
                            args.filters);

    logger.summarize();
    return !logger.good();
  }
  catch(const std::exception &e) {
    caliber::report_error(e.what());
    return 3;
  }
}
<commit_msg>Fix ambiguous command line option<commit_after>#include <cstdlib>
#include <iostream>
#include <vector>

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

#include <mettle/driver/cmd_line.hpp>
#include <mettle/driver/log/child.hpp>
#include <mettle/driver/log/summary.hpp>
#include <mettle/driver/log/term.hpp>
#include <mettle/driver/subprocess_test_runner.hpp>

#include "cmd_line.hpp"
#include "run_test_files.hpp"
#include "test_compiler.hpp"

namespace caliber {

namespace {
  struct all_options : mettle::generic_options, mettle::driver_options,
                       mettle::output_options {
    all_options() {
      auto cxx = getenv("CXX");
      tool = cxx ? cxx : "c++";
    }

    std::string suite_name = "compilation tests";
    std::string tool;
    METTLE_OPTIONAL_NS::optional<int> output_fd;
    std::vector<std::string> files;
  };

  const char program_name[] = "caliber";
  void report_error(const std::string &message) {
    std::cerr << program_name << ": " << message << std::endl;
  }
}

} // namespace caliber

int main(int argc, const char *argv[]) {
  using namespace mettle;
  namespace opts = boost::program_options;

  auto factory = make_logger_factory();

  caliber::all_options args;
  auto generic = make_generic_options(args);
  auto driver = make_driver_options(args);
  auto output = make_output_options(args, factory);

  driver.add_options()
    ("suite-name,S", opts::value(&args.suite_name)->value_name("NAME"),
     "the name of the suite containing these tests")
    ("tool", opts::value(&args.tool)->value_name("TOOL"),
     "the tool to use for these tests")
  ;

  opts::options_description hidden("Hidden options");
  hidden.add_options()
    ("output-fd", opts::value(&args.output_fd),
     "pipe the results to this file descriptor")
    ("input-file", opts::value(&args.files), "input file")
  ;
  opts::positional_options_description pos;
  pos.add("input-file", -1);

  opts::variables_map vm;
  try {
    opts::options_description all;
    all.add(generic).add(driver).add(output).add(hidden);
    auto parsed = opts::command_line_parser(argc, argv)
      .options(all).positional(pos).run();

    opts::store(parsed, vm);
    opts::notify(vm);
  } catch(const std::exception &e) {
    caliber::report_error(e.what());
    return 2;
  }

  if(args.show_help) {
    caliber::per_file_options tmp;
    auto per_file = caliber::make_per_file_options(tmp);
    per_file.add(caliber::make_compiler_options());

    opts::options_description displayed;
    displayed.add(generic).add(driver).add(output).add(per_file);
    std::cout << displayed << std::endl;
    return 0;
  }

  if(args.files.empty()) {
    caliber::report_error("no inputs specified");
    return 1;
  }

  try {
    caliber::test_compiler compiler(args.tool, args.timeout);

    if(args.output_fd) {
      if(auto output_opt = has_option(output, vm)) {
        using namespace opts::command_line_style;
        caliber::report_error(output_opt->canonical_display_name(allow_long) +
                              " can't be used with --output-fd");
        return 2;
      }

      make_fd_private(*args.output_fd);
      namespace io = boost::iostreams;
      io::stream<io::file_descriptor_sink> fds(
        *args.output_fd, io::never_close_handle
      );
      log::child logger(fds);
      caliber::run_test_files(args.suite_name, args.files, logger, compiler,
                              args.filters);
      return 0;
    }

    term::enable(std::cout, color_enabled(args.color));
    indenting_ostream out(std::cout);

    log::summary logger(
      out, factory.make(args.output, out, args), args.show_time,
      args.show_terminal
    );
    caliber::run_test_files(args.suite_name, args.files, logger, compiler,
                            args.filters);

    logger.summarize();
    return !logger.good();
  }
  catch(const std::exception &e) {
    caliber::report_error(e.what());
    return 3;
  }
}
<|endoftext|>


<commit_before>/*
 MCMC SAMPLER FOR A CAR(p) PROCESS.

 AUTHOR: DR. BRANDON C. KELLY, DEC 2012
		 DEPT. OF PHYSICS
		 UNIV. OF CALIFORNIA, SANTA BARBARA

 TESTING HISTORY:

 ************ CAR(1) ************

 PASS: Test loading in data and instantiating CAR1 class, including
	   when the time values are not sorted and contain duplicates (12/20/2012)
 PASS: CAR1::StartingValue (12/20/2012)
 PASS: CAR1::Value (12/20/2012)
 PASS: CAR1::StringValue (12/20/2012)
 PASS: CAR1::Save (12/20/2012)
 PASS: CAR1::KalmanFilter (12/21/2012)
 PASS: CAR1::LogDensity
 PASS: Test MCMC sampler without measurement errors, starting at true values. (12/21/2012)
 PASS: Test MCMC sampler without meas. errors, with random starts. (12/21/2012)
 PASS: Test MCMC sampler with measurement errors, starting at true values. (12/21/2012)
 PASS: Test MCMC sampler with measurement errors, with random startings values. (12/21/2012)
 PASS: Test MCMC sampler with all of above for time series with long gaps (12/24/2012)
 PASS: Test MCMC sampler on real AGN lightcurve, compare with IDL results (1/3/2013)

 ************* CAR(p) ************

 PASS: Test loading in data and instantiating CARp object, including
	   when the time values are not sorted and contain duplicates (12/31/2012)
 PASS: Test root finding algorithm and polycoefs function (12/31/2012)
 PASS: Test unique_roots function (12/31/2012)
 PASS: Within StartingValue, test alpha_roots --> phi and phi --> alpha_roots (12/31/2012)
 PASS: CARp::StartingValue (12/31/2012)
 PASS: CARp::Value (1/1/2013)
 PASS: CARp::StringValue (1/1/2013)
 PASS: CARp::SetKappa (1/1/2013)
 PASS: CARp::Save (1/1/2013)
 PASS: CARp::Variance (1/1/2013)
 PASS: CARp::KalmanFilter (1/2/2013)
 PASS: CARp::LogDensity (1/3/2013)

 Generated a CAR(1) process without measurement errors in IDL as follows:

 ny = 1000
 dt = randomu(seed, ny)
 time = total(dt, /cum)
 tau = 25.0
 omega = 1.0 / tau
 sigma = 1.0
 mu = 6.0
 kappa = 1.0 / median(time[1:*] - time)
 phi = -1.0 * (1.0 + omega / kappa) / (1.0 - omega / kappa)
 y = ouprocess(seed, time, tau, sigma) + mu

 Test fitting this data with a CAR(2) process. Did the following tests to compare
 the model powerspectrum with the true powerspectrum:

 PASS: Test MCMC sampler without measurement errors, starting at true values. (1/7/2013)
 PASS: Test MCMC sampler without meas. errors, with random starts. (1/7/2013)
 PASS: Test MCMC sampler with 10% measurement errors, with random startings values. (1/7/2013)

 Generated a CAR(2) process without measurement errors in IDL as follows:

 ny = 1000
 dt = randomu(seed, ny)
 time = total(dt, /cum)
 lorentz_cent = 1d / 25.0
 lorentz_width = 1d / 100.0
 roots = dcomplexarr(2)
 roots[0] = dcomplex(-1.0 * lorentz_width, lorentz_cent)
 roots[1] = dcomplex(-1.0 * lorentz_width, -1.0 * lorentz_cent)
 roots = roots * 2.0 * !pi
 sigma = 1.0
 mu = 6.0
 alpha = polycoefs(roots)
 alpha = alpha[1:*]
 kappa = 1.0 / median(time[1:*]-time)
 y = carma_process(seed, time, sigma^2, reverse(alpha), kappa=kappa) + mu

 phi_roots = (1.0 + roots / kappa) / (1.0 - roots / kappa)
 phi = polycoefs(phi_roots)
 phi = phi[1:*]
 print, phi
 -1.9530404      0.95999374

 PASS: Test MCMC sampler without measurement errors, starting at true values. (1/8/2013)
 PASS: Test MCMC sampler without meas. errors, with random starts. (1/8/2013)
 PASS: Test MCMC sampler with measurement errors, with random startings values. (1/8/2013)
 PASS, but slow convergence: Test MCMC sampler with meas. err., random starts, and using a CAR(3) process. (1/9/2013)

 Test MCMC sampler with all of above but for a CAR(5) process
 Test MCMC sampler with all of above for time series with long gaps
 Test MCMC sampler on real AGN lightcurve, compare with IDL results

 TODO:
	- Include optimizer to start the sampler off at the maximum-likelihood estimate,
	  use Fisher information matrix as initial guess for proposal scale matrix.

 */

// Standard includes
#include <iostream>
#include <fstream>
// Include the MCMC sampler header files
#include <yamcmc++>
// Local include
#include "carpack.hpp"

// Function prototypes
void RunCarSampler(MCMCOptions mcmc_options, arma::vec& time, arma::vec& y,
                   arma::vec& yerr, int p);
void RunEnsembleCarSampler(MCMCOptions mcmc_options, arma::vec& time, arma::vec& y,
						   arma::vec& yerr, int p, int nwalkers);

// Temporary testing functions
void test_carp(arma::vec& time, arma::vec& y, arma::vec& yerr, int p);
void test_exchange(arma::vec& time, arma::vec& y, arma::vec& yerr, int nwalkers);

// Global variables
const double target_arate = 0.30; // Target acceptance rate for RAM

// Global random number generator object, instantiated in random.cpp
extern boost::random::mt19937 rng;

// Object containing some common random number generators.
extern RandomGenerator RandGen;

int main (int argc, char * const argv[])
{
	// Find what directory we are in
	//std::string idirectory = get_initial_directory();

    std::string idirectory = ".";

	// Prompt user for MCMC parameters
	MCMCOptions mcmc_options = mcmc_options_prompt(idirectory);

	int car_order = -1;
	do {
		std::cout << "Fit a CAR(p) process of what order? (p>0) ";
		std::cin >> car_order;
		std::cout << std::endl;
	} while (car_order <= 0);

	int nwalkers = -1;
	do {
		std::cout << "Use how many walkers for ensemble sampler? (n>p+2) ";
		std::cin >> nwalkers;
		std::cout << std::endl;
	} while (nwalkers <= car_order+2);

	// Load data
	arma::vec time, y, yerr;
	arma::mat Data;

	Data.load(mcmc_options.data_file);
	time = Data.col(0);
	y = Data.col(1);
	yerr = Data.col(2);

	// Run the samplers
    //RunCarSampler(mcmc_options, time, y, yerr, car_order);
    RunEnsembleCarSampler(mcmc_options, time, y, yerr, car_order, nwalkers);

	return 0;
}

// Run the MCMC sampler for a CAR(p) process
void RunEnsembleCarSampler(MCMCOptions mcmc_options, arma::vec& time, arma::vec& y,
						   arma::vec& yerr, int p, int nwalkers)
{
    // Instantiate MCMC Sampler object for CAR process
	Sampler CarModel(mcmc_options);

	// Construct the parameter ensemble
    Ensemble<CAR1> CarEnsemble;

	double max_stdev = 10.0 * arma::stddev(y); // For prior: maximum standard-deviation of CAR(1) process

    // Set the temperature ladder. The logarithms of the temperatures are on a linear grid
    double max_temperature = 100.0;

    arma::vec temp_ladder = arma::linspace<arma::vec>(0.0, log(max_temperature), nwalkers);
    temp_ladder = arma::exp(temp_ladder);

    // Add the parameters to the ensemble, starting with the coolest chain
	for (int i=0; i<nwalkers; i++) {
		// Add this walker to the ensemble
		if (p == 1) {
			// Doing a CAR(1) model
			CarEnsemble.AddObject(new CAR1(false, "CAR(1) Parameters", time, y, yerr, temp_ladder(i)));
		} else {
			// Doing a CAR(p) model
			CarEnsemble.AddObject(new CARp(false, "CAR(p) Parameters", time, y, yerr, p, temp_ladder(i)));
		}

		// Set the prior parameters
        CarEnsemble[i].SetPrior(max_stdev);
	}

    // Report average acceptance rates at end of sampler
    int report_iter = mcmc_options.burnin + mcmc_options.thin * mcmc_options.sample_size;

    // Setup initial covariance matrix for RAM proposals. This
	// is just a diagonal matrix with the diagonal elements equal to 0.01^2.
	//
	// TODO: Get a better guess from maximum-likelihood fit
	//
	arma::mat prop_covar(2+p,2+p);
	prop_covar.eye();
	prop_covar.diag() = prop_covar.diag() * 0.01 * 0.01;
    prop_covar(0,0) = 2.0 * arma::var(y) * arma::var(y) / y.n_elem;

	// Instantiate base proposal object
    StudentProposal RAMProp(8.0, 1.0);
	//NormalProposal RAMProp(1.0);

    double target_rate = 0.2;

    //test_ptemp(CarEnsemble, RAMProp, prop_covar);

    // Add the steps to the sampler, starting with the hottest chain first
    for (int i=nwalkers-1; i>0; i--) {
        // First add Robust Adaptive Metropolis Step
        CarModel.AddStep( new AdaptiveMetro(CarEnsemble[i], RAMProp, prop_covar,
                                            target_rate, mcmc_options.burnin) );
        // Now add Exchange steps
        CarModel.AddStep( new ExchangeStep<arma::vec, CAR1>(CarEnsemble[i], i, CarEnsemble, report_iter) );
    }

    // Make sure we set this parameter to be tracked
    CarEnsemble[0].SetTracking(true);
    // Add in coolest chain. This is the chain that is actually moving in the posterior.
    CarModel.AddStep( new AdaptiveMetro(CarEnsemble[0], RAMProp, prop_covar, target_rate, mcmc_options.burnin) );

    // Now run the MCMC sampler. The samples will be dumped in the
    // output file provided by the user.

	CarModel.Run();
}

// Run the MCMC sampler for a CAR(p) process
void RunCarSampler(MCMCOptions mcmc_options, arma::vec& time, arma::vec& y,
                   arma::vec& yerr, int p)
{
    // Instantiate MCMC Sampler object for CAR process
	Sampler CarModel(mcmc_options);

	double max_stdev = 10.0 * arma::stddev(y); // For prior: maximum standard-deviation of CAR(1) process

    // Setup initial covariance matrix for RAM proposals. This
	// is just a diagonal matrix with the diagonal elements equal to 0.01^2.
	//
	// TODO: Get a better guess from maximum-likelihood fit
	//
	arma::mat prop_covar(2+p,2+p);
	prop_covar.eye();
	prop_covar.diag() = prop_covar.diag() * 0.01 * 0.01;
    prop_covar(0,0) = 2.0 * arma::var(y) * arma::var(y) / y.n_elem;

	// Instantiate base proposal object
    StudentProposal RAMProp(8.0, 1.0);
	//NormalProposal RAMProp(1.0);

    CAR1 CarParameter(true, "CAR(1)", time, y, yerr);
    CarParameter.SetPrior(max_stdev);

    double target_rate = 0.2;
    CarModel.AddStep( new AdaptiveMetro(CarParameter, RAMProp, prop_covar, target_rate, mcmc_options.burnin) );

    // Now run the MCMC sampler. The samples will be dumped in the
    // output file provided by the user.

	CarModel.Run();
}
<commit_msg>Updated use of sampler object to be compatible with new version of yamcmc++: sampler object no longer dumps samples to a file, but save them in memory.<commit_after>/*
 MCMC SAMPLER FOR A CAR(p) PROCESS.

 AUTHOR: DR. BRANDON C. KELLY, DEC 2012
		 DEPT. OF PHYSICS
		 UNIV. OF CALIFORNIA, SANTA BARBARA

 TESTING HISTORY:

 ************ CAR(1) ************

 PASS: Test loading in data and instantiating CAR1 class, including
	   when the time values are not sorted and contain duplicates (12/20/2012)
 PASS: CAR1::StartingValue (12/20/2012)
 PASS: CAR1::Value (12/20/2012)
 PASS: CAR1::StringValue (12/20/2012)
 PASS: CAR1::Save (12/20/2012)
 PASS: CAR1::KalmanFilter (12/21/2012)
 PASS: CAR1::LogDensity
 PASS: Test MCMC sampler without measurement errors, starting at true values. (12/21/2012)
 PASS: Test MCMC sampler without meas. errors, with random starts. (12/21/2012)
 PASS: Test MCMC sampler with measurement errors, starting at true values. (12/21/2012)
 PASS: Test MCMC sampler with measurement errors, with random startings values. (12/21/2012)
 PASS: Test MCMC sampler with all of above for time series with long gaps (12/24/2012)
 PASS: Test MCMC sampler on real AGN lightcurve, compare with IDL results (1/3/2013)

 ************* CAR(p) ************

 PASS: Test loading in data and instantiating CARp object, including
	   when the time values are not sorted and contain duplicates (12/31/2012)
 PASS: Test root finding algorithm and polycoefs function (12/31/2012)
 PASS: Test unique_roots function (12/31/2012)
 PASS: Within StartingValue, test alpha_roots --> phi and phi --> alpha_roots (12/31/2012)
 PASS: CARp::StartingValue (12/31/2012)
 PASS: CARp::Value (1/1/2013)
 PASS: CARp::StringValue (1/1/2013)
 PASS: CARp::SetKappa (1/1/2013)
 PASS: CARp::Save (1/1/2013)
 PASS: CARp::Variance (1/1/2013)
 PASS: CARp::KalmanFilter (1/2/2013)
 PASS: CARp::LogDensity (1/3/2013)

 Generated a CAR(1) process without measurement errors in IDL as follows:

 ny = 1000
 dt = randomu(seed, ny)
 time = total(dt, /cum)
 tau = 25.0
 omega = 1.0 / tau
 sigma = 1.0
 mu = 6.0
 kappa = 1.0 / median(time[1:*] - time)
 phi = -1.0 * (1.0 + omega / kappa) / (1.0 - omega / kappa)
 y = ouprocess(seed, time, tau, sigma) + mu

 Test fitting this data with a CAR(2) process. Did the following tests to compare
 the model powerspectrum with the true powerspectrum:

 PASS: Test MCMC sampler without measurement errors, starting at true values. (1/7/2013)
 PASS: Test MCMC sampler without meas. errors, with random starts. (1/7/2013)
 PASS: Test MCMC sampler with 10% measurement errors, with random startings values. (1/7/2013)

 Generated a CAR(2) process without measurement errors in IDL as follows:

 ny = 1000
 dt = randomu(seed, ny)
 time = total(dt, /cum)
 lorentz_cent = 1d / 25.0
 lorentz_width = 1d / 100.0
 roots = dcomplexarr(2)
 roots[0] = dcomplex(-1.0 * lorentz_width, lorentz_cent)
 roots[1] = dcomplex(-1.0 * lorentz_width, -1.0 * lorentz_cent)
 roots = roots * 2.0 * !pi
 sigma = 1.0
 mu = 6.0
 alpha = polycoefs(roots)
 alpha = alpha[1:*]
 kappa = 1.0 / median(time[1:*]-time)
 y = carma_process(seed, time, sigma^2, reverse(alpha), kappa=kappa) + mu

 phi_roots = (1.0 + roots / kappa) / (1.0 - roots / kappa)
 phi = polycoefs(phi_roots)
 phi = phi[1:*]
 print, phi
 -1.9530404      0.95999374

 PASS: Test MCMC sampler without measurement errors, starting at true values. (1/8/2013)
 PASS: Test MCMC sampler without meas. errors, with random starts. (1/8/2013)
 PASS: Test MCMC sampler with measurement errors, with random startings values. (1/8/2013)
 PASS, but slow convergence: Test MCMC sampler with meas. err., random starts, and using a CAR(3) process. (1/9/2013)

 Test MCMC sampler with all of above but for a CAR(5) process
 Test MCMC sampler with all of above for time series with long gaps
 Test MCMC sampler on real AGN lightcurve, compare with IDL results

 TODO:
	- Include optimizer to start the sampler off at the maximum-likelihood estimate,
	  use Fisher information matrix as initial guess for proposal scale matrix.

 */

// Standard includes
#include <iostream>
#include <fstream>
#include <vector>
// Include the MCMC sampler header files
#include <yamcmc++>
// Local include
#include "carpack.hpp"

// Function prototypes
std::vector<arma::vec> RunEnsembleCarSampler(MCMCOptions mcmc_options, arma::vec& time, arma::vec& y,
                                             arma::vec& yerr, int p, int nwalkers);

// Temporary testing functions
void test_carp(arma::vec& time, arma::vec& y, arma::vec& yerr, int p);
void test_exchange(arma::vec& time, arma::vec& y, arma::vec& yerr, int nwalkers);

// Global variables
const double target_arate = 0.30; // Target acceptance rate for RAM

// Global random number generator object, instantiated in random.cpp
extern boost::random::mt19937 rng;

// Object containing some common random number generators.
extern RandomGenerator RandGen;

int main (int argc, char * const argv[])
{
	// Find what directory we are in
	//std::string idirectory = get_initial_directory();

    std::string idirectory = ".";

	// Prompt user for MCMC parameters
	MCMCOptions mcmc_options = mcmc_options_prompt(idirectory);

	int car_order = -1;
	do {
		std::cout << "Fit a CAR(p) process of what order? (p>0) ";
		std::cin >> car_order;
		std::cout << std::endl;
	} while (car_order <= 0);

	int nwalkers = -1;
	do {
		std::cout << "Use how many walkers for ensemble sampler? (n>p+2) ";
		std::cin >> nwalkers;
		std::cout << std::endl;
	} while (nwalkers <= car_order+2);

	// Load data
	arma::vec time, y, yerr;
	arma::mat Data;

	Data.load(mcmc_options.data_file);
	time = Data.col(0);
	y = Data.col(1);
	yerr = Data.col(2);

	// Run the sampler
    std::vector<arma::vec> car_samples;
    car_samples = RunEnsembleCarSampler(mcmc_options, time, y, yerr, car_order, nwalkers);

    // Save the samples to the output file
    std::ofstream outfile(mcmc_options.out_file);
    for (int i=0; i<car_samples.size(); i++) {
        for (int j=0; j<car_samples[0].n_elem; j++) {
            outfile << car_samples[i](j) << " ";
        }
        outfile << std::endl;
    }
    outfile.close();

	return 0;
}

// Run the MCMC sampler for a CAR(p) process
std::vector<arma::vec> RunEnsembleCarSampler(MCMCOptions mcmc_options, arma::vec& time, arma::vec& y,
                                             arma::vec& yerr, int p, int nwalkers)
{
    // Instantiate MCMC Sampler object for CAR process
	Sampler CarModel(mcmc_options.sample_size, mcmc_options.burnin, mcmc_options.thin);

	// Construct the parameter ensemble
    Ensemble<CAR1> CarEnsemble;

	double max_stdev = 10.0 * arma::stddev(y); // For prior: maximum standard-deviation of CAR(1) process

    // Set the temperature ladder. The logarithms of the temperatures are on a linear grid
    double max_temperature = 100.0;

    arma::vec temp_ladder = arma::linspace<arma::vec>(0.0, log(max_temperature), nwalkers);
    temp_ladder = arma::exp(temp_ladder);

    // Add the parameters to the ensemble, starting with the coolest chain
	for (int i=0; i<nwalkers; i++) {
		// Add this walker to the ensemble
		if (p == 1) {
			// Doing a CAR(1) model
			CarEnsemble.AddObject(new CAR1(false, "CAR(1) Parameters", time, y, yerr, temp_ladder(i)));
		} else {
			// Doing a CAR(p) model
			CarEnsemble.AddObject(new CARp(false, "CAR(p) Parameters", time, y, yerr, p, temp_ladder(i)));
		}

		// Set the prior parameters
        CarEnsemble[i].SetPrior(max_stdev);
	}

    // Report average acceptance rates at end of sampler
    int report_iter = mcmc_options.burnin + mcmc_options.thin * mcmc_options.sample_size;

    // Setup initial covariance matrix for RAM proposals. This
	// is just a diagonal matrix with the diagonal elements equal to 0.01^2.
	//
	// TODO: Get a better guess from maximum-likelihood fit
	//
	arma::mat prop_covar(2+p,2+p);
	prop_covar.eye();
	prop_covar.diag() = prop_covar.diag() * 0.01 * 0.01;
    prop_covar(0,0) = 2.0 * arma::var(y) * arma::var(y) / y.n_elem;

	// Instantiate base proposal object
    StudentProposal RAMProp(8.0, 1.0);
	//NormalProposal RAMProp(1.0);

    double target_rate = 0.2;

    //test_ptemp(CarEnsemble, RAMProp, prop_covar);

    // Add the steps to the sampler, starting with the hottest chain first
    for (int i=nwalkers-1; i>0; i--) {
        // First add Robust Adaptive Metropolis Step
        CarModel.AddStep( new AdaptiveMetro(CarEnsemble[i], RAMProp, prop_covar,
                                            target_rate, mcmc_options.burnin) );
        // Now add Exchange steps
        CarModel.AddStep( new ExchangeStep<arma::vec, CAR1>(CarEnsemble[i], i, CarEnsemble, report_iter) );
    }

    // Make sure we set this parameter to be tracked
    CarEnsemble[0].SetTracking(true);
    // Add in coolest chain. This is the chain that is actually moving in the posterior.
    CarModel.AddStep( new AdaptiveMetro(CarEnsemble[0], RAMProp, prop_covar, target_rate, mcmc_options.burnin) );

    // Now run the MCMC sampler. The samples will be dumped in the
    // output file provided by the user.

	CarModel.Run();

    std::vector<arma::vec> car_samples = CarEnsemble[0].GetSamples();

    return car_samples;
}
<|endoftext|>