<commit_before>/*
 * Copyright (C) 2015 ScyllaDB
 */

/*
 * This file is part of Scylla.
 *
 * Scylla is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Scylla is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Scylla.  If not, see <http://www.gnu.org/licenses/>.
 */

#pragma once

#include "query-request.hh"
#include "query-result.hh"
#include "mutation_reader.hh"
#include "frozen_mutation.hh"
#include "db/timeout_clock.hh"
#include "querier.hh"
#include "utils/chunked_vector.hh"
#include "query_class_config.hh"
#include <seastar/core/execution_stage.hh>

class reconcilable_result;
class frozen_reconcilable_result;

// Can be read by other cores after publishing.
struct partition {
    uint32_t _row_count_low_bits;
    frozen_mutation _m; // FIXME: We don't need cf UUID, which frozen_mutation includes.
    uint32_t _row_count_high_bits;
    partition(uint32_t row_count_low_bits, frozen_mutation m, uint32_t row_count_high_bits)
        : _row_count_low_bits(row_count_low_bits)
        , _m(std::move(m))
        , _row_count_high_bits(row_count_high_bits)
    { }

    partition(uint64_t row_count, frozen_mutation m)
        : _row_count_low_bits(static_cast<uint32_t>(row_count))
        , _m(std::move(m))
        , _row_count_high_bits(static_cast<uint32_t>(row_count >> 32))
    { }

    uint32_t row_count_low_bits() const {
        return _row_count_low_bits;
    }

    uint32_t row_count_high_bits() const {
        return _row_count_high_bits;
    }

    uint64_t row_count() const {
        return (static_cast<uint64_t>(_row_count_high_bits) << 32) | _row_count_low_bits;
    }

    const frozen_mutation& mut() const {
        return _m;
    }

    frozen_mutation& mut() {
        return _m;
    }

    bool operator==(const partition& other) const {
        return row_count() == other.row_count() && _m.representation() == other._m.representation();
    }

    bool operator!=(const partition& other) const {
        return !(*this == other);
    }
};

// The partitions held by this object are ordered according to dht::decorated_key ordering and non-overlapping.
// Each mutation must have different key.
//
// Can be read by other cores after publishing.
class reconcilable_result {
    uint32_t _row_count_low_bits;
    query::short_read _short_read;
    query::result_memory_tracker _memory_tracker;
    utils::chunked_vector<partition> _partitions;
    uint32_t _row_count_high_bits;
public:
    ~reconcilable_result();
    reconcilable_result();
    reconcilable_result(reconcilable_result&&) = default;
    reconcilable_result& operator=(reconcilable_result&&) = default;
    reconcilable_result(uint32_t row_count_low_bits, utils::chunked_vector<partition> partitions, query::short_read short_read,
                        uint32_t row_count_high_bits, query::result_memory_tracker memory_tracker = { });
    reconcilable_result(uint64_t row_count, utils::chunked_vector<partition> partitions, query::short_read short_read,
                        query::result_memory_tracker memory_tracker = { });

    const utils::chunked_vector<partition>& partitions() const;
    utils::chunked_vector<partition>& partitions();

    uint32_t row_count_low_bits() const {
        return _row_count_low_bits;
    }

    uint32_t row_count_high_bits() const {
        return _row_count_high_bits;
    }

    uint64_t row_count() const {
        return (static_cast<uint64_t>(_row_count_high_bits) << 32) | _row_count_low_bits;
    }

    query::short_read is_short_read() const {
        return _short_read;
    }

    size_t memory_usage() const {
        return _memory_tracker.used_memory();
    }

    bool operator==(const reconcilable_result& other) const;
    bool operator!=(const reconcilable_result& other) const;

    struct printer {
        const reconcilable_result& self;
        schema_ptr schema;
        friend std::ostream& operator<<(std::ostream&, const printer&);
    };

    printer pretty_printer(schema_ptr) const;
};

class reconcilable_result_builder {
    const schema& _schema;
    const query::partition_slice& _slice;

    bool _return_static_content_on_partition_with_no_rows{};
    bool _static_row_is_alive{};
    uint64_t _total_live_rows = 0;
    query::result_memory_accounter _memory_accounter;
    stop_iteration _stop;
    std::optional<streamed_mutation_freezer> _mutation_consumer;

    uint64_t _live_rows{};
    // make this the last member so it is destroyed first. #7240
    utils::chunked_vector<partition> _result;
public:
    reconcilable_result_builder(const schema& s, const query::partition_slice& slice,
                                query::result_memory_accounter&& accounter)
        : _schema(s), _slice(slice)
        , _memory_accounter(std::move(accounter))
    { }

    void consume_new_partition(const dht::decorated_key& dk);
    void consume(tombstone t);
    stop_iteration consume(static_row&& sr, tombstone, bool is_alive);
    stop_iteration consume(clustering_row&& cr, row_tombstone, bool is_alive);
    stop_iteration consume(range_tombstone&& rt);
    stop_iteration consume_end_of_partition();
    reconcilable_result consume_end_of_stream();
};

query::result to_data_query_result(const reconcilable_result&, schema_ptr, const query::partition_slice&, uint64_t row_limit, uint32_t partition_limit, query::result_options opts = query::result_options::only_result());

// Performs a query on given data source returning data in reconcilable form.
//
// Reads at most row_limit rows. If less rows are returned, the data source
// didn't have more live data satisfying the query.
//
// Any cells which have expired according to query_time are returned as
// deleted cells and do not count towards live data. The mutations are
// compact, meaning that any cell which is covered by higher-level tombstone
// is absent in the results.
//
// 'source' doesn't have to survive deferring.
future<reconcilable_result> mutation_query(
    schema_ptr,
    mutation_source source,
    const dht::partition_range& range,
    const query::partition_slice& slice,
    uint64_t row_limit,
    uint32_t partition_limit,
    gc_clock::time_point query_time,
    db::timeout_clock::time_point timeout,
    query::query_class_config class_config,
    query::result_memory_accounter&& accounter,
    tracing::trace_state_ptr trace_ptr = nullptr,
    query::querier_cache_context cache_ctx = { });

future<> data_query(
    schema_ptr s,
    const mutation_source& source,
    const dht::partition_range& range,
    const query::partition_slice& slice,
    uint64_t row_limit,
    uint32_t partition_limit,
    gc_clock::time_point query_time,
    query::result::builder& builder,
    db::timeout_clock::time_point timeout,
    query::query_class_config class_config,
    tracing::trace_state_ptr trace_ptr = nullptr,
    query::querier_cache_context cache_ctx = { });

class mutation_query_stage {
    inheriting_concrete_execution_stage<future<reconcilable_result>,
        schema_ptr,
        mutation_source,
        const dht::partition_range&,
        const query::partition_slice&,
        uint32_t,
        uint32_t,
        gc_clock::time_point,
        db::timeout_clock::time_point,
        query::query_class_config,
        query::result_memory_accounter&&,
        tracing::trace_state_ptr,
        query::querier_cache_context> _execution_stage;
public:
    explicit mutation_query_stage();
    template <typename... Args>
    future<reconcilable_result> operator()(Args&&... args) { return _execution_stage(std::forward<Args>(args)...); }
};

// Performs a query for counter updates.
future<mutation_opt> counter_write_query(schema_ptr, const mutation_source&, reader_permit permit,
                                         const dht::decorated_key& dk,
                                         const query::partition_slice& slice,
                                         tracing::trace_state_ptr trace_ptr,
                                         db::timeout_clock::time_point timeout);

<commit_msg>mutation_query: mutation_query_stage: add get_stats()<commit_after>/*
 * Copyright (C) 2015 ScyllaDB
 */

/*
 * This file is part of Scylla.
 *
 * Scylla is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Scylla is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Scylla.  If not, see <http://www.gnu.org/licenses/>.
 */

#pragma once

#include "query-request.hh"
#include "query-result.hh"
#include "mutation_reader.hh"
#include "frozen_mutation.hh"
#include "db/timeout_clock.hh"
#include "querier.hh"
#include "utils/chunked_vector.hh"
#include "query_class_config.hh"
#include <seastar/core/execution_stage.hh>

class reconcilable_result;
class frozen_reconcilable_result;

// Can be read by other cores after publishing.
struct partition {
    uint32_t _row_count_low_bits;
    frozen_mutation _m; // FIXME: We don't need cf UUID, which frozen_mutation includes.
    uint32_t _row_count_high_bits;
    partition(uint32_t row_count_low_bits, frozen_mutation m, uint32_t row_count_high_bits)
        : _row_count_low_bits(row_count_low_bits)
        , _m(std::move(m))
        , _row_count_high_bits(row_count_high_bits)
    { }

    partition(uint64_t row_count, frozen_mutation m)
        : _row_count_low_bits(static_cast<uint32_t>(row_count))
        , _m(std::move(m))
        , _row_count_high_bits(static_cast<uint32_t>(row_count >> 32))
    { }

    uint32_t row_count_low_bits() const {
        return _row_count_low_bits;
    }

    uint32_t row_count_high_bits() const {
        return _row_count_high_bits;
    }

    uint64_t row_count() const {
        return (static_cast<uint64_t>(_row_count_high_bits) << 32) | _row_count_low_bits;
    }

    const frozen_mutation& mut() const {
        return _m;
    }

    frozen_mutation& mut() {
        return _m;
    }

    bool operator==(const partition& other) const {
        return row_count() == other.row_count() && _m.representation() == other._m.representation();
    }

    bool operator!=(const partition& other) const {
        return !(*this == other);
    }
};

// The partitions held by this object are ordered according to dht::decorated_key ordering and non-overlapping.
// Each mutation must have different key.
//
// Can be read by other cores after publishing.
class reconcilable_result {
    uint32_t _row_count_low_bits;
    query::short_read _short_read;
    query::result_memory_tracker _memory_tracker;
    utils::chunked_vector<partition> _partitions;
    uint32_t _row_count_high_bits;
public:
    ~reconcilable_result();
    reconcilable_result();
    reconcilable_result(reconcilable_result&&) = default;
    reconcilable_result& operator=(reconcilable_result&&) = default;
    reconcilable_result(uint32_t row_count_low_bits, utils::chunked_vector<partition> partitions, query::short_read short_read,
                        uint32_t row_count_high_bits, query::result_memory_tracker memory_tracker = { });
    reconcilable_result(uint64_t row_count, utils::chunked_vector<partition> partitions, query::short_read short_read,
                        query::result_memory_tracker memory_tracker = { });

    const utils::chunked_vector<partition>& partitions() const;
    utils::chunked_vector<partition>& partitions();

    uint32_t row_count_low_bits() const {
        return _row_count_low_bits;
    }

    uint32_t row_count_high_bits() const {
        return _row_count_high_bits;
    }

    uint64_t row_count() const {
        return (static_cast<uint64_t>(_row_count_high_bits) << 32) | _row_count_low_bits;
    }

    query::short_read is_short_read() const {
        return _short_read;
    }

    size_t memory_usage() const {
        return _memory_tracker.used_memory();
    }

    bool operator==(const reconcilable_result& other) const;
    bool operator!=(const reconcilable_result& other) const;

    struct printer {
        const reconcilable_result& self;
        schema_ptr schema;
        friend std::ostream& operator<<(std::ostream&, const printer&);
    };

    printer pretty_printer(schema_ptr) const;
};

class reconcilable_result_builder {
    const schema& _schema;
    const query::partition_slice& _slice;

    bool _return_static_content_on_partition_with_no_rows{};
    bool _static_row_is_alive{};
    uint64_t _total_live_rows = 0;
    query::result_memory_accounter _memory_accounter;
    stop_iteration _stop;
    std::optional<streamed_mutation_freezer> _mutation_consumer;

    uint64_t _live_rows{};
    // make this the last member so it is destroyed first. #7240
    utils::chunked_vector<partition> _result;
public:
    reconcilable_result_builder(const schema& s, const query::partition_slice& slice,
                                query::result_memory_accounter&& accounter)
        : _schema(s), _slice(slice)
        , _memory_accounter(std::move(accounter))
    { }

    void consume_new_partition(const dht::decorated_key& dk);
    void consume(tombstone t);
    stop_iteration consume(static_row&& sr, tombstone, bool is_alive);
    stop_iteration consume(clustering_row&& cr, row_tombstone, bool is_alive);
    stop_iteration consume(range_tombstone&& rt);
    stop_iteration consume_end_of_partition();
    reconcilable_result consume_end_of_stream();
};

query::result to_data_query_result(const reconcilable_result&, schema_ptr, const query::partition_slice&, uint64_t row_limit, uint32_t partition_limit, query::result_options opts = query::result_options::only_result());

// Performs a query on given data source returning data in reconcilable form.
//
// Reads at most row_limit rows. If less rows are returned, the data source
// didn't have more live data satisfying the query.
//
// Any cells which have expired according to query_time are returned as
// deleted cells and do not count towards live data. The mutations are
// compact, meaning that any cell which is covered by higher-level tombstone
// is absent in the results.
//
// 'source' doesn't have to survive deferring.
future<reconcilable_result> mutation_query(
    schema_ptr,
    mutation_source source,
    const dht::partition_range& range,
    const query::partition_slice& slice,
    uint64_t row_limit,
    uint32_t partition_limit,
    gc_clock::time_point query_time,
    db::timeout_clock::time_point timeout,
    query::query_class_config class_config,
    query::result_memory_accounter&& accounter,
    tracing::trace_state_ptr trace_ptr = nullptr,
    query::querier_cache_context cache_ctx = { });

future<> data_query(
    schema_ptr s,
    const mutation_source& source,
    const dht::partition_range& range,
    const query::partition_slice& slice,
    uint64_t row_limit,
    uint32_t partition_limit,
    gc_clock::time_point query_time,
    query::result::builder& builder,
    db::timeout_clock::time_point timeout,
    query::query_class_config class_config,
    tracing::trace_state_ptr trace_ptr = nullptr,
    query::querier_cache_context cache_ctx = { });

class mutation_query_stage {
    inheriting_concrete_execution_stage<future<reconcilable_result>,
        schema_ptr,
        mutation_source,
        const dht::partition_range&,
        const query::partition_slice&,
        uint32_t,
        uint32_t,
        gc_clock::time_point,
        db::timeout_clock::time_point,
        query::query_class_config,
        query::result_memory_accounter&&,
        tracing::trace_state_ptr,
        query::querier_cache_context> _execution_stage;
public:
    explicit mutation_query_stage();
    template <typename... Args>
    future<reconcilable_result> operator()(Args&&... args) { return _execution_stage(std::forward<Args>(args)...); }
    inheriting_execution_stage::stats get_stats() const { return _execution_stage.get_stats(); }
};

// Performs a query for counter updates.
future<mutation_opt> counter_write_query(schema_ptr, const mutation_source&, reader_permit permit,
                                         const dht::decorated_key& dk,
                                         const query::partition_slice& slice,
                                         tracing::trace_state_ptr trace_ptr,
                                         db::timeout_clock::time_point timeout);

<|endoftext|>


<commit_before>#include "TileLogic.hpp"

#include <limits>
#include <string>
#include <array>

using namespace jakway_antf;

/**
 * returns whether this tile will be alive in the next generation
 * note that this function ONLY calculates whether THIS tile will live--does not give any information about neighboring tiles
 * this is OK because by looping through every tile you will get the correct generation
 * implement Conway's 4 rules of the game of life
 */
bool TileLogic::WillBeAlive(const bool alive, const POS_TYPE numLiveNeighbors)
{
    /** 1. Any live cell with fewer than two live neighbours dies, as if caused by under-population. */
    if(numLiveNeighbors < 2)
        return false;

    /** 2. Any live cell with two or three live neighbours lives on to the next generation. */
    if((alive && numLiveNeighbors == 2) || (alive && numLiveNeighbors == 3))
        return true;

    /** 3. Any live cell with more than three live neighbours dies, as if by overcrowding. */
    if(numLiveNeighbors > 3)
        return false;

    /** 4. Any dead cell with exactly three live neighbours becomes a live cell, as if by reproduction. */
    if(!alive && numLiveNeighbors == 3)
        return true;

    throw TileException("Invalid game board state -- should never reach here.");
}

std::array<std::array<POS_TYPE,2>, NUM_NEIGHBORS> TileLogic::GetNeighbors(const POS_TYPE x, const POS_TYPE y)
{
    //check for overflow errors and construct the appropriate error message
    bool overflowX = false, overflowY = false;
    std::string exceptionStr = "Error in TileLogic::GetNeighbors:";
    if(x == std::numeric_limits<POS_TYPE>::max())
        overflowX = true;
    if(y == std::numeric_limits<POS_TYPE>::max())
        overflowY = true;

    const std::string maxValStr = std::to_string(std::numeric_limits<POS_TYPE>::max());
    if(overflowX)
    {
        exceptionStr += (" x == " + maxValStr);
    }
    if(overflowY)
    {
        if(overflowX)
            exceptionStr += ";";
        exceptionStr += (" y == " + maxValStr);
    }
    if(overflowX || overflowY)
        throw std::overflow_error(exceptionStr);

    //return neighbor positions
    std::array<std::array<POS_TYPE,2>, NUM_NEIGHBORS> neighbors
    { //need an extra set of braces for each std::array, see http://stackoverflow.com/questions/12844475/why-cant-simple-initialize-with-braces-2d-stdarray
        { {{x - 1, y - 1}},
          {{x - 1, y}},
          {{x - 1, y + 1}},
          {{x, y - 1}},
          //the tile is not it's neighbor, skip (x,y)
          {{x, y + 1}},
          {{x + 1, y - 1}},
          {{x + 1, y}},
          {{x + 1, y + 1}} }
    };
    return neighbors;
}
<commit_msg>fixed semantic error in the rules-- any LIVE cell with more than 3 live neighbors dies<commit_after>#include "TileLogic.hpp"

#include <limits>
#include <string>
#include <array>

using namespace jakway_antf;

/**
 * returns whether this tile will be alive in the next generation
 * note that this function ONLY calculates whether THIS tile will live--does not give any information about neighboring tiles
 * this is OK because by looping through every tile you will get the correct generation
 * implement Conway's 4 rules of the game of life
 */
bool TileLogic::WillBeAlive(const bool alive, const POS_TYPE numLiveNeighbors)
{
    /** 1. Any live cell with fewer than two live neighbours dies, as if caused by under-population. */
    if(numLiveNeighbors < 2)
        return false;

    /** 2. Any live cell with two or three live neighbours lives on to the next generation. */
    if((alive && numLiveNeighbors == 2) || (alive && numLiveNeighbors == 3))
        return true;

    /** 3. Any live cell with more than three live neighbours dies, as if by overcrowding. */
    if(alive && (numLiveNeighbors > 3))
        return false;

    /** 4. Any dead cell with exactly three live neighbours becomes a live cell, as if by reproduction. */
    if(!alive && numLiveNeighbors == 3)
        return true;

    throw TileException("Invalid game board state -- should never reach here.");
}

std::array<std::array<POS_TYPE,2>, NUM_NEIGHBORS> TileLogic::GetNeighbors(const POS_TYPE x, const POS_TYPE y)
{
    //check for overflow errors and construct the appropriate error message
    bool overflowX = false, overflowY = false;
    std::string exceptionStr = "Error in TileLogic::GetNeighbors:";
    if(x == std::numeric_limits<POS_TYPE>::max())
        overflowX = true;
    if(y == std::numeric_limits<POS_TYPE>::max())
        overflowY = true;

    const std::string maxValStr = std::to_string(std::numeric_limits<POS_TYPE>::max());
    if(overflowX)
    {
        exceptionStr += (" x == " + maxValStr);
    }
    if(overflowY)
    {
        if(overflowX)
            exceptionStr += ";";
        exceptionStr += (" y == " + maxValStr);
    }
    if(overflowX || overflowY)
        throw std::overflow_error(exceptionStr);

    //return neighbor positions
    std::array<std::array<POS_TYPE,2>, NUM_NEIGHBORS> neighbors
    { //need an extra set of braces for each std::array, see http://stackoverflow.com/questions/12844475/why-cant-simple-initialize-with-braces-2d-stdarray
        { {{x - 1, y - 1}},
          {{x - 1, y}},
          {{x - 1, y + 1}},
          {{x, y - 1}},
          //the tile is not it's neighbor, skip (x,y)
          {{x, y + 1}},
          {{x + 1, y - 1}},
          {{x + 1, y}},
          {{x + 1, y + 1}} }
    };
    return neighbors;
}
<|endoftext|>


<commit_before>#define BOOST_TEST_MODULE test_fmath
#define BOOST_TEST_DYN_LINK

#include "test.hpp"
#include "fmath.hpp"

BOOST_AUTO_TEST_CASE(gcf00) {
    BOOST_TEST(gcf(0, 0) == 0);
}

BOOST_AUTO_TEST_CASE(gcf10) {
    BOOST_TEST(gcf(1, 0) == 1);
}

BOOST_AUTO_TEST_CASE(gcf01) {
    BOOST_TEST(gcf(0, 1) == 1);
}

BOOST_AUTO_TEST_CASE(gcf11) {
    BOOST_TEST(gcf(1, 1) == 1);
}

BOOST_AUTO_TEST_CASE(gcf02) {
    BOOST_TEST(gcf(0, 2) == 2);
    BOOST_TEST(gcf(2, 0) == 2);
    BOOST_TEST(gcf(2, 2) == 2);
}

BOOST_AUTO_TEST_CASE(gcf42) {
    BOOST_TEST(gcf(2, 4) == 2);
    BOOST_TEST(gcf(4, 2) == 2);
}

BOOST_AUTO_TEST_CASE(gcf2n) {
    for (int i = 2; i != 1024; i *= 2) {
        BOOST_TEST(gcf(i, 1) == 1);
        BOOST_TEST(gcf(i, 2) == 2);
        BOOST_TEST(gcf(i, 1024) == i);

        BOOST_TEST(gcf(1, i) == 1);
        BOOST_TEST(gcf(2, i) == 2);
        BOOST_TEST(gcf(1024, i) == i);
    }
}

BOOST_AUTO_TEST_CASE(gcf_primes) {
    for (int t = 2; t != 10'000; ++t) {
        if (t % 13 == 0) {
            BOOST_TEST(gcf(t, 13) == 13);
        } else {
            BOOST_TEST(gcf(t, 13) == 1);
        }

        if (t % 97 == 0) {
            BOOST_TEST(gcf(t, 97) == 97);
        } else {
            BOOST_TEST(gcf(t, 97) == 1);
        }
    }
}

BOOST_AUTO_TEST_CASE(xgcf00) {
    const auto result = xgcf(0, 0);

    BOOST_TEST(result[0] == 0);
    BOOST_TEST(result[1] == 1);
    BOOST_TEST(result[2] == 0);
}

BOOST_DATA_TEST_CASE(xgcf_random, bdata::make(100), i) {
    std::mt19937 engine(i);
    std::uniform_int_distribution<> uniform(-1'000'000, 1'000'000);

    const auto x = uniform(engine);
    const auto y = uniform(engine);

    const auto result = xgcf(x, y);

    BOOST_TEST(result[0] == result[1] * x + result[2] * y);
}
<commit_msg>Drop ': confused editor theme<commit_after>#define BOOST_TEST_MODULE test_fmath
#define BOOST_TEST_DYN_LINK

#include "test.hpp"
#include "fmath.hpp"

BOOST_AUTO_TEST_CASE(gcf00) {
    BOOST_TEST(gcf(0, 0) == 0);
}

BOOST_AUTO_TEST_CASE(gcf10) {
    BOOST_TEST(gcf(1, 0) == 1);
}

BOOST_AUTO_TEST_CASE(gcf01) {
    BOOST_TEST(gcf(0, 1) == 1);
}

BOOST_AUTO_TEST_CASE(gcf11) {
    BOOST_TEST(gcf(1, 1) == 1);
}

BOOST_AUTO_TEST_CASE(gcf02) {
    BOOST_TEST(gcf(0, 2) == 2);
    BOOST_TEST(gcf(2, 0) == 2);
    BOOST_TEST(gcf(2, 2) == 2);
}

BOOST_AUTO_TEST_CASE(gcf42) {
    BOOST_TEST(gcf(2, 4) == 2);
    BOOST_TEST(gcf(4, 2) == 2);
}

BOOST_AUTO_TEST_CASE(gcf2n) {
    for (int i = 2; i != 1024; i *= 2) {
        BOOST_TEST(gcf(i, 1) == 1);
        BOOST_TEST(gcf(i, 2) == 2);
        BOOST_TEST(gcf(i, 1024) == i);

        BOOST_TEST(gcf(1, i) == 1);
        BOOST_TEST(gcf(2, i) == 2);
        BOOST_TEST(gcf(1024, i) == i);
    }
}

BOOST_AUTO_TEST_CASE(gcf_primes) {
    for (int t = 2; t != 10000; ++t) {
        if (t % 13 == 0) {
            BOOST_TEST(gcf(t, 13) == 13);
        } else {
            BOOST_TEST(gcf(t, 13) == 1);
        }

        if (t % 97 == 0) {
            BOOST_TEST(gcf(t, 97) == 97);
        } else {
            BOOST_TEST(gcf(t, 97) == 1);
        }
    }
}

BOOST_AUTO_TEST_CASE(xgcf00) {
    const auto result = xgcf(0, 0);

    BOOST_TEST(result[0] == 0);
    BOOST_TEST(result[1] == 1);
    BOOST_TEST(result[2] == 0);
}

BOOST_DATA_TEST_CASE(xgcf_random, bdata::make(100), i) {
    std::mt19937 engine(i);
    std::uniform_int_distribution<> uniform(-1'000'000, 1'000'000);

    const auto x = uniform(engine);
    const auto y = uniform(engine);

    const auto result = xgcf(x, y);

    BOOST_TEST(result[0] == result[1] * x + result[2] * y);
}
<|endoftext|>


<commit_before>// Copyright 2013 Mirus Project

// 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.

//
// kernel.cpp - main source file + kernel entry point
//              we all have to begin somewhere, right?
//

#include <stdafx.hpp>
#include <boot/multiboot.hpp>
#include <boot/ramdisk.hpp>
#include <cpu/gdt.hpp>
#include <cpu/idt.hpp>
#include <cpu/isr.hpp>
#include <cpu/irq.hpp>
#include <system/process/task.hpp>
#include <system/syscall.hpp>
#include <hardware/serial.hpp>

namespace mirus
{
    extern "C" void test_func();

    // Memory size
    uint32_t memory_size = 0;
    uint32_t memory_size_m = 0;
    uint32_t min_mem = 512;

    // Memory map
    memory_map_t* mmap = nullptr;

    // Modules
    uint32_t mod_count = 0;
    module_t* mods = nullptr;

    //
    // kernel_main - our kernel entry point
    //
    extern "C" void kernel_main(multiboot_info_t* mbd, unsigned int magic)
    {
        // Print debug stub
        ktrace(trace_level::msg, "Mirus 0.3.7-dev\n\n");

        // Set up screen early on for boot information output
        screen::terminal::install();

        // Print kernel information
        kprintf("Mirus [%d.%d.%d-dev]\n\n", BUILD_MAJOR, BUILD_MINOR,
            BUILD_REV);

        // Get avalible memory
        if (magic != MULTIBOOT_BOOTLOADER_MAGIC)
            ktrace(trace_level::error,
                "Multiboot bootloader magic doesn't match!\n");

        // Retrieve number of multiboot modules
        mod_count = mbd->mods_count;

        // Verify if multiboot flags are ok to go
        if (mbd->flags & 1)
        {
            // Read header and assign
            ktrace(trace_level::msg, "Reading multiboot header\n");
            mmap = (memory_map_t*)mbd->mmap_addr;

            // Parse entries
            while ((unsigned int)mmap < (unsigned int)(mbd->mmap_addr)
                + mbd->mmap_length)
            {
                memory_size += mmap->length_low;
                mmap = (memory_map_t*)((unsigned int)mmap + mmap->size
                    + sizeof(unsigned int));
            }

            // Get memory size in megabytes
            memory_size_m = ((memory_size / 1024) / 1024);
            ktrace(trace_level::msg, "Avalible memory: %dm\n", memory_size_m);
        }

        // Check for any modules, the only of which should be the ramdisk
        ktrace(trace_level::msg, "Trying to get ramdisk...\n");

        if (mod_count > 0)
        {
            ktrace(trace_level::msg, "Modules found: %d\n", mod_count);

            uint32_t i = 0;
            for (i = 0, mods = (module_t*)mbd->mods_addr;
                i < mod_count;
                i++, mods++)
            {
                ktrace(trace_level::none, "==========\n");
                ktrace(trace_level::msg, "Module found: [%d:%d]\n",
                    mods->mod_start,
                    mods->mod_end);

                // load the ramdisk
                boot::parse_tar(mods->mod_start);
                kprintf("Loaded ramdisk\n");

                ktrace(trace_level::none, "==========\n");
            }
        }
        else
        {
            ktrace(trace_level::msg, "No modules found.\n");
            kprintf("[ERROR]\n");
        }

        // Check for minimum memory size
        if (memory_size_m < min_mem)
            ktrace(trace_level::warn, "Memory is less than expected minimum\n");

        // Setup CPU
        cpu::gdt::install();
        cpu::idt::install();
        cpu::isr::install();
        cpu::irq::install();

        // Enable interrupts
        asm volatile("sti");

        // Setup hardware
        hardware::serial::install();

        // Set up system calls
        system::init_syscalls();
        ktrace(trace_level::msg, "Installed system calls\n");
        kprintf("Installed system calls\n");

        // Enter usermode
        system::enter_userspace();
        ktrace(trace_level::notice, "Entered usermode...\n");

        // System call test function
        test_func();

        // YOU SHALL NOT PASS!!!!
        while (true);
    }
} // !namespace<commit_msg>Aligned variables<commit_after>// Copyright 2013 Mirus Project

// 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.

//
// kernel.cpp - main source file + kernel entry point
//              we all have to begin somewhere, right?
//

#include <stdafx.hpp>
#include <boot/multiboot.hpp>
#include <boot/ramdisk.hpp>
#include <cpu/gdt.hpp>
#include <cpu/idt.hpp>
#include <cpu/isr.hpp>
#include <cpu/irq.hpp>
#include <system/process/task.hpp>
#include <system/syscall.hpp>
#include <hardware/serial.hpp>

namespace mirus
{
    extern "C" void test_func();

    // Memory size
    uint32_t memory_size   = 0;
    uint32_t memory_size_m = 0;
    uint32_t min_mem       = 512;

    // Memory map
    memory_map_t* mmap     = nullptr;

    // Modules
    uint32_t mod_count     = 0;
    module_t* mods         = nullptr;

    //
    // kernel_main - our kernel entry point
    //
    extern "C" void kernel_main(multiboot_info_t* mbd, unsigned int magic)
    {
        // Print debug stub
        ktrace(trace_level::msg, "Mirus 0.3.7-dev\n\n");

        // Set up screen early on for boot information output
        screen::terminal::install();

        // Print kernel information
        kprintf("Mirus [%d.%d.%d-dev]\n\n", BUILD_MAJOR, BUILD_MINOR,
            BUILD_REV);

        // Get avalible memory
        if (magic != MULTIBOOT_BOOTLOADER_MAGIC)
            ktrace(trace_level::error,
                "Multiboot bootloader magic doesn't match!\n");

        // Retrieve number of multiboot modules
        mod_count = mbd->mods_count;

        // Verify if multiboot flags are ok to go
        if (mbd->flags & 1)
        {
            // Read header and assign
            ktrace(trace_level::msg, "Reading multiboot header\n");
            mmap = (memory_map_t*)mbd->mmap_addr;

            // Parse entries
            while ((unsigned int)mmap < (unsigned int)(mbd->mmap_addr)
                + mbd->mmap_length)
            {
                memory_size += mmap->length_low;
                mmap = (memory_map_t*)((unsigned int)mmap + mmap->size
                    + sizeof(unsigned int));
            }

            // Get memory size in megabytes
            memory_size_m = ((memory_size / 1024) / 1024);
            ktrace(trace_level::msg, "Avalible memory: %dm\n", memory_size_m);
        }

        // Check for any modules, the only of which should be the ramdisk
        ktrace(trace_level::msg, "Trying to get ramdisk...\n");

        if (mod_count > 0)
        {
            ktrace(trace_level::msg, "Modules found: %d\n", mod_count);

            uint32_t i = 0;
            for (i = 0, mods = (module_t*)mbd->mods_addr;
                i < mod_count;
                i++, mods++)
            {
                ktrace(trace_level::none, "==========\n");
                ktrace(trace_level::msg, "Module found: [%d:%d]\n",
                    mods->mod_start,
                    mods->mod_end);

                // load the ramdisk
                boot::parse_tar(mods->mod_start);
                kprintf("Loaded ramdisk\n");

                ktrace(trace_level::none, "==========\n");
            }
        }
        else
        {
            ktrace(trace_level::msg, "No modules found.\n");
            kprintf("[ERROR]\n");
        }

        // Check for minimum memory size
        if (memory_size_m < min_mem)
            ktrace(trace_level::warn, "Memory is less than expected minimum\n");

        // Setup CPU
        cpu::gdt::install();
        cpu::idt::install();
        cpu::isr::install();
        cpu::irq::install();

        // Enable interrupts
        asm volatile("sti");

        // Setup hardware
        hardware::serial::install();

        // Set up system calls
        system::init_syscalls();
        ktrace(trace_level::msg, "Installed system calls\n");
        kprintf("Installed system calls\n");

        // Enter usermode
        system::enter_userspace();
        ktrace(trace_level::notice, "Entered usermode...\n");

        // System call test function
        test_func();

        // YOU SHALL NOT PASS!!!!
        while (true);
    }
} // !namespace<|endoftext|>


<commit_before>/*
 * Copyright (c) 2014 ARM Limited
 * All rights reserved
 *
 * The license below extends only to copyright in the software and shall
 * not be construed as granting a license to any other intellectual
 * property including but not limited to intellectual property relating
 * to a hardware implementation of the functionality of the software
 * licensed hereunder.  You may use the software subject to the license
 * terms below provided that you ensure that this notice is replicated
 * unmodified and in its entirety in all distributions of the software,
 * modified or unmodified, in source code or in binary form.
 *
 * 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 the copyright holders 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.
 *
 * Authors: Andrew Bardsley
 */

/**
 * @file
 *
 *  C++-only configuration and instantiation support.  This allows a
 *  config to be read back from a .ini and instantiated without
 *  Python.  Useful if you want to embed gem5 within a larger system
 *  without carrying the integration cost of the fully-featured
 *  configuration system.
 *
 *  This file contains a demonstration main using CxxConfigManager.
 *  Build with something like:
 *
 *      scons --without-python build/ARM/libgem5_opt.so
 *
 *      g++ -DTRACING_ON -std=c++0x -Ibuild/ARM src/sim/cxx_main.cc \
 *          -o gem5cxx.opt -Lbuild/ARM -lgem5_opt
 */

#include <cstdlib>
#include <iostream>
#include <sstream>

#include "base/inifile.hh"
#include "base/statistics.hh"
#include "base/str.hh"
#include "base/trace.hh"
#include "cpu/base.hh"
#include "sim/cxx_config_ini.hh"
#include "sim/cxx_manager.hh"
#include "sim/init_signals.hh"
#include "sim/serialize.hh"
#include "sim/simulate.hh"
#include "sim/stat_control.hh"
#include "sim/system.hh"
#include "stats.hh"

void
usage(const std::string &prog_name)
{
    std::cerr << "Usage: " << prog_name << (
        " <config-file.ini> [ <option> ]\n\n"
        "OPTIONS:\n"
        "    -p <object> <param> <value>  -- set a parameter\n"
        "    -v <object> <param> <values> -- set a vector parameter from"
        " a comma\n"
        "                                    separated values string\n"
        "    -d <flag>                    -- set a debug flag (-<flag>\n"
        "                                    clear a flag)\n"
        "    -s <dir> <ticks>             -- save checkpoint to dir after"
        " the given\n"
        "                                    number of ticks\n"
        "    -r <dir>                     -- restore checkpoint to dir\n"
        "    -c <from> <to> <ticks>       -- switch from cpu 'from' to cpu"
        " 'to' after\n"
        "                                    the given number of ticks\n"
        "\n"
        );

    std::exit(EXIT_FAILURE);
}

int
main(int argc, char **argv)
{
    std::string prog_name(argv[0]);
    unsigned int arg_ptr = 1;

    if (argc == 1)
        usage(prog_name);

    cxxConfigInit();

    initSignals();

    setClockFrequency(1000000000000);
    curEventQueue(getEventQueue(0));

    Stats::initSimStats();
    Stats::registerHandlers(CxxConfig::statsReset, CxxConfig::statsDump);

    Trace::enabled = true;
    setDebugFlag("Terminal");
    // setDebugFlag("CxxConfig");

    const std::string config_file(argv[arg_ptr]);

    CxxConfigFileBase *conf = new CxxIniFile();

    if (!conf->load(config_file.c_str())) {
        std::cerr << "Can't open config file: " << config_file << '\n';
        return EXIT_FAILURE;
    }
    arg_ptr++;

    CxxConfigManager *config_manager = new CxxConfigManager(*conf);

    bool checkpoint_restore = false;
    bool checkpoint_save = false;
    bool switch_cpus = false;
    std::string checkpoint_dir = "";
    std::string from_cpu = "";
    std::string to_cpu = "";
    Tick pre_run_time = 1000000;
    Tick pre_switch_time = 1000000;

    try {
        while (arg_ptr < argc) {
            std::string option(argv[arg_ptr]);
            arg_ptr++;
            unsigned num_args = argc - arg_ptr;

            if (option == "-p") {
                if (num_args < 3)
                    usage(prog_name);
                config_manager->setParam(argv[arg_ptr], argv[arg_ptr + 1],
                    argv[arg_ptr + 2]);
                arg_ptr += 3;
            } else if (option == "-v") {
                std::vector<std::string> values;

                if (num_args < 3)
                    usage(prog_name);
                tokenize(values, argv[arg_ptr + 2], ',');
                config_manager->setParamVector(argv[arg_ptr],
                    argv[arg_ptr + 1], values);
                arg_ptr += 3;
            } else if (option == "-d") {
                if (num_args < 1)
                    usage(prog_name);
                if (argv[arg_ptr][0] == '-')
                    clearDebugFlag(argv[arg_ptr] + 1);
                else
                    setDebugFlag(argv[arg_ptr]);
                arg_ptr++;
            } else if (option == "-r") {
                if (num_args < 1)
                    usage(prog_name);
                checkpoint_dir = argv[arg_ptr];
                checkpoint_restore = true;
                arg_ptr++;
            } else if (option == "-s") {
                if (num_args < 2)
                    usage(prog_name);
                checkpoint_dir = argv[arg_ptr];
                std::istringstream(argv[arg_ptr + 1]) >> pre_run_time;
                checkpoint_save = true;
                arg_ptr += 2;
            } else if (option == "-c") {
                if (num_args < 3)
                    usage(prog_name);
                switch_cpus = true;
                from_cpu = argv[arg_ptr];
                to_cpu = argv[arg_ptr + 1];
                std::istringstream(argv[arg_ptr + 2]) >> pre_switch_time;
                arg_ptr += 3;
            } else {
                usage(prog_name);
            }
        }
    } catch (CxxConfigManager::Exception &e) {
        std::cerr << e.name << ": " << e.message << "\n";
        return EXIT_FAILURE;
    }

    if (checkpoint_save && checkpoint_restore) {
        std::cerr << "Don't try and save and restore a checkpoint in the"
            " same run\n";
        return EXIT_FAILURE;
    }

    CxxConfig::statsEnable();
    getEventQueue(0)->dump();

    try {
        config_manager->instantiate();
        if (!checkpoint_restore) {
            config_manager->initState();
            config_manager->startup();
        }
    } catch (CxxConfigManager::Exception &e) {
        std::cerr << "Config problem in sim object " << e.name
            << ": " << e.message << "\n";

        return EXIT_FAILURE;
    }

    GlobalSimLoopExitEvent *exit_event = NULL;

    if (checkpoint_save) {

        exit_event = simulate(pre_run_time);

        DrainManager drain_manager;
        unsigned int drain_count = 1;
        do {
            drain_count = config_manager->drain(&drain_manager);

            std::cerr << "Draining " << drain_count << '\n';

            if (drain_count > 0) {
                drain_manager.setCount(drain_count);
                exit_event = simulate();
            }
        } while (drain_count > 0);

        std::cerr << "Simulation stop at tick " << curTick()
            << ", cause: " << exit_event->getCause() << '\n';

        std::cerr << "Checkpointing\n";

        /* FIXME, this should really be serialising just for
         *  config_manager rather than using serializeAll's ugly
         *  SimObject static object list */
        Serializable::serializeAll(checkpoint_dir);

        std::cerr << "Completed checkpoint\n";

        config_manager->drainResume();
    }

    if (checkpoint_restore) {
        std::cerr << "Restoring checkpoint\n";

        Checkpoint *checkpoint = new Checkpoint(checkpoint_dir,
            config_manager->getSimObjectResolver());

        Serializable::unserializeGlobals(checkpoint);
        config_manager->loadState(checkpoint);

        config_manager->drainResume();

        std::cerr << "Restored from checkpoint\n";
    }

    if (switch_cpus) {
        exit_event = simulate(pre_switch_time);

        std::cerr << "Switching CPU\n";

        /* Assume the system is called system */
        System &system = config_manager->getObject<System>("system");
        BaseCPU &old_cpu = config_manager->getObject<BaseCPU>(from_cpu);
        BaseCPU &new_cpu = config_manager->getObject<BaseCPU>(to_cpu);

        DrainManager drain_manager;
        unsigned int drain_count = 1;
        do {
            drain_count = config_manager->drain(&drain_manager);

            std::cerr << "Draining " << drain_count << '\n';

            if (drain_count > 0) {
                drain_manager.setCount(drain_count);
                exit_event = simulate();
            }
        } while (drain_count > 0);

        old_cpu.switchOut();
        system.setMemoryMode(Enums::timing);
        new_cpu.takeOverFrom(&old_cpu);
        config_manager->drainResume();

        std::cerr << "Switched CPU\n";
    }

    exit_event = simulate();

    std::cerr << "Exit at tick " << curTick()
        << ", cause: " << exit_event->getCause() << '\n';

    getEventQueue(0)->dump();

#if TRY_CLEAN_DELETE
    config_manager->deleteObjects();
#endif

    delete config_manager;

    return EXIT_SUCCESS;
}
<commit_msg>config: Fix checkpoint restore in C++ config example<commit_after>/*
 * Copyright (c) 2014 ARM Limited
 * All rights reserved
 *
 * The license below extends only to copyright in the software and shall
 * not be construed as granting a license to any other intellectual
 * property including but not limited to intellectual property relating
 * to a hardware implementation of the functionality of the software
 * licensed hereunder.  You may use the software subject to the license
 * terms below provided that you ensure that this notice is replicated
 * unmodified and in its entirety in all distributions of the software,
 * modified or unmodified, in source code or in binary form.
 *
 * 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 the copyright holders 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.
 *
 * Authors: Andrew Bardsley
 */

/**
 * @file
 *
 *  C++-only configuration and instantiation support.  This allows a
 *  config to be read back from a .ini and instantiated without
 *  Python.  Useful if you want to embed gem5 within a larger system
 *  without carrying the integration cost of the fully-featured
 *  configuration system.
 *
 *  This file contains a demonstration main using CxxConfigManager.
 *  Build with something like:
 *
 *      scons --without-python build/ARM/libgem5_opt.so
 *
 *      g++ -DTRACING_ON -std=c++0x -Ibuild/ARM src/sim/cxx_main.cc \
 *          -o gem5cxx.opt -Lbuild/ARM -lgem5_opt
 */

#include <cstdlib>
#include <iostream>
#include <sstream>

#include "base/inifile.hh"
#include "base/statistics.hh"
#include "base/str.hh"
#include "base/trace.hh"
#include "cpu/base.hh"
#include "sim/cxx_config_ini.hh"
#include "sim/cxx_manager.hh"
#include "sim/init_signals.hh"
#include "sim/serialize.hh"
#include "sim/simulate.hh"
#include "sim/stat_control.hh"
#include "sim/system.hh"
#include "stats.hh"

void
usage(const std::string &prog_name)
{
    std::cerr << "Usage: " << prog_name << (
        " <config-file.ini> [ <option> ]\n\n"
        "OPTIONS:\n"
        "    -p <object> <param> <value>  -- set a parameter\n"
        "    -v <object> <param> <values> -- set a vector parameter from"
        " a comma\n"
        "                                    separated values string\n"
        "    -d <flag>                    -- set a debug flag (-<flag>\n"
        "                                    clear a flag)\n"
        "    -s <dir> <ticks>             -- save checkpoint to dir after"
        " the given\n"
        "                                    number of ticks\n"
        "    -r <dir>                     -- restore checkpoint from dir\n"
        "    -c <from> <to> <ticks>       -- switch from cpu 'from' to cpu"
        " 'to' after\n"
        "                                    the given number of ticks\n"
        "\n"
        );

    std::exit(EXIT_FAILURE);
}

int
main(int argc, char **argv)
{
    std::string prog_name(argv[0]);
    unsigned int arg_ptr = 1;

    if (argc == 1)
        usage(prog_name);

    cxxConfigInit();

    initSignals();

    setClockFrequency(1000000000000);
    curEventQueue(getEventQueue(0));

    Stats::initSimStats();
    Stats::registerHandlers(CxxConfig::statsReset, CxxConfig::statsDump);

    Trace::enabled = true;
    setDebugFlag("Terminal");
    // setDebugFlag("CxxConfig");

    const std::string config_file(argv[arg_ptr]);

    CxxConfigFileBase *conf = new CxxIniFile();

    if (!conf->load(config_file.c_str())) {
        std::cerr << "Can't open config file: " << config_file << '\n';
        return EXIT_FAILURE;
    }
    arg_ptr++;

    CxxConfigManager *config_manager = new CxxConfigManager(*conf);

    bool checkpoint_restore = false;
    bool checkpoint_save = false;
    bool switch_cpus = false;
    std::string checkpoint_dir = "";
    std::string from_cpu = "";
    std::string to_cpu = "";
    Tick pre_run_time = 1000000;
    Tick pre_switch_time = 1000000;

    try {
        while (arg_ptr < argc) {
            std::string option(argv[arg_ptr]);
            arg_ptr++;
            unsigned num_args = argc - arg_ptr;

            if (option == "-p") {
                if (num_args < 3)
                    usage(prog_name);
                config_manager->setParam(argv[arg_ptr], argv[arg_ptr + 1],
                    argv[arg_ptr + 2]);
                arg_ptr += 3;
            } else if (option == "-v") {
                std::vector<std::string> values;

                if (num_args < 3)
                    usage(prog_name);
                tokenize(values, argv[arg_ptr + 2], ',');
                config_manager->setParamVector(argv[arg_ptr],
                    argv[arg_ptr + 1], values);
                arg_ptr += 3;
            } else if (option == "-d") {
                if (num_args < 1)
                    usage(prog_name);
                if (argv[arg_ptr][0] == '-')
                    clearDebugFlag(argv[arg_ptr] + 1);
                else
                    setDebugFlag(argv[arg_ptr]);
                arg_ptr++;
            } else if (option == "-r") {
                if (num_args < 1)
                    usage(prog_name);
                checkpoint_dir = argv[arg_ptr];
                checkpoint_restore = true;
                arg_ptr++;
            } else if (option == "-s") {
                if (num_args < 2)
                    usage(prog_name);
                checkpoint_dir = argv[arg_ptr];
                std::istringstream(argv[arg_ptr + 1]) >> pre_run_time;
                checkpoint_save = true;
                arg_ptr += 2;
            } else if (option == "-c") {
                if (num_args < 3)
                    usage(prog_name);
                switch_cpus = true;
                from_cpu = argv[arg_ptr];
                to_cpu = argv[arg_ptr + 1];
                std::istringstream(argv[arg_ptr + 2]) >> pre_switch_time;
                arg_ptr += 3;
            } else {
                usage(prog_name);
            }
        }
    } catch (CxxConfigManager::Exception &e) {
        std::cerr << e.name << ": " << e.message << "\n";
        return EXIT_FAILURE;
    }

    if (checkpoint_save && checkpoint_restore) {
        std::cerr << "Don't try and save and restore a checkpoint in the"
            " same run\n";
        return EXIT_FAILURE;
    }

    CxxConfig::statsEnable();
    getEventQueue(0)->dump();

    try {
        config_manager->instantiate();
        if (!checkpoint_restore) {
            config_manager->initState();
            config_manager->startup();
        }
    } catch (CxxConfigManager::Exception &e) {
        std::cerr << "Config problem in sim object " << e.name
            << ": " << e.message << "\n";

        return EXIT_FAILURE;
    }

    GlobalSimLoopExitEvent *exit_event = NULL;

    if (checkpoint_save) {
        exit_event = simulate(pre_run_time);

        DrainManager drain_manager;
        unsigned int drain_count = 1;
        do {
            drain_count = config_manager->drain(&drain_manager);

            std::cerr << "Draining " << drain_count << '\n';

            if (drain_count > 0) {
                drain_manager.setCount(drain_count);
                exit_event = simulate();
            }
        } while (drain_count > 0);

        std::cerr << "Simulation stop at tick " << curTick()
            << ", cause: " << exit_event->getCause() << '\n';

        std::cerr << "Checkpointing\n";

        /* FIXME, this should really be serialising just for
         *  config_manager rather than using serializeAll's ugly
         *  SimObject static object list */
        Serializable::serializeAll(checkpoint_dir);

        std::cerr << "Completed checkpoint\n";

        config_manager->drainResume();
    }

    if (checkpoint_restore) {
        std::cerr << "Restoring checkpoint\n";

        Checkpoint *checkpoint = new Checkpoint(checkpoint_dir,
            config_manager->getSimObjectResolver());

        Serializable::unserializeGlobals(checkpoint);
        config_manager->loadState(checkpoint);
        config_manager->startup();

        config_manager->drainResume();

        std::cerr << "Restored from checkpoint\n";
    }

    if (switch_cpus) {
        exit_event = simulate(pre_switch_time);

        std::cerr << "Switching CPU\n";

        /* Assume the system is called system */
        System &system = config_manager->getObject<System>("system");
        BaseCPU &old_cpu = config_manager->getObject<BaseCPU>(from_cpu);
        BaseCPU &new_cpu = config_manager->getObject<BaseCPU>(to_cpu);

        DrainManager drain_manager;
        unsigned int drain_count = 1;
        do {
            drain_count = config_manager->drain(&drain_manager);

            std::cerr << "Draining " << drain_count << '\n';

            if (drain_count > 0) {
                drain_manager.setCount(drain_count);
                exit_event = simulate();
            }
        } while (drain_count > 0);

        old_cpu.switchOut();
        system.setMemoryMode(Enums::timing);
        new_cpu.takeOverFrom(&old_cpu);
        config_manager->drainResume();

        std::cerr << "Switched CPU\n";
    }

    exit_event = simulate();

    std::cerr << "Exit at tick " << curTick()
        << ", cause: " << exit_event->getCause() << '\n';

    getEventQueue(0)->dump();

#if TRY_CLEAN_DELETE
    config_manager->deleteObjects();
#endif

    delete config_manager;

    return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>#include "core/memory/temp_allocator.h"
#include "core/strings/string_stream.h"

namespace crown
{
static void console_send(TCPSocket& client, const char* json)
{
	const u32 size = strlen32(json);
	client.write(&size, sizeof(u32));
	client.write(json, size);
}

static void console_sanitize_json_string(StringStream& json, const char* str)
{
	const char* ch = str;
	for (; *ch; ch++)
	{
		if (*ch == '"' || *ch == '\\')
			json << "\\";
		json << *ch;
	}
}

static void console_send_script(TCPSocket& client, const char* lua)
{
	TempAllocator1024 ta;
	StringStream json(ta);

	json << "{\"type\":\"script\",\"script\":\"";
	console_sanitize_json_string(json, lua);
	json << "\"}";

	console_send(client, string_stream::c_str(json));
}

static void console_send_command(TCPSocket& client, char* cmd)
{
	TempAllocator1024 ta;
	StringStream json(ta);

	char* saveptr;
	const char* delim = " ";
	const char* token = strtok_r(cmd, delim, &saveptr);

	json << "{\"type\":\"command\",\"args\":[";
	while (token != NULL)
	{
		json << "\"";
		console_sanitize_json_string(json, token);
		json << "\",";
		token = strtok_r(NULL, delim, &saveptr);
	}
	json << "]}";

	console_send(client, string_stream::c_str(json));
}

Console::Console()
	: _num_items(0)
	, _history(default_allocator())
	, _commands(default_allocator())
	, _open(true)
	, _has_focus(false)
	, _history_pos(-1)
	, _scroll_to_bottom(true)
{
	_client.connect(IP_ADDRESS_LOOPBACK, CROWN_DEFAULT_CONSOLE_PORT);

	for (u32 i = 0; i < countof(_items); ++i)
		_items[i].severity = LogSeverity::COUNT;

	// FIXME: clear tmp commands
	TempAllocator128 a;
	DynamicString str(a);
	str = "help - Show this";
	vector::push_back(_commands, str);
	str = "clear - Clear console";
	vector::push_back(_commands, str);
	str = "history - Show recent commands";
	vector::push_back(_commands, str);

	memset(_input_text, 0, sizeof(_input_text));
}

Console::~Console()
{
	_client.close();
}

void Console::add_log(LogSeverity::Enum severity, const char* message)
{
	_items[_num_items].severity = severity;
	strncpy(_items[_num_items].message, message, sizeof(_items[_num_items].message)-1);
	_items[_num_items].message[sizeof(_items[_num_items].message)-1] = '\0';
	_num_items = (_num_items + 1) % countof(_items);
}

int console_inputtext_callback(ImGuiInputTextCallbackData* data)
{
	if (data->EventFlag == ImGuiInputTextFlags_CallbackHistory)
	{
		Console* console = (Console*) data->UserData;
		const Vector<DynamicString>& history = console->_history;
		s32& history_pos = console->_history_pos;
		const s32 prev_history_pos = history_pos;

		if (ImGuiKey_UpArrow == data->EventKey)
		{
			if (history_pos == -1)
				history_pos = vector::size(history) - 1;
			else if (history_pos > 0)
				history_pos--;
		}
		else if (ImGuiKey_DownArrow == data->EventKey)
		{
			if (history_pos != -1)
			{
				if (++history_pos >= (int)vector::size(history))
					history_pos = -1;
			}
		}

		if (prev_history_pos != history_pos)
		{
			s32 len = snprintf(data->Buf, (size_t) data->BufSize, "%s", (history_pos >= 0) ? history[history_pos].c_str() : "");
			data->CursorPos = data->SelectionStart = data->SelectionEnd = data->BufTextLen = len;
			data->BufDirty = true;
		}
	}

	return 0;
}

void console_draw(Console& console)
{
	if (!console._open)
		return;

	ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0,0));
	static ImGuiTextFilter filter;
	filter.Draw("Filter (\"incl,-excl\") (\"error\")", 180);
	ImGui::PopStyleVar();
	ImGui::Separator();

	const float footer_height_to_reserve = ImGui::GetStyle().ItemSpacing.y + ImGui::GetFrameHeightWithSpacing(); // 1 separator, 1 input text
	ImGui::BeginChild("ScrollingRegion"
		, ImVec2(0.0f, -footer_height_to_reserve)
		, false
		, ImGuiWindowFlags_HorizontalScrollbar
		);

	ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(4,1)); // Tighten spacing
	for (u32 i = console._num_items, n = 0; n < countof(console._items); i = (i + 1) % countof(console._items), ++n)
	{
		ConsoleLog& item = console._items[i];
		if (item.severity == LogSeverity::COUNT)
			continue;

		if (!filter.PassFilter(item.message))
			continue;

		ImVec4 col = ImVec4(1.0f,1.0f,1.0f,1.0f);

		switch (item.severity)
		{
			case LogSeverity::LOG_INFO: col = ImColor(0.7f, 0.7f, 0.7f, 1.0f); break;
			case LogSeverity::LOG_WARN: col = ImColor(1.0f, 1.0f, 0.4f, 1.0f); break;
			case LogSeverity::LOG_ERROR: col = ImColor(1.0f, 0.4f, 0.4f, 1.0f); break;
			default: CE_FATAL("Unknown Severity"); break;
		}
		ImGui::PushStyleColor(ImGuiCol_Text, col);
		ImGui::PushFont(ImGui::Font::Mono);
		ImGui::TextUnformatted(item.message);
		ImGui::PopFont();
		ImGui::PopStyleColor();
	}

	if (console._scroll_to_bottom)
		ImGui::SetScrollHereY();

	console._scroll_to_bottom = false;
	ImGui::PopStyleVar();
	ImGui::EndChild();
	ImGui::Separator();

	ImGui::PushItemWidth(-1);
	ImGui::PushFont(ImGui::Font::Mono);
	if (ImGui::InputText("##label"
		, console._input_text
		, IM_ARRAYSIZE(console._input_text)
		, ImGuiInputTextFlags_EnterReturnsTrue | ImGuiInputTextFlags_CallbackHistory
		, console_inputtext_callback
		, &console
		))
	{
		char* input_end = console._input_text + strlen(console._input_text);
		while (input_end > console._input_text && input_end[-1] == ' ')
		{
			input_end--;
		}

		*input_end = 0;

		if (console._input_text[0])
		{
			console.add_log(LogSeverity::LOG_INFO, console._input_text);
			console_execute_command(console, console._input_text);
		}

		strcpy(console._input_text, "");
		console._history_pos = -1;

		ImGui::SetKeyboardFocusHere(-1);
		console._scroll_to_bottom = true;
	}
	ImGui::PopFont();
	ImGui::PopItemWidth();
}

void console_execute_command(Console& console, const char* command)
{
	TCPSocket& client = console._client;
	Vector<DynamicString>& history = console._history;
	Vector<DynamicString>& commands = console._commands;

	{
		TempAllocator512 ta;
		DynamicString str(ta);
		str = command;
		vector::push_back(history, str);
	}

	// Process command
	if (strcmp(command, "clear") == 0)
	{
		console._num_items = 0;
	}
	else if (strcmp(command, "history") == 0)
	{
		int first = vector::size(history)-10;
		for (u32 i = first > 0 ? first : 0; i < vector::size(history); i++)
		{
			char buf[64];
			sprintf(buf, "%3d: %s\n", i, history[i].c_str());
			console.add_log(LogSeverity::LOG_INFO, buf);
		}
	}
	else if (strcmp(command, "help") == 0)
	{
		console.add_log(LogSeverity::LOG_INFO, "commands: ");
		for (u32 i = 0; i < vector::size(commands); i++)
			console.add_log(LogSeverity::LOG_INFO, commands[i].c_str());
	}
	else if (command[0] == ':')
	{
		console_send_command(client, (char*)&command[1]);
	}
	else
	{
		console_send_script(client, command);
	}

	console._scroll_to_bottom = true;
}

void console_scroll_to_bottom(Console& console)
{
	console._scroll_to_bottom = true;
}

} // namespace crown
<commit_msg>tools-imgui: fix build<commit_after>#include "core/memory/temp_allocator.h"
#include "core/strings/string_stream.h"
#include <string.h> // strtok_r

namespace crown
{
static void console_send(TCPSocket& client, const char* json)
{
	const u32 size = strlen32(json);
	client.write(&size, sizeof(u32));
	client.write(json, size);
}

static void console_sanitize_json_string(StringStream& json, const char* str)
{
	const char* ch = str;
	for (; *ch; ch++)
	{
		if (*ch == '"' || *ch == '\\')
			json << "\\";
		json << *ch;
	}
}

static void console_send_script(TCPSocket& client, const char* lua)
{
	TempAllocator1024 ta;
	StringStream json(ta);

	json << "{\"type\":\"script\",\"script\":\"";
	console_sanitize_json_string(json, lua);
	json << "\"}";

	console_send(client, string_stream::c_str(json));
}

static void console_send_command(TCPSocket& client, char* cmd)
{
	TempAllocator1024 ta;
	StringStream json(ta);

	char* saveptr;
	const char* delim = " ";
	const char* token = strtok_r(cmd, delim, &saveptr);

	json << "{\"type\":\"command\",\"args\":[";
	while (token != NULL)
	{
		json << "\"";
		console_sanitize_json_string(json, token);
		json << "\",";
		token = strtok_r(NULL, delim, &saveptr);
	}
	json << "]}";

	console_send(client, string_stream::c_str(json));
}

Console::Console()
	: _num_items(0)
	, _history(default_allocator())
	, _commands(default_allocator())
	, _open(true)
	, _has_focus(false)
	, _history_pos(-1)
	, _scroll_to_bottom(true)
{
	_client.connect(IP_ADDRESS_LOOPBACK, CROWN_DEFAULT_CONSOLE_PORT);

	for (u32 i = 0; i < countof(_items); ++i)
		_items[i].severity = LogSeverity::COUNT;

	// FIXME: clear tmp commands
	TempAllocator128 a;
	DynamicString str(a);
	str = "help - Show this";
	vector::push_back(_commands, str);
	str = "clear - Clear console";
	vector::push_back(_commands, str);
	str = "history - Show recent commands";
	vector::push_back(_commands, str);

	memset(_input_text, 0, sizeof(_input_text));
}

Console::~Console()
{
	_client.close();
}

void Console::add_log(LogSeverity::Enum severity, const char* message)
{
	_items[_num_items].severity = severity;
	strncpy(_items[_num_items].message, message, sizeof(_items[_num_items].message)-1);
	_items[_num_items].message[sizeof(_items[_num_items].message)-1] = '\0';
	_num_items = (_num_items + 1) % countof(_items);
}

int console_inputtext_callback(ImGuiInputTextCallbackData* data)
{
	if (data->EventFlag == ImGuiInputTextFlags_CallbackHistory)
	{
		Console* console = (Console*) data->UserData;
		const Vector<DynamicString>& history = console->_history;
		s32& history_pos = console->_history_pos;
		const s32 prev_history_pos = history_pos;

		if (ImGuiKey_UpArrow == data->EventKey)
		{
			if (history_pos == -1)
				history_pos = vector::size(history) - 1;
			else if (history_pos > 0)
				history_pos--;
		}
		else if (ImGuiKey_DownArrow == data->EventKey)
		{
			if (history_pos != -1)
			{
				if (++history_pos >= (int)vector::size(history))
					history_pos = -1;
			}
		}

		if (prev_history_pos != history_pos)
		{
			s32 len = snprintf(data->Buf, (size_t) data->BufSize, "%s", (history_pos >= 0) ? history[history_pos].c_str() : "");
			data->CursorPos = data->SelectionStart = data->SelectionEnd = data->BufTextLen = len;
			data->BufDirty = true;
		}
	}

	return 0;
}

void console_draw(Console& console)
{
	if (!console._open)
		return;

	ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0,0));
	static ImGuiTextFilter filter;
	filter.Draw("Filter (\"incl,-excl\") (\"error\")", 180);
	ImGui::PopStyleVar();
	ImGui::Separator();

	const float footer_height_to_reserve = ImGui::GetStyle().ItemSpacing.y + ImGui::GetFrameHeightWithSpacing(); // 1 separator, 1 input text
	ImGui::BeginChild("ScrollingRegion"
		, ImVec2(0.0f, -footer_height_to_reserve)
		, false
		, ImGuiWindowFlags_HorizontalScrollbar
		);

	ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(4,1)); // Tighten spacing
	for (u32 i = console._num_items, n = 0; n < countof(console._items); i = (i + 1) % countof(console._items), ++n)
	{
		ConsoleLog& item = console._items[i];
		if (item.severity == LogSeverity::COUNT)
			continue;

		if (!filter.PassFilter(item.message))
			continue;

		ImVec4 col = ImVec4(1.0f,1.0f,1.0f,1.0f);

		switch (item.severity)
		{
			case LogSeverity::LOG_INFO: col = ImColor(0.7f, 0.7f, 0.7f, 1.0f); break;
			case LogSeverity::LOG_WARN: col = ImColor(1.0f, 1.0f, 0.4f, 1.0f); break;
			case LogSeverity::LOG_ERROR: col = ImColor(1.0f, 0.4f, 0.4f, 1.0f); break;
			default: CE_FATAL("Unknown Severity"); break;
		}
		ImGui::PushStyleColor(ImGuiCol_Text, col);
		ImGui::PushFont(ImGui::Font::Mono);
		ImGui::TextUnformatted(item.message);
		ImGui::PopFont();
		ImGui::PopStyleColor();
	}

	if (console._scroll_to_bottom)
		ImGui::SetScrollHereY();

	console._scroll_to_bottom = false;
	ImGui::PopStyleVar();
	ImGui::EndChild();
	ImGui::Separator();

	ImGui::PushItemWidth(-1);
	ImGui::PushFont(ImGui::Font::Mono);
	if (ImGui::InputText("##label"
		, console._input_text
		, IM_ARRAYSIZE(console._input_text)
		, ImGuiInputTextFlags_EnterReturnsTrue | ImGuiInputTextFlags_CallbackHistory
		, console_inputtext_callback
		, &console
		))
	{
		char* input_end = console._input_text + strlen(console._input_text);
		while (input_end > console._input_text && input_end[-1] == ' ')
		{
			input_end--;
		}

		*input_end = 0;

		if (console._input_text[0])
		{
			console.add_log(LogSeverity::LOG_INFO, console._input_text);
			console_execute_command(console, console._input_text);
		}

		strcpy(console._input_text, "");
		console._history_pos = -1;

		ImGui::SetKeyboardFocusHere(-1);
		console._scroll_to_bottom = true;
	}
	ImGui::PopFont();
	ImGui::PopItemWidth();
}

void console_execute_command(Console& console, const char* command)
{
	TCPSocket& client = console._client;
	Vector<DynamicString>& history = console._history;
	Vector<DynamicString>& commands = console._commands;

	{
		TempAllocator512 ta;
		DynamicString str(ta);
		str = command;
		vector::push_back(history, str);
	}

	// Process command
	if (strcmp(command, "clear") == 0)
	{
		console._num_items = 0;
	}
	else if (strcmp(command, "history") == 0)
	{
		int first = vector::size(history)-10;
		for (u32 i = first > 0 ? first : 0; i < vector::size(history); i++)
		{
			char buf[64];
			sprintf(buf, "%3d: %s\n", i, history[i].c_str());
			console.add_log(LogSeverity::LOG_INFO, buf);
		}
	}
	else if (strcmp(command, "help") == 0)
	{
		console.add_log(LogSeverity::LOG_INFO, "commands: ");
		for (u32 i = 0; i < vector::size(commands); i++)
			console.add_log(LogSeverity::LOG_INFO, commands[i].c_str());
	}
	else if (command[0] == ':')
	{
		console_send_command(client, (char*)&command[1]);
	}
	else
	{
		console_send_script(client, command);
	}

	console._scroll_to_bottom = true;
}

void console_scroll_to_bottom(Console& console)
{
	console._scroll_to_bottom = true;
}

} // namespace crown
<|endoftext|>


<commit_before>/*
 * fMBT, free Model Based Testing tool
 * Copyright (c) 2011, Intel Corporation.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms and conditions of the GNU Lesser General Public License,
 * version 2.1, as published by the Free Software Foundation.
 *
 * This program is distributed in the hope 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 program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
 *
 *
 */

#include "aalang_cpp.hh"
#include "helper.hh"

aalang_cpp::aalang_cpp(): aalang(),action_cnt(1), tag_cnt(1), name_cnt(0),
			  istate(NULL), name(NULL), tag(false)
{
  default_guard="return true;";
  default_body="";
  default_adapter="";
  std::vector<std::string> t;
  aname.push_back(t);
  tname.push_back(t);
  amap.push_back(0);
  tmap.push_back(0);
}

aalang_cpp::~aalang_cpp()
{
  delete istate;
  delete name;
}

void aalang_cpp::set_starter(std::string* st)
{
  s+=*st;
  delete st;
}

void aalang_cpp::set_name(std::string* name)
{
  s+="\n//action"+to_string(action_cnt)+": \""+*name+"\"\n";
  aname.back().push_back(*name);
  delete name;
  amap.push_back(action_cnt);
  name_cnt++;
}

void aalang_cpp::set_namestr(std::string* _name)
{
  name=_name;
  s+="#include \"aal.hh\"\n\n";
  s+="class _gen_"+*name+":public aal {\nprivate:\n\t";
}

void aalang_cpp::set_variables(std::string* var)
{
  s+="//variables\n"+*var+"\n";
  delete var;
}

void aalang_cpp::set_istate(std::string* ist)
{
  istate=ist;
}

void aalang_cpp::set_push(std::string* p)
{
  push=*p;
  delete p;
}

void aalang_cpp::set_pop(std::string* p)
{
  pop=*p;
  delete p;
}

void aalang_cpp::set_tagname(std::string* name)
{
  s+="\n//tag"+to_string(tag_cnt)+": \""+*name+"\"\n";
  tname.back().push_back(*name);
  delete name;
  tmap.push_back(tag_cnt);
  name_cnt++;
  tag=true;
}

void aalang_cpp::next_tag()
{
  std::vector<std::string> t;
  tname.push_back(t);
  tag_cnt+=name_cnt;
  name_cnt=0;
  tag=false;
}

void aalang_cpp::set_guard(std::string* gua)
{
  if (tag) {
    s+="bool tag"+to_string(tag_cnt)+"_guard() {\n"+
      *gua+"}\n";
  } else {
    s+="bool action"+to_string(action_cnt)+"_guard() {\n"+
      *gua+"}\n";
  }
  if (gua!=&default_guard)
    delete gua;
}

void aalang_cpp::set_body(std::string* bod)
{
  s+="void action"+to_string(action_cnt)+"_body() {\n"+*bod+"}\n";
  if (bod!=&default_body)
    delete bod;
}

void aalang_cpp::set_adapter(std::string* ada)
{
  s+="int action" + to_string(action_cnt) + "_adapter() {\n" +
      *ada + "\n"
      "\treturn " + to_string(action_cnt) + ";\n"
      "}\n";
  if (ada!=&default_adapter)
      delete ada;
}

void aalang_cpp::next_action()
{
  std::vector<std::string> t;
  aname.push_back(t);
  action_cnt+=name_cnt;
  name_cnt=0;
}

std::string aalang_cpp::stringify()
{

  s=s+
    "\npublic:\n"
    "\t_gen_"+*name+"(Log& l): aal(l) {\n\taction_names.push_back(\"\");\n";

  for(std::list<std::vector<std::string> >::iterator i=aname.begin();i!=aname.end();i++) {
    for(std::vector<std::string>::iterator j=i->begin();j!=i->end();j++) {
      s+="\taction_names.push_back(\""+*j+"\");\n";
    }
  }
  s=s+"\ttag_names.push_back(\"\");\n";

  for(std::list<std::vector<std::string> >::iterator i=tname.begin();i!=tname.end();i++) {
    for(std::vector<std::string>::iterator j=i->begin();j!=i->end();j++) {
      s+="\ttag_names.push_back(\""+*j+"\");\n";
    }
  }

  s+=*istate+"}\n"
    "virtual bool reset() {\n"+
    *istate +
    "return true;\n}\n\n"
    "virtual int adapter_execute(int action) {\n"
    "\tswitch(action) {\n";

  if (pop!="") {
    s=s+"\nvirtual void pop(){\n"+pop+"\n}\n";
    s=s+"\nvirtual void push(){\n"+push+"\n}\n";
  }

  for(int i=1;i<action_cnt;i++) {
    s+="\t\tcase "+to_string(i)+":\n"
      "\t\treturn action"+to_string(amap[i])+
      "_adapter();\n\t\tbreak;\n";
  }
  s=s+"\t\tdefault:\n"
    "\t\treturn 0;\n"
    "\t};\n"
    "}\n"
    "virtual int model_execute(int action) {\n"
    "\tswitch(action) {\n";

  for(int i=1;i<action_cnt;i++) {
    s+="\t\tcase "+to_string(i)+":\n"
      "\t\taction"+to_string(amap[i])+"_body();\n\t\treturn "+
      to_string(i)+";\n\t\tbreak;\n";
  }
  s=s+"\t\tdefault:\n"
    "\t\treturn 0;\n"
    "\t};\n"
    "}\n"
    "virtual int getActions(int** act) {\n"
    "actions.clear();\n";

  for(int i=1;i<action_cnt;i++) {
    s+="\tif (action"+to_string(amap[i])+"_guard()) {\n"
      "\t\tactions.push_back("+to_string(i)+");\n"
      "\t}\n";
  }
  s=s+"\t*act = &actions[0];\n"
    "\treturn actions.size();\n"
    "}\n";

  s=s+"virtual int getprops(int** props) {\n"
    "tags.clear();\n";

  for(int i=1;i<tag_cnt;i++) {
    s+="\tif (tag"+to_string(tmap[i])+"_guard()) {\n"
      "\t\ttags.push_back("+to_string(i)+");\n"
      "\t}\n";
  }
  s=s+"\t*props = &tags[0];\n"
    "\treturn tags.size();\n"
    "}\n"
    "};\n";

  factory_register();

  return s;
}

void aalang_cpp::factory_register()
{
  s=s+"  /* factory register */\n\n"
    "namespace {\n"
    "static aal* a=NULL;\n\n"
    "Model* model_creator(Log&l, std::string params) {\n"
    "\tif (!a) {\n"
    "\t  a=new _gen_"+*name+"(l);\n"
    "\t}\n"
    "\treturn new Mwrapper(l,params,a);\n"
    "}\n\n"
    "static ModelFactory::Register me1(\""+*name+"\", model_creator);\n\n"
    "Adapter* adapter_creator(Log&l, std::string params = \"\")\n"
    "{\n"
    "\tif (!a) {\n"
    "\t  a=new _gen_"+*name+"(l);\n"
    "\t}\n"
    "\treturn new Awrapper(l,params,a);\n"
    "}\n"
    "static AdapterFactory::Register me2(\""+*name+"\", adapter_creator);\n"+
    "}\n";
}
<commit_msg>Fix pop/push<commit_after>/*
 * fMBT, free Model Based Testing tool
 * Copyright (c) 2011, Intel Corporation.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms and conditions of the GNU Lesser General Public License,
 * version 2.1, as published by the Free Software Foundation.
 *
 * This program is distributed in the hope 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 program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
 *
 *
 */

#include "aalang_cpp.hh"
#include "helper.hh"

aalang_cpp::aalang_cpp(): aalang(),action_cnt(1), tag_cnt(1), name_cnt(0),
			  istate(NULL), name(NULL), tag(false)
{
  default_guard="return true;";
  default_body="";
  default_adapter="";
  std::vector<std::string> t;
  aname.push_back(t);
  tname.push_back(t);
  amap.push_back(0);
  tmap.push_back(0);
}

aalang_cpp::~aalang_cpp()
{
  delete istate;
  delete name;
}

void aalang_cpp::set_starter(std::string* st)
{
  s+=*st;
  delete st;
}

void aalang_cpp::set_name(std::string* name)
{
  s+="\n//action"+to_string(action_cnt)+": \""+*name+"\"\n";
  aname.back().push_back(*name);
  delete name;
  amap.push_back(action_cnt);
  name_cnt++;
}

void aalang_cpp::set_namestr(std::string* _name)
{
  name=_name;
  s+="#include \"aal.hh\"\n\n";
  s+="class _gen_"+*name+":public aal {\nprivate:\n\t";
}

void aalang_cpp::set_variables(std::string* var)
{
  s+="//variables\n"+*var+"\n";
  delete var;
}

void aalang_cpp::set_istate(std::string* ist)
{
  istate=ist;
}

void aalang_cpp::set_push(std::string* p)
{
  push=*p;
  delete p;
}

void aalang_cpp::set_pop(std::string* p)
{
  pop=*p;
  delete p;
}

void aalang_cpp::set_tagname(std::string* name)
{
  s+="\n//tag"+to_string(tag_cnt)+": \""+*name+"\"\n";
  tname.back().push_back(*name);
  delete name;
  tmap.push_back(tag_cnt);
  name_cnt++;
  tag=true;
}

void aalang_cpp::next_tag()
{
  std::vector<std::string> t;
  tname.push_back(t);
  tag_cnt+=name_cnt;
  name_cnt=0;
  tag=false;
}

void aalang_cpp::set_guard(std::string* gua)
{
  if (tag) {
    s+="bool tag"+to_string(tag_cnt)+"_guard() {\n"+
      *gua+"}\n";
  } else {
    s+="bool action"+to_string(action_cnt)+"_guard() {\n"+
      *gua+"}\n";
  }
  if (gua!=&default_guard)
    delete gua;
}

void aalang_cpp::set_body(std::string* bod)
{
  s+="void action"+to_string(action_cnt)+"_body() {\n"+*bod+"}\n";
  if (bod!=&default_body)
    delete bod;
}

void aalang_cpp::set_adapter(std::string* ada)
{
  s+="int action" + to_string(action_cnt) + "_adapter() {\n" +
      *ada + "\n"
      "\treturn " + to_string(action_cnt) + ";\n"
      "}\n";
  if (ada!=&default_adapter)
      delete ada;
}

void aalang_cpp::next_action()
{
  std::vector<std::string> t;
  aname.push_back(t);
  action_cnt+=name_cnt;
  name_cnt=0;
}

std::string aalang_cpp::stringify()
{

  s=s+
    "\npublic:\n"
    "\t_gen_"+*name+"(Log& l): aal(l) {\n\taction_names.push_back(\"\");\n";

  for(std::list<std::vector<std::string> >::iterator i=aname.begin();i!=aname.end();i++) {
    for(std::vector<std::string>::iterator j=i->begin();j!=i->end();j++) {
      s+="\taction_names.push_back(\""+*j+"\");\n";
    }
  }
  s=s+"\ttag_names.push_back(\"\");\n";

  for(std::list<std::vector<std::string> >::iterator i=tname.begin();i!=tname.end();i++) {
    for(std::vector<std::string>::iterator j=i->begin();j!=i->end();j++) {
      s+="\ttag_names.push_back(\""+*j+"\");\n";
    }
  }

  s+=*istate+"}\n"
    "virtual bool reset() {\n"+
    *istate +
    "return true;\n}\n\n";

  if (pop!="") {
    s=s+"\nvirtual void pop(){\n"+pop+"\n}\n";
    s=s+"\nvirtual void push(){\n"+push+"\n}\n";
  }

  s=s+"virtual int adapter_execute(int action) {\n"
    "\tswitch(action) {\n";

  for(int i=1;i<action_cnt;i++) {
    s+="\t\tcase "+to_string(i)+":\n"
      "\t\treturn action"+to_string(amap[i])+
      "_adapter();\n\t\tbreak;\n";
  }
  s=s+"\t\tdefault:\n"
    "\t\treturn 0;\n"
    "\t};\n"
    "}\n"
    "virtual int model_execute(int action) {\n"
    "\tswitch(action) {\n";

  for(int i=1;i<action_cnt;i++) {
    s+="\t\tcase "+to_string(i)+":\n"
      "\t\taction"+to_string(amap[i])+"_body();\n\t\treturn "+
      to_string(i)+";\n\t\tbreak;\n";
  }
  s=s+"\t\tdefault:\n"
    "\t\treturn 0;\n"
    "\t};\n"
    "}\n"
    "virtual int getActions(int** act) {\n"
    "actions.clear();\n";

  for(int i=1;i<action_cnt;i++) {
    s+="\tif (action"+to_string(amap[i])+"_guard()) {\n"
      "\t\tactions.push_back("+to_string(i)+");\n"
      "\t}\n";
  }
  s=s+"\t*act = &actions[0];\n"
    "\treturn actions.size();\n"
    "}\n";

  s=s+"virtual int getprops(int** props) {\n"
    "tags.clear();\n";

  for(int i=1;i<tag_cnt;i++) {
    s+="\tif (tag"+to_string(tmap[i])+"_guard()) {\n"
      "\t\ttags.push_back("+to_string(i)+");\n"
      "\t}\n";
  }
  s=s+"\t*props = &tags[0];\n"
    "\treturn tags.size();\n"
    "}\n"
    "};\n";

  factory_register();

  return s;
}

void aalang_cpp::factory_register()
{
  s=s+"  /* factory register */\n\n"
    "namespace {\n"
    "static aal* a=NULL;\n\n"
    "Model* model_creator(Log&l, std::string params) {\n"
    "\tif (!a) {\n"
    "\t  a=new _gen_"+*name+"(l);\n"
    "\t}\n"
    "\treturn new Mwrapper(l,params,a);\n"
    "}\n\n"
    "static ModelFactory::Register me1(\""+*name+"\", model_creator);\n\n"
    "Adapter* adapter_creator(Log&l, std::string params = \"\")\n"
    "{\n"
    "\tif (!a) {\n"
    "\t  a=new _gen_"+*name+"(l);\n"
    "\t}\n"
    "\treturn new Awrapper(l,params,a);\n"
    "}\n"
    "static AdapterFactory::Register me2(\""+*name+"\", adapter_creator);\n"+
    "}\n";
}
<|endoftext|>


<commit_before>#include "Variant.h"
#include "split.h"
#include "cdflib.hpp"
#include "pdflib.hpp"
#include "var.hpp"

#include <string>
#include <iostream>
#include <math.h>
#include <cmath>
#include <stdlib.h>
#include <time.h>
#include <stdio.h>
#include <getopt.h>

using namespace std;
using namespace vcf;

void printVersion(void){
  cerr << "INFO: version 1.0.0 ; date: April 2014 ; author: Zev Kronenberg; email : zev.kronenberg@utah.edu " << endl;
}

void printHelp(void){
  cerr << endl << endl;
  cerr << "INFO: help" << endl;
  cerr << "INFO: description:" << endl;
  cerr << "     abba-baba calculates the tree pattern for four indviduals.                         " << endl;
  cerr << "     This tool assumes reference is ancestral and ignores non abba-baba sites.          " << endl;
  cerr << "     The output is a boolian value: 1 = true , 0 = false for abba and baba.             " << endl;
  cerr << "     the tree argument should be specified from the most basal taxa to the most derived." << endl;
  cerr <<  endl;
  cerr << "     Example:" << endl;

  cerr <<  "     D   C  B   A "  << endl;
  cerr <<  "     \\   \\/    /  "  << endl;
  cerr <<  "      \\  /    /   "  << endl;
  cerr <<  "       \\    /    "  << endl;
  cerr <<  "        \\  /     "  << endl;
  cerr <<  "         /        "  << endl;
  cerr <<  "        /         "  << endl;

  cerr << " --tree A,B,C,D"  << endl << endl;

  cerr << "Output : 4 columns :     "    << endl;
  cerr << "     1. seqid            "    << endl;
  cerr << "     2. position         "    << endl;
  cerr << "     3. abba             "    << endl;
  cerr << "     4. baba             "    << endl;

  cerr << "INFO: usage:  abba-baba-zabba --tree 0,1,2,3 --file my.vcf --type PL" << endl;
  cerr << endl;
  cerr << "INFO: required: t,tree       -- a zero based comma seperated list of target individuals corrisponding to VCF columns" << endl;
  cerr << "INFO: required: f,file       -- a properly formatted VCF.                                                           " << endl;
  cerr << "INFO: required: y,type       -- genotype likelihood format ; genotypes: GP,GL or PL;                                " << endl;
  cerr << endl;

  printVersion() ;
}

double bound(double v){
  if(v <= 0.00001){
    return  0.00001;
  }
  if(v >= 0.99999){
    return 0.99999;
  }
  return v;
}

int  containsAlt(string gt){
  if(gt == "1/1"){
    return 1;
  }
  if(gt == "0/1"){
    return 1;
  }
  if(gt == "1|1"){
    return 1;
  }
  if(gt == "0|1"){
    return 1;
  }
  if(gt == "1|0"){
    return 1;
  }
  return 0;
}

void loadIndices(vector<int> tree, string set){

  vector<string>  indviduals = split(set, ",");

  if(indviduals.size() < 4){
    cerr << "FATAL: the abba-baba requires four indviduals provided to the tree option" << endl;
    exit(1);
  }
  for( vector<string>::iterator it = indviduals.begin(); it != indviduals.end(); it++){
    tree.push_back(atoi((*it).c_str()));
  }
}

int main(int argc, char** argv) {

  // pooled or genotyped

  int pool = 0;

  // the filename

  string filename = "NA";

  // set region to scaffold

  string region = "NA";

  // using vcflib; thanks to Erik Garrison

  VariantCallFile variantFile;

  // zero based index for the tree

  vector<int> tree;

  // deltaaf is the difference of allele frequency we bother to look at

  string deltaaf ;
  double daf  = 0;

  //

  int counts = 0;

  // type pooled GL PL

  string type = "NA";

    const struct option longopts[] =
      {
	{"version"   , 0, 0, 'v'},
	{"help"      , 0, 0, 'h'},
	{"counts"    , 0, 0, 'c'},
        {"file"      , 1, 0, 'f'},
	{"tree"      , 1, 0, 't'},
	{"background", 1, 0, 'b'},
	{"region"    , 1, 0, 'r'},
	{"type"      , 1, 0, 'y'},
	{0,0,0,0}
      };

    int index;
    int iarg=0;

    while(iarg != -1)
      {
	iarg = getopt_long(argc, argv, "r:d:t:f:y:hv", longopts, &index);

	switch (iarg)
	  {
	  case 'h':
	    printHelp();
	    return 0;
	  case 'v':
	    printVersion();
	    return 0;
	  case 'y':
	    type = optarg;
	    cerr << "INFO: genotype likelihoods set to: " << type << endl;
	    break;
	  case 't':
	    loadIndices(tree, optarg);
	    break;
	  case 'f':
	    cerr << "INFO: File: " << optarg  <<  endl;
	    filename = optarg;
	    break;
	  case 'r':
            cerr << "INFO: set seqid region to : " << optarg << endl;
	    region = optarg;
	    break;
	  default:
	    break;
	  }
      }

    if(filename == "NA"){
      cerr << "FATAL: did not specify the file\n";
      printHelp();
      exit(1);
    }

    variantFile.open(filename);

    if(region != "NA"){
      variantFile.setRegion(region);
    }

    if (!variantFile.is_open()) {
      exit(1);
    }
    map<string, int> okayGenotypeLikelihoods;

    okayGenotypeLikelihoods["PL"] = 1;
    okayGenotypeLikelihoods["PO"] = 1;
    okayGenotypeLikelihoods["GL"] = 1;
    okayGenotypeLikelihoods["GP"] = 1;

    if(type == "NA"){
      cerr << "FATAL: failed to specify genotype likelihood format : PL or GL" << endl;
      printHelp();
      return 1;
    }
    if(okayGenotypeLikelihoods.find(type) == okayGenotypeLikelihoods.end()){
      cerr << "FATAL: genotype likelihood is incorrectly formatted, only use: PL or GL" << endl;
      printHelp();
      return 1;
    }

    Variant var(variantFile);

    vector<string> sampleNames = variantFile.sampleNames;

    while (variantFile.getNextVariant(var)) {

      if(var.alt.size() > 1){
	continue;
      }

      map<string, vector<string> >  tA, tB, tC, tD;

      tA = var.samples[sampleNames[1]];
      tB = var.samples[sampleNames[2]];
      tC = var.samples[sampleNames[3]];
      tD = var.samples[sampleNames[4]];

      if(tA["GT"].front() == "./." || tB["GT"].front() == "./." || tC["GT"].front() == "./." || tD["GT"].front() == "./."){
	continue;
      }

      int A,B,C,D = 0;

      double abba = 0;
      double baba = 0;

      A = containsAlt(tA["GT"].front());
      B = containsAlt(tB["GT"].front());
      C = containsAlt(tC["GT"].front());
      D = containsAlt(tD["GT"].front());

      while(1){
	if(D == 0 && C == 1 && B == 1 && A == 0){
	  abba = 1;
	  break;
	}
	if(D == 1 && C == 0 && B == 1 && A == 0){
	  baba = 1;
	}
	break;
      }

      if(abba == 0 && baba == 0){
	continue;
      }

      cout << var.sequenceName << "\t" << var.position << "\t" << abba << "\t" << baba << endl;

    }
    return 0;
}
<commit_msg>fixed not indexing<commit_after>#include "Variant.h"
#include "split.h"
#include "cdflib.hpp"
#include "pdflib.hpp"
#include "var.hpp"

#include <string>
#include <iostream>
#include <math.h>
#include <cmath>
#include <stdlib.h>
#include <time.h>
#include <stdio.h>
#include <getopt.h>

using namespace std;
using namespace vcf;

void printVersion(void){
  cerr << "INFO: version 1.0.0 ; date: April 2014 ; author: Zev Kronenberg; email : zev.kronenberg@utah.edu " << endl;
}

void printHelp(void){
  cerr << endl << endl;
  cerr << "INFO: help" << endl;
  cerr << "INFO: description:" << endl;
  cerr << "     abba-baba calculates the tree pattern for four indviduals.                         " << endl;
  cerr << "     This tool assumes reference is ancestral and ignores non abba-baba sites.          " << endl;
  cerr << "     The output is a boolian value: 1 = true , 0 = false for abba and baba.             " << endl;
  cerr << "     the tree argument should be specified from the most basal taxa to the most derived." << endl;
  cerr <<  endl;
  cerr << "     Example:" << endl;

  cerr <<  "     D   C  B   A "  << endl;
  cerr <<  "     \\ /  /    /  "  << endl;
  cerr <<  "      \\  /    /   "  << endl;
  cerr <<  "       \\    /    "  << endl;
  cerr <<  "        \\  /     "  << endl;
  cerr <<  "         /        "  << endl;
  cerr <<  "        /         "  << endl;

  cerr << " --tree A,B,C,D"  << endl << endl;

  cerr << "Output : 4 columns :     "    << endl;
  cerr << "     1. seqid            "    << endl;
  cerr << "     2. position         "    << endl;
  cerr << "     3. abba             "    << endl;
  cerr << "     4. baba             "    << endl;

  cerr << "INFO: usage:  abba-baba-zabba --tree 0,1,2,3 --file my.vcf --type PL" << endl;
  cerr << endl;
  cerr << "INFO: required: t,tree       -- a zero based comma seperated list of target individuals corrisponding to VCF columns" << endl;
  cerr << "INFO: required: f,file       -- a properly formatted VCF.                                                           " << endl;
  cerr << "INFO: required: y,type       -- genotype likelihood format ; genotypes: GP,GL or PL;                                " << endl;
  cerr << endl;

  printVersion() ;
}

double bound(double v){
  if(v <= 0.00001){
    return  0.00001;
  }
  if(v >= 0.99999){
    return 0.99999;
  }
  return v;
}

int  containsAlt(string gt){
  if(gt == "1/1"){
    return 1;
  }
  if(gt == "0/1"){
    return 1;
  }
  if(gt == "1|1"){
    return 1;
  }
  if(gt == "0|1"){
    return 1;
  }
  if(gt == "1|0"){
    return 1;
  }
  return 0;
}

void loadIndices(vector<int> & tree, string set){

  vector<string>  indviduals = split(set, ",");

  if(indviduals.size() < 4){
    cerr << "FATAL: the abba-baba requires four indviduals provided to the tree option" << endl;
    exit(1);
  }
  for( vector<string>::iterator it = indviduals.begin(); it != indviduals.end(); it++){

    int indx = atoi((*it).c_str());
    cerr << indx << endl;

    tree.push_back(atoi((*it).c_str()));
  }
}

int main(int argc, char** argv) {

  // pooled or genotyped

  int pool = 0;

  // the filename

  string filename = "NA";

  // set region to scaffold

  string region = "NA";

  // using vcflib; thanks to Erik Garrison

  VariantCallFile variantFile;

  // zero based index for the tree

  vector<int> tree;

  // deltaaf is the difference of allele frequency we bother to look at

  string deltaaf ;
  double daf  = 0;

  //

  int counts = 0;

  // type pooled GL PL

  string type = "NA";

    const struct option longopts[] =
      {
	{"version"   , 0, 0, 'v'},
	{"help"      , 0, 0, 'h'},
	{"counts"    , 0, 0, 'c'},
        {"file"      , 1, 0, 'f'},
	{"tree"      , 1, 0, 't'},
	{"background", 1, 0, 'b'},
	{"region"    , 1, 0, 'r'},
	{"type"      , 1, 0, 'y'},
	{0,0,0,0}
      };

    int index;
    int iarg=0;

    while(iarg != -1)
      {
	iarg = getopt_long(argc, argv, "r:d:t:f:y:hv", longopts, &index);

	switch (iarg)
	  {
	  case 'h':
	    printHelp();
	    return 0;
	  case 'v':
	    printVersion();
	    return 0;
	  case 'y':
	    type = optarg;
	    cerr << "INFO: genotype likelihoods set to: " << type << endl;
	    break;
	  case 't':
	    loadIndices(tree, optarg);
	    break;
	  case 'f':
	    cerr << "INFO: File: " << optarg  <<  endl;
	    filename = optarg;
	    break;
	  case 'r':
            cerr << "INFO: set seqid region to : " << optarg << endl;
	    region = optarg;
	    break;
	  default:
	    break;
	  }
      }

    if(filename == "NA"){
      cerr << "FATAL: did not specify the file\n";
      printHelp();
      exit(1);
    }

    variantFile.open(filename);

    if(region != "NA"){
      variantFile.setRegion(region);
    }

    if (!variantFile.is_open()) {
      exit(1);
    }
    map<string, int> okayGenotypeLikelihoods;

    okayGenotypeLikelihoods["PL"] = 1;
    okayGenotypeLikelihoods["PO"] = 1;
    okayGenotypeLikelihoods["GL"] = 1;
    okayGenotypeLikelihoods["GP"] = 1;

    if(type == "NA"){
      cerr << "FATAL: failed to specify genotype likelihood format : PL or GL" << endl;
      printHelp();
      return 1;
    }
    if(okayGenotypeLikelihoods.find(type) == okayGenotypeLikelihoods.end()){
      cerr << "FATAL: genotype likelihood is incorrectly formatted, only use: PL or GL" << endl;
      printHelp();
      return 1;
    }

    Variant var(variantFile);

    vector<string> sampleNames = variantFile.sampleNames;

    while (variantFile.getNextVariant(var)) {

      if(var.alt.size() > 1){
	continue;
      }

      map<string, vector<string> >  tA, tB, tC, tD;

      tA = var.samples[sampleNames[tree[1]]];
      tB = var.samples[sampleNames[tree[2]]];
      tC = var.samples[sampleNames[tree[3]]];
      tD = var.samples[sampleNames[tree[4]]];

      if(tA["GT"].front() == "./." || tB["GT"].front() == "./." || tC["GT"].front() == "./." || tD["GT"].front() == "./."){
	continue;
      }

      int A,B,C,D = 0;

      double abba = 0;
      double baba = 0;

      A = containsAlt(tA["GT"].front());
      B = containsAlt(tB["GT"].front());
      C = containsAlt(tC["GT"].front());
      D = containsAlt(tD["GT"].front());

      while(1){
	if(D == 0 && C == 1 && B == 1 && A == 0){
	  abba = 1;
	  break;
	}
	if(D == 1 && C == 0 && B == 1 && A == 0){
	  baba = 1;
	}
	break;
      }

      if(abba == 0 && baba == 0){
	continue;
      }

      cout << var.sequenceName << "\t" << var.position << "\t" << abba << "\t" << baba << endl;

    }
    return 0;
}
<|endoftext|>