text:
#include <util/StopWatch.hpp>
#include "controller.h"
#include "snapshot_patch_iterator_triple_id.h"
#include "patch_builder_streaming.h"
#include "../snapshot/combined_triple_iterator.h"
#include "../simpleprogresslistener.h"
#include <sys/stat.h>
#include <boost/filesystem.hpp>

Controller::Controller(string basePath, int8_t kc_opts, bool readonly) : patchTreeManager(new PatchTreeManager(basePath, kc_opts, readonly)), snapshotManager(new SnapshotManager(basePath, readonly)) {
    struct stat sb;
    if (!(stat(basePath.c_str(), &sb) == 0 && S_ISDIR(sb.st_mode))) {
        throw std::invalid_argument("The provided path '" + basePath + "' is not a valid directory.");
    }
}

Controller::~Controller() {
    delete patchTreeManager;
    delete snapshotManager;
}

size_t Controller::get_version_materialized_count_estimated(const Triple& triple_pattern, int patch_id) const {
    return get_version_materialized_count(triple_pattern, patch_id, true).first;
}

std::pair<size_t, ResultEstimationType> Controller::get_version_materialized_count(const Triple& triple_pattern, int patch_id, bool allowEstimates) const {
    int snapshot_id = get_corresponding_snapshot_id(patch_id);
    if(snapshot_id < 0) {
        return std::make_pair(0, EXACT);
    }

    HDT* snapshot = get_snapshot_manager()->get_snapshot(snapshot_id);
    IteratorTripleID* snapshot_it = SnapshotManager::search_with_offset(snapshot, triple_pattern, 0);
    size_t snapshot_count = snapshot_it->estimatedNumResults();
    if (!allowEstimates && snapshot_it->numResultEstimation() != EXACT) {
        snapshot_count = 0;
        while (snapshot_it->hasNext()) {
            snapshot_it->next();
            snapshot_count++;
        }
    }
    if(snapshot_id == patch_id) {
        return std::make_pair(snapshot_count, snapshot_it->numResultEstimation());
    }

    DictionaryManager *dict = get_snapshot_manager()->get_dictionary_manager(snapshot_id);
    int patch_tree_id = get_patch_tree_id(patch_id);
    PatchTree* patchTree = get_patch_tree_manager()->get_patch_tree(patch_tree_id, dict);
    if(patchTree == NULL) {
        return std::make_pair(snapshot_count, snapshot_it->numResultEstimation());
    }

    std::pair<PatchPosition, Triple> deletion_count_data = patchTree->deletion_count(triple_pattern, patch_id);
    size_t addition_count = patchTree->addition_count(patch_id, triple_pattern);
    return std::make_pair(snapshot_count - deletion_count_data.first + addition_count, snapshot_it->numResultEstimation());
}

TripleIterator* Controller::get_version_materialized(const Triple &triple_pattern, int offset, int patch_id) const {
    // Find the snapshot
    int snapshot_id = get_corresponding_snapshot_id(patch_id);
    if(snapshot_id < 0) {
        //throw std::invalid_argument("No snapshot was found for version " + std::to_string(patch_id));
        return new EmptyTripleIterator();
    }
    HDT* snapshot = get_snapshot_manager()->get_snapshot(snapshot_id);

    // Simple case: We are requesting a snapshot, delegate lookup to that snapshot.
    IteratorTripleID* snapshot_it = SnapshotManager::search_with_offset(snapshot, triple_pattern, offset);
    if(snapshot_id == patch_id) {
        return new SnapshotTripleIterator(snapshot_it);
    }
    DictionaryManager *dict = get_snapshot_manager()->get_dictionary_manager(snapshot_id);

    // Otherwise, we have to prepare an iterator for a certain patch
    int patch_tree_id = get_patch_tree_id(patch_id);
    PatchTree* patchTree = get_patch_tree_manager()->get_patch_tree(patch_tree_id, dict);
    if(patchTree == NULL) {
        return new SnapshotTripleIterator(snapshot_it);
    }
    PositionedTripleIterator* deletion_it = NULL;
    long added_offset = 0;
    bool check_offseted_deletions = true;

    // Limit the patch id to the latest available patch id
//    int max_patch_id = patchTree->get_max_patch_id();
//    if (patch_id > max_patch_id) {
//        patch_id = max_patch_id;
//    }

    std::pair<PatchPosition, Triple> deletion_count_data = patchTree->deletion_count(triple_pattern, patch_id);
    // This loop continuously determines new snapshot iterators until it finds one that contains
    // no new deletions with respect to the snapshot iterator from last iteration.
    // This loop is required to handle special cases like the one in the ControllerTest::EdgeCase1.
    // As worst-case, this loop will take O(n) (n:dataset size), as an optimization we can look
    // into storing long consecutive chains of deletions more efficiently.
    while(check_offseted_deletions) {
        if (snapshot_it->hasNext()) { // We have elements left in the snapshot we should apply deletions to
            // Determine the first triple in the original snapshot and use it as offset for the deletion iterator
            TripleID *tripleId = snapshot_it->next();
            Triple firstTriple(tripleId->getSubject(), tripleId->getPredicate(), tripleId->getObject());
            deletion_it = patchTree->deletion_iterator_from(firstTriple, patch_id, triple_pattern);
            deletion_it->getPatchTreeIterator()->set_early_break(true);

            // Calculate a new offset, taking into account deletions.
            PositionedTriple first_deletion_triple;
            long snapshot_offset = 0;
            if (deletion_it->next(&first_deletion_triple, true)) {
                snapshot_offset = first_deletion_triple.position;
            } else {
                // The exact snapshot triple could not be found as a deletion
                if (patchTree->get_spo_comparator()->compare(firstTriple, deletion_count_data.second) < 0) {
                    // If the snapshot triple is smaller than the largest deletion,
                    // set the offset to zero, as all deletions will come *after* this triple.

                    // Note that it should impossible that there would exist a deletion *before* this snapshot triple,
                    // otherwise we would already have found this triple as a snapshot triple before.
                    // If we would run into issues because of this after all, we could do a backwards step with
                    // deletion_it and see if we find a triple matching the pattern, and use its position.

                    snapshot_offset = 0;
                } else {
                    // If the snapshot triple is larger than the largest deletion,
                    // set the offset to the total number of deletions.
                    snapshot_offset = deletion_count_data.first;
                }
            }
            long previous_added_offset = added_offset;
            added_offset = snapshot_offset;

            // Make a new snapshot iterator for the new offset
            // TODO: look into reusing the snapshot iterator and applying a relative offset (NOTE: I tried it before, it's trickier than it seems...)
            delete snapshot_it;
            snapshot_it = SnapshotManager::search_with_offset(snapshot, triple_pattern, offset + added_offset);

            // Check if we need to loop again
            check_offseted_deletions = previous_added_offset < added_offset;
            if(check_offseted_deletions) {
                delete deletion_it;
                deletion_it = NULL;
            }
        } else {
            check_offseted_deletions = false;
        }
    }
    return new SnapshotPatchIteratorTripleID(snapshot_it, deletion_it, patchTree->get_spo_comparator(), snapshot, triple_pattern, patchTree, patch_id, offset, deletion_count_data.first);
}

std::pair<size_t, ResultEstimationType> Controller::get_delta_materialized_count(const Triple &triple_pattern, int patch_id_start, int patch_id_end, bool allowEstimates) const {
    int snapshot_id_start = get_corresponding_snapshot_id(patch_id_start);
    int snapshot_id_end = get_corresponding_snapshot_id(patch_id_end);
    int patch_tree_id_end = get_patch_tree_id(patch_id_end);
    int patch_tree_id_start = get_patch_tree_id(patch_id_start);
    // S_start <- P <- P_end
    if(snapshot_id_start == patch_id_start){
        DictionaryManager *dict = get_snapshot_manager()->get_dictionary_manager(snapshot_id_start);
        PatchTree* patchTree = get_patch_tree_manager()->get_patch_tree(patch_tree_id_end, dict);
        size_t count = patchTree->deletion_count(triple_pattern, patch_id_end).first + patchTree->addition_count(patch_id_end, triple_pattern);
        return std::make_pair(count, EXACT);
    }
    //P_start -> P -> S_end
    else if(snapshot_id_end == patch_id_end){
        DictionaryManager *dict = get_snapshot_manager()->get_dictionary_manager(snapshot_id_end);
        PatchTree* patchTree = get_patch_tree_manager()->get_patch_tree(patch_tree_id_start, dict);
        size_t count = patchTree->deletion_count(triple_pattern, patch_id_start).first + patchTree->addition_count(patch_id_start, triple_pattern);
        return std::make_pair(count, EXACT);
    }
    // reverse tree and forward tree case P_start -> S <- P_end
    else if(snapshot_id_start > patch_id_start && snapshot_id_end < patch_id_end) {
        DictionaryManager *dict = get_snapshot_manager()->get_dictionary_manager(snapshot_id_end);
        PatchTree* patchTreeForward = get_patch_tree_manager()->get_patch_tree(patch_tree_id_end, dict);
        PatchTree* patchTreeReverse = get_patch_tree_manager()->get_patch_tree(patch_tree_id_start, dict);
        size_t count = patchTreeForward->deletion_count(triple_pattern, patch_id_end).first + patchTreeForward->addition_count(patch_id_end, triple_pattern) + patchTreeReverse->deletion_count(triple_pattern, patch_id_start).first + patchTreeReverse->addition_count(patch_id_start, triple_pattern);
        return std::make_pair(count, UP_TO);
    }
    else{
        if (allowEstimates) {
            DictionaryManager *dict = get_snapshot_manager()->get_dictionary_manager(snapshot_id_start);
            PatchTree* patchTree = get_patch_tree_manager()->get_patch_tree(patch_tree_id_start, dict);
            size_t count_start = patchTree->deletion_count(triple_pattern, patch_id_start).first + patchTree->addition_count(patch_id_start, triple_pattern);
            size_t count_end = patchTree->deletion_count(triple_pattern, patch_id_end).first + patchTree->addition_count(patch_id_end, triple_pattern);
            // There may be an overlap between the delta-triples from start and end.
            // This overlap is not easy to determine, so we ignore it when possible.
            // The real count will never be higher this value, because we should subtract the overlap count.
            return std::make_pair(count_start + count_end, UP_TO);
        } else {
            return std::make_pair(get_delta_materialized(triple_pattern, 0, patch_id_start, patch_id_end)->get_count(), EXACT);
        }
    }
}

size_t Controller::get_delta_materialized_count_estimated(const Triple &triple_pattern, int patch_id_start, int patch_id_end) const {
    return get_delta_materialized_count(triple_pattern, patch_id_start, patch_id_end, true).second;
}

TripleDeltaIterator* Controller::get_delta_materialized(const Triple &triple_pattern, int offset, int patch_id_start,
                                                        int patch_id_end) const {
    if (patch_id_end <= patch_id_start) {
        return new EmptyTripleDeltaIterator();
    }

    // Find the snapshot
    int snapshot_id_start = get_corresponding_snapshot_id(patch_id_start);
    int snapshot_id_end = get_corresponding_snapshot_id(patch_id_end);
    if (snapshot_id_start < 0 || snapshot_id_end < 0) {
        return new EmptyTripleDeltaIterator();
    }

    // start = snapshot, end = snapshot
    if(snapshot_id_start == patch_id_start && snapshot_id_end == patch_id_end) {
        // TODO: implement this when multiple snapshots are supported
        throw std::invalid_argument("Multiple snapshots are not supported.");
    }

    // start = snapshot, end = patch
    if(snapshot_id_start == patch_id_start && snapshot_id_end != patch_id_end) {
        DictionaryManager *dict = get_snapshot_manager()->get_dictionary_manager(snapshot_id_end);
        if (snapshot_id_start == snapshot_id_end) {
            // Return iterator for the end patch relative to the start snapshot
            int patch_tree_id = get_patch_tree_id(patch_id_end);
            PatchTree* patchTree = get_patch_tree_manager()->get_patch_tree(patch_tree_id, dict);
            if(patchTree == NULL) {
                throw std::invalid_argument("Could not find the given end patch id");
            }
            if (TripleStore::is_default_tree(triple_pattern)) {
                return (new ForwardPatchTripleDeltaIterator<PatchTreeDeletionValue>(patchTree, triple_pattern, patch_id_end))->offset(offset);
            } else {
                return (new ForwardPatchTripleDeltaIterator<PatchTreeDeletionValueReduced>(patchTree, triple_pattern, patch_id_end))->offset(offset);
            }
        } else {
            // TODO: implement this when multiple snapshots are supported
            throw std::invalid_argument("Multiple snapshots are not supported.");
        }
    }

    // start = patch, end = snapshot
    if(snapshot_id_start != patch_id_start && snapshot_id_end == patch_id_end) {
        DictionaryManager *dict = get_snapshot_manager()->get_dictionary_manager(snapshot_id_end);
        if (snapshot_id_start == snapshot_id_end) {
            // Return iterator for the end patch relative to the start snapshot
            int patch_tree_id = get_patch_tree_id(patch_id_start);
            PatchTree* patchTree = get_patch_tree_manager()->get_patch_tree(patch_tree_id, dict);
            if(patchTree == NULL) {
                throw std::invalid_argument("Could not find the given end patch id");
            }
            if (TripleStore::is_default_tree(triple_pattern)) {
                return (new ForwardPatchTripleDeltaIterator<PatchTreeDeletionValue>(patchTree, triple_pattern, patch_id_start))->offset(offset);
            } else {
                return (new ForwardPatchTripleDeltaIterator<PatchTreeDeletionValueReduced>(patchTree, triple_pattern, patch_id_start))->offset(offset);
            }
        } else {
            // TODO: implement this when multiple snapshots are supported
            throw std::invalid_argument("Multiple snapshots are not supported.");
        }

//        // TODO: implement this when multiple snapshots are supported
//        throw std::invalid_argument("Multiple snapshots are not supported.");
    }

    // start = patch, end = patch
    if(snapshot_id_start != patch_id_start && snapshot_id_end != patch_id_end) {
        DictionaryManager *dict = get_snapshot_manager()->get_dictionary_manager(snapshot_id_end);
        if (snapshot_id_start == snapshot_id_end) {

            // Return diff between two patches relative to the same snapshot
            int patch_tree_id_end = get_patch_tree_id(patch_id_end);
            int patch_tree_id_start = get_patch_tree_id(patch_id_start);

            // forward patch tree (same tree) S <- P_start <- P_end
            if(snapshot_id_start < patch_tree_id_start && patch_tree_id_end == patch_tree_id_start){

                PatchTree* patchTree = get_patch_tree_manager()->get_patch_tree(patch_tree_id_end, dict);
                if(patchTree == NULL) {
                    throw std::invalid_argument("Could not find the given end patch id");
                }

                if (TripleStore::is_default_tree(triple_pattern)) {
                    return (new ForwardDiffPatchTripleDeltaIterator<PatchTreeDeletionValue>(patchTree, triple_pattern, patch_id_start, patch_id_end))->offset(offset);
                } else {
                    return (new ForwardDiffPatchTripleDeltaIterator<PatchTreeDeletionValueReduced>(patchTree, triple_pattern, patch_id_start, patch_id_end))->offset(offset);
                }
            }
            //reverse patch tree (same tree) P_start -> P_end -> S
            else if(snapshot_id_start > patch_tree_id_start && patch_tree_id_end == patch_tree_id_start){

                PatchTree* patchTree = get_patch_tree_manager()->get_patch_tree(patch_tree_id_end, dict);
                if(patchTree == NULL) {
                    throw std::invalid_argument("Could not find the given end patch id");
                }

                if (TripleStore::is_default_tree(triple_pattern)) {
                    return (new ForwardDiffPatchTripleDeltaIterator<PatchTreeDeletionValue>(patchTree, triple_pattern, patch_id_start, patch_id_end, true))->offset(offset);
                } else {
                    return (new ForwardDiffPatchTripleDeltaIterator<PatchTreeDeletionValueReduced>(patchTree, triple_pattern, patch_id_start, patch_id_end, true))->offset(offset);
                }
            }
            // reverse tree and forward tree case P_start -> S <- P_end
            else{
//                int patch_tree_id = get_patch_tree_id(patch_id_start);
//                PatchTree* patchTree = get_patch_tree_manager()->get_patch_tree(patch_tree_id, dict);
//                if(patchTree == NULL) {
//                    throw std::invalid_argument("Could not find the given end patch id");
//                }
//                if (TripleStore::is_default_tree(triple_pattern)) {
//                    return (new ForwardPatchTripleDeltaIterator<PatchTreeDeletionValue>(patchTree, triple_pattern, patch_id_start))->offset(offset);
//                } else {
//                    return (new ForwardPatchTripleDeltaIterator<PatchTreeDeletionValueReduced>(patchTree, triple_pattern, patch_id_start))->offset(offset);
//                }
//
//                int patch_tree_id = get_patch_tree_id(patch_id_end);
//                PatchTree* patchTree = get_patch_tree_manager()->get_patch_tree(patch_tree_id, dict);
//                if(patchTree == NULL) {
//                    throw std::invalid_argument("Could not find the given end patch id");
//                }
//                if (TripleStore::is_default_tree(triple_pattern)) {
//                    return (new ForwardPatchTripleDeltaIterator<PatchTreeDeletionValue>(patchTree, triple_pattern, patch_id_end))->offset(offset);
//                } else {
//                    return (new ForwardPatchTripleDeltaIterator<PatchTreeDeletionValueReduced>(patchTree, triple_pattern, patch_id_end))->offset(offset);
//                }
                PatchTree* patchTreeReverse = get_patch_tree_manager()->get_patch_tree(patch_tree_id_start, dict);
                PatchTree* patchTreeForward = get_patch_tree_manager()->get_patch_tree(patch_tree_id_end, dict);
                if(patchTreeReverse == NULL || patchTreeForward == NULL) {
                    throw std::invalid_argument("Could not find the given patch id");
                }

                if (TripleStore::is_default_tree(triple_pattern)) {
                    return (new BiDiffPatchTripleDeltaIterator<PatchTreeDeletionValue>(
                            new ForwardPatchTripleDeltaIterator<PatchTreeDeletionValue>(patchTreeReverse,
                                                                                triple_pattern,
                                                                                patch_id_start
                                                                                ),
                            new ForwardPatchTripleDeltaIterator<PatchTreeDeletionValue>(patchTreeForward,
                                                                                triple_pattern,
                                                                                patch_id_end),
                            patchTreeForward->get_spo_comparator()))->offset(offset);
                } else {
                    return (new BiDiffPatchTripleDeltaIterator<PatchTreeDeletionValueReduced>(
                            new ForwardPatchTripleDeltaIterator<PatchTreeDeletionValueReduced>(patchTreeReverse,
                                                                                triple_pattern,
                                                                                patch_id_start),
                            new ForwardPatchTripleDeltaIterator<PatchTreeDeletionValueReduced>(patchTreeForward,
                                                                                triple_pattern,
                                                                                patch_id_end),
                            patchTreeForward->get_spo_comparator()))->offset(offset);
                }

            }

        } else {
            // TODO: implement this when multiple snapshots are supported
            throw std::invalid_argument("Multiple snapshots are not supported.");
        }
    }
    return nullptr;
}

std::pair<size_t, ResultEstimationType> Controller::get_version_count(const Triple &triple_pattern, bool allowEstimates) const {
    // TODO: this will require some changes when we support multiple snapshots.
    // Find the snapshot an count its elements
    HDT* snapshot = get_snapshot_manager()->get_snapshot(0);
    IteratorTripleID* snapshot_it = SnapshotManager::search_with_offset(snapshot, triple_pattern, 0);
    size_t count = snapshot_it->estimatedNumResults();
    if (!allowEstimates && snapshot_it->numResultEstimation() != EXACT) {
        count = 0;
        while (snapshot_it->hasNext()) {
            snapshot_it->next();
            count++;
        }
    }

    // Count the additions for all versions
    DictionaryManager *dict = get_snapshot_manager()->get_dictionary_manager(0);
    PatchTree* patchTree = get_patch_tree_manager()->get_patch_tree(0, dict);
    if (patchTree != NULL) {
        count += patchTree->addition_count(0, triple_pattern);
    }
    return std::make_pair(count, allowEstimates ? snapshot_it->numResultEstimation() : EXACT);
}

std::pair<size_t, ResultEstimationType> Controller::get_partial_version_count(const Triple &triple_pattern, bool allowEstimates) const {
    // TODO: this will require some changes when we support multiple snapshots.
    int snapshot_id = snapshotManager->get_snapshots().begin()->first;
    int reverse_patch_tree_id = snapshot_id - 1;
    int forward_patch_tree_id = snapshot_id + 1;

    // Find the snapshot an count its elements
    HDT* snapshot = get_snapshot_manager()->get_snapshot(snapshot_id);
    DictionaryManager *dict = get_snapshot_manager()->get_dictionary_manager(snapshot_id);
    IteratorTripleID* snapshot_it = SnapshotManager::search_with_offset(snapshot, triple_pattern, 0);
    PatchTree* reverse_patch_tree = get_patch_tree_manager()->get_patch_tree(reverse_patch_tree_id, dict); // Can be null
    PatchTree* forward_patch_tree = get_patch_tree_manager()->get_patch_tree(forward_patch_tree_id, dict); // Can be null

    size_t count = snapshot_it->estimatedNumResults();
    if (!allowEstimates && snapshot_it->numResultEstimation() != EXACT) {
        count = 0;
        while (snapshot_it->hasNext()) {
            snapshot_it->next();
            count++;
        }
    }

    // Count the additions for all versions
    if (reverse_patch_tree != NULL) {
        count += reverse_patch_tree->addition_count(-1, triple_pattern);
    }
    if (forward_patch_tree != NULL) {
        count += forward_patch_tree->addition_count(-1, triple_pattern);
    }

    return std::make_pair(count, UP_TO);
}

size_t Controller::get_version_count_estimated(const Triple &triple_pattern) const {
    return get_version_count(triple_pattern, true).first;
}
TripleVersionsIterator* Controller::get_partial_version(const Triple &triple_pattern, int offset) const {
    int snapshot_id = snapshotManager->get_snapshots().begin()->first;
    int reverse_patch_tree_id = snapshot_id - 1;
    int forward_patch_tree_id = snapshot_id + 1;

    HDT* snapshot = get_snapshot_manager()->get_snapshot(snapshot_id);
    IteratorTripleID* snapshot_it = SnapshotManager::search_with_offset(snapshot, triple_pattern, offset);
    DictionaryManager *dict = get_snapshot_manager()->get_dictionary_manager(snapshot_id);
    PatchTree* reverse_patch_tree = get_patch_tree_manager()->get_patch_tree(reverse_patch_tree_id, dict); // Can be null
    PatchTree* forward_patch_tree = get_patch_tree_manager()->get_patch_tree(forward_patch_tree_id, dict); // Can be null

    // Snapshots have already been offsetted, calculate the remaining offset.
    // After this, offset will only be >0 if we are past the snapshot elements and at the additions.
    if (snapshot_it->numResultEstimation() == EXACT) {
        offset -= snapshot_it->estimatedNumResults();
        if (offset <= 0) {
            offset = 0;
        } else {
            delete snapshot_it;
            snapshot_it = NULL;
        }
    } else {
        IteratorTripleID *tmp_it = SnapshotManager::search_with_offset(snapshot, triple_pattern, 0);
        while (tmp_it->hasNext() && offset > 0) {
            tmp_it->next();
            offset--;
        }
        delete tmp_it;
    }
    return (new TripleVersionsIterator(triple_pattern, snapshot_it, reverse_patch_tree, forward_patch_tree, snapshot_id))->offset(offset);
}
TripleVersionsIterator* Controller::get_version(const Triple &triple_pattern, int offset) const {
//    // TODO: this will require some changes when we support multiple snapshots. (probably just a simple merge for all snapshots with what is already here)
//    // Find the snapshot
//    int snapshot_id = 0;
//    HDT* snapshot = get_snapshot_manager()->get_snapshot(snapshot_id);
//    IteratorTripleID* snapshot_it = SnapshotManager::search_with_offset(snapshot, triple_pattern, offset);
//    DictionaryManager *dict = get_snapshot_manager()->get_dictionary_manager(snapshot_id);
//    PatchTree* patchTree = get_patch_tree_manager()->get_patch_tree(snapshot_id, dict); // Can be null, if only snapshot is available
//
//    // Snapshots have already been offsetted, calculate the remaining offset.
//    // After this, offset will only be >0 if we are past the snapshot elements and at the additions.
//    if (snapshot_it->numResultEstimation() == EXACT) {
//        offset -= snapshot_it->estimatedNumResults();
//        if (offset <= 0) {
//            offset = 0;
//        } else {
//            delete snapshot_it;
//            snapshot_it = NULL;
//        }
//    } else {
//        IteratorTripleID *tmp_it = SnapshotManager::search_with_offset(snapshot, triple_pattern, 0);
//        while (tmp_it->hasNext() && offset > 0) {
//            tmp_it->next();
//            offset--;
//        }
//        delete tmp_it;
//    }
//
//    return (new TripleVersionsIterator(triple_pattern, snapshot_it, patchTree, 0))->offset(offset);
    return NULL;
}

bool Controller::append(PatchElementIterator* patch_it, int patch_id, DictionaryManager* dict, bool check_uniqueness, ProgressListener* progressListener) {

    //find largest key smaller or equal to patch_id, this is the patch_tree_id
    auto it = patchTreeManager->get_patch_trees().lower_bound(patch_id); //gives elements equal to or greater than patch_id
    if(it == patchTreeManager->get_patch_trees().end() || it->first > patch_id) {
        if(it == patchTreeManager->get_patch_trees().begin()) {
            // todo error no smaller element found
            return -1;
        }
        it--;
    }
    int patch_tree_id = it->first;
    return get_patch_tree_manager()->append(patch_it, patch_id, patch_tree_id, check_uniqueness, progressListener, dict);
}

bool Controller::reverse_append(PatchElementIterator* patch_it, int patch_id, DictionaryManager* dict, bool check_uniqueness, ProgressListener* progressListener) {

    //find smallest element larger than or equal to patch_id, this is the patch_tree_id
    int patch_tree_id;
    if(patchTreeManager->get_patch_trees().find(patch_id) == patchTreeManager->get_patch_trees().end()){
        auto iterator = patchTreeManager->get_patch_trees().upper_bound(patch_id); //returns first element bigger than patch_id
        patch_tree_id = iterator->first;
    }
    else{
        patch_tree_id = patch_id;
    }
    return get_patch_tree_manager()->reverse_append(patch_it, patch_id, patch_tree_id, dict, check_uniqueness, progressListener);
}

PatchTreeManager* Controller::get_patch_tree_manager() const {
    return patchTreeManager;
}

SnapshotManager* Controller::get_snapshot_manager() const {
    return snapshotManager;
}

DictionaryManager *Controller::get_dictionary_manager(int patch_id) const {
    int snapshot_id = get_corresponding_snapshot_id(patch_id);
    if(snapshot_id < 0) {
        throw std::invalid_argument("No snapshot has been created yet.");
    }
    get_snapshot_manager()->get_snapshot(snapshot_id); // Force a snapshot load
    return get_snapshot_manager()->get_dictionary_manager(snapshot_id);
}

int Controller::get_max_patch_id() {
    get_snapshot_manager()->get_snapshot(0); // Make sure our first snapshot is loaded, otherwise KC might get intro trouble while reorganising since it needs the dict for that.
    int max_patch_id = get_patch_tree_manager()->get_max_patch_id(get_snapshot_manager()->get_dictionary_manager(0));
    if (max_patch_id < 0) {
        return get_corresponding_snapshot_id(0);
    }
    return max_patch_id;
}

void Controller::cleanup(string basePath, Controller* controller) {
    // Delete patch files
    std::map<int, PatchTree*> patches = controller->get_patch_tree_manager()->get_patch_trees();
    std::map<int, PatchTree*>::iterator itP = patches.begin();
    std::list<int> patchMetadataToDelete;
    while(itP != patches.end()) {
        int id = itP->first;
        std::remove((basePath + PATCHTREE_FILENAME(id, "spo_deletions")).c_str());
        std::remove((basePath + PATCHTREE_FILENAME(id, "pos_deletions")).c_str());
        std::remove((basePath + PATCHTREE_FILENAME(id, "pso_deletions")).c_str());
        std::remove((basePath + PATCHTREE_FILENAME(id, "sop_deletions")).c_str());
        std::remove((basePath + PATCHTREE_FILENAME(id, "osp_deletions")).c_str());
        std::remove((basePath + PATCHTREE_FILENAME(id, "spo_additions")).c_str());
        std::remove((basePath + PATCHTREE_FILENAME(id, "pos_additions")).c_str());
        std::remove((basePath + PATCHTREE_FILENAME(id, "pso_additions")).c_str());
        std::remove((basePath + PATCHTREE_FILENAME(id, "sop_additions")).c_str());
        std::remove((basePath + PATCHTREE_FILENAME(id, "osp_additions")).c_str());
        std::remove((basePath + PATCHTREE_FILENAME(id, "count_additions")).c_str());
        std::remove((basePath + PATCHTREE_FILENAME(id, "count_additions.tmp")).c_str());
        patchMetadataToDelete.push_back(id);
        itP++;
    }

    // Delete snapshot files
    std::map<int, HDT*> snapshots = controller->get_snapshot_manager()->get_snapshots();
    std::map<int, HDT*>::iterator itS = snapshots.begin();
    std::list<int> patchDictsToDelete;
    while(itS != snapshots.end()) {
        int id = itS->first;
        std::remove((basePath + SNAPSHOT_FILENAME_BASE(id)).c_str());
        std::remove((basePath + SNAPSHOT_FILENAME_BASE(id) + ".index").c_str());

        patchDictsToDelete.push_back(id);
        itS++;
    }

    delete controller;

    // Delete dictionaries
    std::list<int>::iterator it1;
    for(it1=patchDictsToDelete.begin(); it1!=patchDictsToDelete.end(); ++it1) {
        DictionaryManager::cleanup(basePath, *it1);
    }

    // Delete metadata files
    std::list<int>::iterator it2;
    for(it2=patchMetadataToDelete.begin(); it2!=patchMetadataToDelete.end(); ++it2) {
        std::remove((basePath + METADATA_FILENAME_BASE(*it2)).c_str());
    }
}

PatchBuilder* Controller::new_patch_bulk() {
    return new PatchBuilder(this);
}

PatchBuilderStreaming *Controller::new_patch_stream() {
    return new PatchBuilderStreaming(this);
}

bool Controller::replace_patch_tree(string basePath, int patch_tree_id) {

    // remove old files
    std::remove((basePath + PATCHTREE_FILENAME(patch_tree_id, "spo_deletions")).c_str());
    std::remove((basePath + PATCHTREE_FILENAME(patch_tree_id, "pos_deletions")).c_str());
    std::remove((basePath + PATCHTREE_FILENAME(patch_tree_id, "pso_deletions")).c_str());
    std::remove((basePath + PATCHTREE_FILENAME(patch_tree_id, "sop_deletions")).c_str());
    std::remove((basePath + PATCHTREE_FILENAME(patch_tree_id, "osp_deletions")).c_str());
    std::remove((basePath + PATCHTREE_FILENAME(patch_tree_id, "spo_additions")).c_str());
    std::remove((basePath + PATCHTREE_FILENAME(patch_tree_id, "pos_additions")).c_str());
    std::remove((basePath + PATCHTREE_FILENAME(patch_tree_id, "pso_additions")).c_str());
    std::remove((basePath + PATCHTREE_FILENAME(patch_tree_id, "sop_additions")).c_str());
    std::remove((basePath + PATCHTREE_FILENAME(patch_tree_id, "osp_additions")).c_str());
    std::remove((basePath + PATCHTREE_FILENAME(patch_tree_id, "count_additions")).c_str());
    std::remove((basePath + PATCHTREE_FILENAME(patch_tree_id, "count_additions.tmp")).c_str());
    std::remove((basePath + METADATA_FILENAME_BASE(patch_tree_id)).c_str());

    //rename temp files
    std::rename((basePath + TEMP_PATCHTREE_FILENAME(patch_tree_id, "spo_deletions")).c_str(), (basePath + PATCHTREE_FILENAME(patch_tree_id, "spo_deletions")).c_str());
    std::rename((basePath + TEMP_PATCHTREE_FILENAME(patch_tree_id, "pos_deletions")).c_str(), (basePath + PATCHTREE_FILENAME(patch_tree_id, "pos_deletions")).c_str());
    std::rename((basePath + TEMP_PATCHTREE_FILENAME(patch_tree_id, "pso_deletions")).c_str(), (basePath + PATCHTREE_FILENAME(patch_tree_id, "pso_deletions")).c_str());
    std::rename((basePath + TEMP_PATCHTREE_FILENAME(patch_tree_id, "sop_deletions")).c_str(), (basePath + PATCHTREE_FILENAME(patch_tree_id, "sop_deletions")).c_str());
    std::rename((basePath + TEMP_PATCHTREE_FILENAME(patch_tree_id, "osp_deletions")).c_str(), (basePath + PATCHTREE_FILENAME(patch_tree_id, "osp_deletions")).c_str());
    std::rename((basePath + TEMP_PATCHTREE_FILENAME(patch_tree_id, "spo_additions")).c_str(), (basePath + PATCHTREE_FILENAME(patch_tree_id, "spo_additions")).c_str());
    std::rename((basePath + TEMP_PATCHTREE_FILENAME(patch_tree_id, "pos_additions")).c_str(), (basePath + PATCHTREE_FILENAME(patch_tree_id, "pos_additions")).c_str());
    std::rename((basePath + TEMP_PATCHTREE_FILENAME(patch_tree_id, "pso_additions")).c_str(), (basePath + PATCHTREE_FILENAME(patch_tree_id, "pso_additions")).c_str());
    std::rename((basePath + TEMP_PATCHTREE_FILENAME(patch_tree_id, "sop_additions")).c_str(), (basePath + PATCHTREE_FILENAME(patch_tree_id, "sop_additions")).c_str());
    std::rename((basePath + TEMP_PATCHTREE_FILENAME(patch_tree_id, "osp_additions")).c_str(), (basePath + PATCHTREE_FILENAME(patch_tree_id, "osp_additions")).c_str());
    std::rename((basePath + TEMP_PATCHTREE_FILENAME(patch_tree_id, "count_additions")).c_str(), (basePath + PATCHTREE_FILENAME(patch_tree_id, "count_additions")).c_str());
    std::rename((basePath + TEMP_PATCHTREE_FILENAME(patch_tree_id, "count_additions.tmp")).c_str(), (basePath + PATCHTREE_FILENAME(patch_tree_id, "count_additions.tmp")).c_str());
    std::rename((basePath + TEMP_METADATA_FILENAME_BASE(patch_tree_id)).c_str(), (basePath + METADATA_FILENAME_BASE(patch_tree_id)).c_str());
    return true;
}

int Controller::get_patch_tree_id(int patch_id)const {
    // case 1: S <- P <- P
    // case 2: S <- P <- P S <- P
    // case 3: S <- P <- P P -> P -> S <- P
    // case 4: P -> P -> S <- P <- P

    // return lower tree if reverse tree does not exists

    // return upper tree if reverse tree does exists
    std::map<int, HDT*> loaded_snapshots = get_snapshot_manager()->get_snapshots();

    std::map<int, HDT*>::iterator low, prev;
    low = loaded_snapshots.lower_bound(patch_id);
    int low_snapshot_id = -1;
    int high_snapshot_id = -1;

    if(low == loaded_snapshots.begin() && low == loaded_snapshots.end()) {
        // empty map
        return -1;
    }
    if (low == loaded_snapshots.end()) {
        low--;
        low_snapshot_id = low->first;
    } else if (low == loaded_snapshots.begin()) {
        low_snapshot_id = low->first;
    } else {
        prev = std::prev(low);
        high_snapshot_id = low->first;
        low_snapshot_id = prev->first;
    }

    // case 4
    if(low_snapshot_id > patch_id){
        return low_snapshot_id - 1;
    }

    std::map<int, PatchTree*> patches = get_patch_tree_manager()->get_patch_trees();
    int low_patch_tree_id = low_snapshot_id + 1 ; // todo make function of forward patch_tree_id
    if(high_snapshot_id >= 0){ // if high snapshot exists
        auto it = patches.find(high_snapshot_id - 1); // todo make function of reverse patch_tree_id
        if(it != patches.end()){ // if reverse patch tree exists
            int dist_to_low = patch_id - low_snapshot_id;
            int dist_to_high = high_snapshot_id -  patch_id;

            if(dist_to_high < dist_to_low){ // closer to reverse patch tree
                return high_snapshot_id - 1; // todo make function of reverse patch_tree_id
            }
        }
    }
    // check if forward chain exists
    auto it = patches.find(low_patch_tree_id); // todo make function of reverse patch_tree_id
    if(it == patches.end()){
        return -1;
    }
    return low_patch_tree_id;
}

int Controller::get_corresponding_snapshot_id(int patch_id) const {
    // get snapshot before patch_id
    // get snapshot after patch_id

    // if snapshot after patch_id does not exist or snapshot_after does not have reverse tree, return snapshot before patch_id
    // if reverse does exist, return snapshot id closest to patch_id (in case of tie, return lowest snapshot_id
    std::map<int, HDT*> loaded_snapshots = get_snapshot_manager()->get_snapshots();

    std::map<int, HDT*>::iterator low, prev;
    low = loaded_snapshots.lower_bound(patch_id);
    int low_snapshot_id = -1;
    int high_snapshot_id = -1;

    if(low == loaded_snapshots.begin() && low == loaded_snapshots.end()) {
        // empty map
        return -1;
    }
    if (low == loaded_snapshots.end()) {
        low--;
        low_snapshot_id = low->first;
    } else if (low == loaded_snapshots.begin()) {
        low_snapshot_id = low->first;
    } else {
        prev = std::prev(low);
        high_snapshot_id = low->first;
        low_snapshot_id = prev->first;
    }
    if(high_snapshot_id == patch_id)
        return high_snapshot_id;
    else if(low_snapshot_id == patch_id)
        return low_snapshot_id;
    else{
        std::map<int, PatchTree*> loaded_patches = get_patch_tree_manager()->get_patch_trees();
        int low_patch_tree_id = low_snapshot_id + 1 ; // todo make function of forward patch_tree_id
        if(high_snapshot_id >= 0){ // if high snapshot exists
            auto it = loaded_patches.find(high_snapshot_id - 1); // todo make function of reverse patch_tree_id
            if(it != loaded_patches.end()){ // if reverse patch tree exists
                int dist_to_low = patch_id - low_snapshot_id;
                int dist_to_high = high_snapshot_id -  patch_id;
                if(dist_to_high < dist_to_low){ // closer to reverse patch tree
                    return high_snapshot_id;
                }
            }
        }
        return low_snapshot_id;}
}

bool Controller::copy_patch_tree_files(string basePath, int patch_tree_id) {
    try {
        boost::filesystem::path source, target;

        source = basePath + PATCHTREE_FILENAME(patch_tree_id, "spo_deletions");
        target = basePath + TEMP_PATCHTREE_FILENAME(patch_tree_id, "spo_deletions");
        if (boost::filesystem::exists(source))
            boost::filesystem::copy_file(source, target);
        source = basePath + PATCHTREE_FILENAME(patch_tree_id, "pos_deletions");
        target = basePath + TEMP_PATCHTREE_FILENAME(patch_tree_id, "pos_deletions");
        if (boost::filesystem::exists(source))
            boost::filesystem::copy_file(source, target);
        source = basePath + PATCHTREE_FILENAME(patch_tree_id, "pso_deletions");
        target = basePath + TEMP_PATCHTREE_FILENAME(patch_tree_id, "pso_deletions");
        if (boost::filesystem::exists(source))
            boost::filesystem::copy_file(source, target);
        source = basePath + PATCHTREE_FILENAME(patch_tree_id, "sop_deletions");
        target = basePath + TEMP_PATCHTREE_FILENAME(patch_tree_id, "sop_deletions");
        if (boost::filesystem::exists(source))
            boost::filesystem::copy_file(source, target);
        source = basePath + PATCHTREE_FILENAME(patch_tree_id, "osp_deletions");
        target = basePath + TEMP_PATCHTREE_FILENAME(patch_tree_id, "osp_deletions");
        if (boost::filesystem::exists(source))
            boost::filesystem::copy_file(source, target);
        source = basePath + PATCHTREE_FILENAME(patch_tree_id, "spo_additions");
        target = basePath + TEMP_PATCHTREE_FILENAME(patch_tree_id, "spo_additions");
        if (boost::filesystem::exists(source))
            boost::filesystem::copy_file(source, target);
        source = basePath + PATCHTREE_FILENAME(patch_tree_id, "pos_additions");
        target = basePath + TEMP_PATCHTREE_FILENAME(patch_tree_id, "pos_additions");
        if (boost::filesystem::exists(source))
            boost::filesystem::copy_file(source, target);
        source = basePath + PATCHTREE_FILENAME(patch_tree_id, "pso_additions");
        target = basePath + TEMP_PATCHTREE_FILENAME(patch_tree_id, "pso_additions");
        if (boost::filesystem::exists(source))
            boost::filesystem::copy_file(source, target);
        source = basePath + PATCHTREE_FILENAME(patch_tree_id, "sop_additions");
        target = basePath + TEMP_PATCHTREE_FILENAME(patch_tree_id, "sop_additions");
        if (boost::filesystem::exists(source))
            boost::filesystem::copy_file(source, target);
        source = basePath + PATCHTREE_FILENAME(patch_tree_id, "osp_additions");
        target = basePath + TEMP_PATCHTREE_FILENAME(patch_tree_id, "osp_additions");
        if (boost::filesystem::exists(source))
            boost::filesystem::copy_file(source, target);
        source = basePath + PATCHTREE_FILENAME(patch_tree_id, "count_additions");
        target = basePath + TEMP_PATCHTREE_FILENAME(patch_tree_id, "count_additions");
        if (boost::filesystem::exists(source))
            boost::filesystem::copy_file(source, target);
//        source = basePath + PATCHTREE_FILENAME(patch_tree_id, "count_additions.tmp");
//        target = basePath + TEMP_PATCHTREE_FILENAME(patch_tree_id, "count_additions.tmp");
//        if (boost::filesystem::exists(source))
//            boost::filesystem::copy_file(source, target);
        source = basePath + METADATA_FILENAME_BASE(patch_tree_id);
        target = basePath + TEMP_METADATA_FILENAME_BASE(patch_tree_id);
        if (boost::filesystem::exists(source))
            boost::filesystem::copy_file(source, target);
    } catch (const boost::filesystem::filesystem_error& e){
        return false;
    }
    return true;
}

void Controller::remove_forward_chain(std::string basePath, int temp_snapshot_id){

    int patch_tree_id = temp_snapshot_id + 1;
    get_patch_tree_manager()->remove_patch_tree(patch_tree_id);
    get_snapshot_manager()->remove_snapshot(temp_snapshot_id);
    std::remove((basePath + PATCHDICT_FILENAME_BASE(temp_snapshot_id)).c_str());
    std::remove((basePath + METADATA_FILENAME_BASE(patch_tree_id)).c_str());
    std::remove((basePath + SNAPSHOT_FILENAME_BASE(temp_snapshot_id)).c_str());
    std::remove((basePath + SNAPSHOT_FILENAME_BASE(temp_snapshot_id) + ".index").c_str());
    std::remove((basePath + PATCHTREE_FILENAME(patch_tree_id, "spo_deletions")).c_str());
    std::remove((basePath + PATCHTREE_FILENAME(patch_tree_id, "pos_deletions")).c_str());
    std::remove((basePath + PATCHTREE_FILENAME(patch_tree_id, "pso_deletions")).c_str());
    std::remove((basePath + PATCHTREE_FILENAME(patch_tree_id, "sop_deletions")).c_str());
    std::remove((basePath + PATCHTREE_FILENAME(patch_tree_id, "osp_deletions")).c_str());
    std::remove((basePath + PATCHTREE_FILENAME(patch_tree_id, "spo_additions")).c_str());
    std::remove((basePath + PATCHTREE_FILENAME(patch_tree_id, "pos_additions")).c_str());
    std::remove((basePath + PATCHTREE_FILENAME(patch_tree_id, "pso_additions")).c_str());
    std::remove((basePath + PATCHTREE_FILENAME(patch_tree_id, "sop_additions")).c_str());
    std::remove((basePath + PATCHTREE_FILENAME(patch_tree_id, "osp_additions")).c_str());
    std::remove((basePath + PATCHTREE_FILENAME(patch_tree_id, "count_additions")).c_str());
    std::remove((basePath + PATCHTREE_FILENAME(patch_tree_id, "count_additions.tmp")).c_str());

}

void Controller::extract_changeset(int patch_tree_id, std::string path_to_files) {
    patchTreeManager->get_patch_tree(patch_tree_id, get_dictionary_manager(patch_tree_id))->getTripleStore()->extract_additions(get_dictionary_manager(patch_tree_id), path_to_files);
    patchTreeManager->get_patch_tree(patch_tree_id, get_dictionary_manager(patch_tree_id))->getTripleStore()->extract_deletions(get_dictionary_manager(patch_tree_id), path_to_files);
}

ext: cc

max_stars_repo_name: rdfostrich/cobra

max_issues_repo_name: rdfostrich/cobra

max_forks_repo_name: rdfostrich/cobra


text:
#include <optional>

#include <boost/test/unit_test.hpp>

#include <smtrat-common/smtrat-common.h>
#include <smtrat-mcsat/smtrat-mcsat.h>

#include <carl/core/Variable.h>
#include <carl-model/evaluation/ModelEvaluation.h>

#include <smtrat-mcsat/explanations/vs/VSHelper.h>

using namespace smtrat;

BOOST_AUTO_TEST_CASE(McsatVSBug) {
	carl::Variable x = carl::freshRealVariable("x");
	carl::Variable y = carl::freshRealVariable("y");
  carl::Variable z = carl::freshRealVariable("z");

  // 100 + -49*y^2 + -49*z^2 + 98*z*x + -98*x^2 < 0
  Poly p = Poly(Rational(100)) - Poly(Rational(49))*y*y - Poly(Rational(49))*z*z + Poly(Rational(98))*z*x - Poly(Rational(98))*x*x;
  ConstraintT c1(p, carl::Relation::LESS);

  // proof that f1 is false given a model
  Model m;
  m.assign(x, Rational(10)/7);
  m.assign(y, Rational(0));
  m.assign(z, Rational(10)/7);

  auto res = carl::model::evaluate(FormulaT(c1), m);
	BOOST_CHECK(res.isBool());
  BOOST_CHECK(!res.asBool());

  auto res2 = carl::model::evaluate(p, m);
	BOOST_CHECK(res2.isRational());
  BOOST_CHECK(res2.asRational() >= 0);

  // but VS returns true after substituting x -> 10/7 into c1
  ::vs::Substitution sub(x, SqrtEx(Poly(Rational(10)/7)), ::vs::Substitution::Type::NORMAL, carl::PointerSet<::vs::Condition>());
  smtrat::vs::DisjunctionOfConstraintConjunctions subResTmp;
  bool r = mcsat::vs::helper::substituteHelper(c1, sub, subResTmp);
  BOOST_CHECK(r);
  auto subRes = mcsat::vs::helper::doccToFormula(subResTmp);
  BOOST_CHECK(subRes.getType() != carl::FormulaType::TRUE);

  // The bug lies in splitSosDecompositions()
}

ext: cpp

max_stars_repo_name: ths-rwth/smtrat

max_issues_repo_name: ths-rwth/smtrat

max_forks_repo_name: ths-rwth/smtrat


text:
//
// dev_poll_reactor.hpp
// ~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//

#ifndef BOOST_ASIO_DETAIL_DEV_POLL_REACTOR_HPP
#define BOOST_ASIO_DETAIL_DEV_POLL_REACTOR_HPP

#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)

#include <boost/asio/detail/push_options.hpp>

#include <boost/asio/detail/dev_poll_reactor_fwd.hpp>

#if defined(BOOST_ASIO_HAS_DEV_POLL)

#include <boost/asio/detail/push_options.hpp>
#include <cstddef>
#include <vector>
#include <boost/config.hpp>
#include <boost/date_time/posix_time/posix_time_types.hpp>
#include <boost/throw_exception.hpp>
#include <sys/devpoll.h>
#include <boost/system/system_error.hpp>
#include <boost/asio/detail/pop_options.hpp>

#include <boost/asio/error.hpp>
#include <boost/asio/io_service.hpp>
#include <boost/asio/detail/hash_map.hpp>
#include <boost/asio/detail/mutex.hpp>
#include <boost/asio/detail/op_queue.hpp>
#include <boost/asio/detail/reactor_op.hpp>
#include <boost/asio/detail/reactor_op_queue.hpp>
#include <boost/asio/detail/select_interrupter.hpp>
#include <boost/asio/detail/service_base.hpp>
#include <boost/asio/detail/socket_types.hpp>
#include <boost/asio/detail/timer_op.hpp>
#include <boost/asio/detail/timer_queue_base.hpp>
#include <boost/asio/detail/timer_queue_fwd.hpp>
#include <boost/asio/detail/timer_queue_set.hpp>

namespace boost {
namespace asio {
namespace detail {

class dev_poll_reactor
  : public boost::asio::detail::service_base<dev_poll_reactor>
{
public:
  enum { read_op = 0, write_op = 1,
    connect_op = 1, except_op = 2, max_ops = 3 };

  // Per-descriptor data.
  struct per_descriptor_data
  {
  };

  // Constructor.
  dev_poll_reactor(boost::asio::io_service& io_service)
    : boost::asio::detail::service_base<dev_poll_reactor>(io_service),
      io_service_(use_service<io_service_impl>(io_service)),
      mutex_(),
      dev_poll_fd_(do_dev_poll_create()),
      interrupter_(),
      shutdown_(false)
  {
    // Add the interrupter's descriptor to /dev/poll.
    ::pollfd ev = { 0 };
    ev.fd = interrupter_.read_descriptor();
    ev.events = POLLIN | POLLERR;
    ev.revents = 0;
    ::write(dev_poll_fd_, &ev, sizeof(ev));
  }

  // Destructor.
  ~dev_poll_reactor()
  {
    shutdown_service();
    ::close(dev_poll_fd_);
  }

  // Destroy all user-defined handler objects owned by the service.
  void shutdown_service()
  {
    boost::asio::detail::mutex::scoped_lock lock(mutex_);
    shutdown_ = true;
    lock.unlock();

    op_queue<operation> ops;

    for (int i = 0; i < max_ops; ++i)
      op_queue_[i].get_all_operations(ops);

    timer_queues_.get_all_timers(ops);
  }

  // Initialise the task.
  void init_task()
  {
    io_service_.init_task();
  }

  // Register a socket with the reactor. Returns 0 on success, system error
  // code on failure.
  int register_descriptor(socket_type, per_descriptor_data&)
  {
    return 0;
  }

  // Start a new operation. The reactor operation will be performed when the
  // given descriptor is flagged as ready, or an error has occurred.
  void start_op(int op_type, socket_type descriptor,
      per_descriptor_data&, reactor_op* op, bool allow_speculative)
  {
    boost::asio::detail::mutex::scoped_lock lock(mutex_);

    if (shutdown_)
      return;

    if (allow_speculative)
    {
      if (op_type != read_op || !op_queue_[except_op].has_operation(descriptor))
      {
        if (!op_queue_[op_type].has_operation(descriptor))
        {
          if (op->perform())
          {
            lock.unlock();
            io_service_.post_immediate_completion(op);
            return;
          }
        }
      }
    }

    bool first = op_queue_[op_type].enqueue_operation(descriptor, op);
    io_service_.work_started();
    if (first)
    {
      ::pollfd& ev = add_pending_event_change(descriptor);
      ev.events = POLLERR | POLLHUP;
      if (op_type == read_op
          || op_queue_[read_op].has_operation(descriptor))
        ev.events |= POLLIN;
      if (op_type == write_op
          || op_queue_[write_op].has_operation(descriptor))
        ev.events |= POLLOUT;
      if (op_type == except_op
          || op_queue_[except_op].has_operation(descriptor))
        ev.events |= POLLPRI;
      interrupter_.interrupt();
    }
  }

  // Cancel all operations associated with the given descriptor. The
  // handlers associated with the descriptor will be invoked with the
  // operation_aborted error.
  void cancel_ops(socket_type descriptor, per_descriptor_data&)
  {
    boost::asio::detail::mutex::scoped_lock lock(mutex_);
    cancel_ops_unlocked(descriptor, boost::asio::error::operation_aborted);
  }

  // Cancel any operations that are running against the descriptor and remove
  // its registration from the reactor.
  void close_descriptor(socket_type descriptor, per_descriptor_data&)
  {
    boost::asio::detail::mutex::scoped_lock lock(mutex_);

    // Remove the descriptor from /dev/poll.
    ::pollfd& ev = add_pending_event_change(descriptor);
    ev.events = POLLREMOVE;
    interrupter_.interrupt();

    // Cancel any outstanding operations associated with the descriptor.
    cancel_ops_unlocked(descriptor, boost::asio::error::operation_aborted);
  }

  // Add a new timer queue to the reactor.
  template <typename Time_Traits>
  void add_timer_queue(timer_queue<Time_Traits>& timer_queue)
  {
    boost::asio::detail::mutex::scoped_lock lock(mutex_);
    timer_queues_.insert(&timer_queue);
  }

  // Remove a timer queue from the reactor.
  template <typename Time_Traits>
  void remove_timer_queue(timer_queue<Time_Traits>& timer_queue)
  {
    boost::asio::detail::mutex::scoped_lock lock(mutex_);
    timer_queues_.erase(&timer_queue);
  }

  // Schedule a new operation in the given timer queue to expire at the
  // specified absolute time.
  template <typename Time_Traits>
  void schedule_timer(timer_queue<Time_Traits>& timer_queue,
      const typename Time_Traits::time_type& time, timer_op* op, void* token)
  {
    boost::asio::detail::mutex::scoped_lock lock(mutex_);
    if (!shutdown_)
    {
      bool earliest = timer_queue.enqueue_timer(time, op, token);
      io_service_.work_started();
      if (earliest)
        interrupter_.interrupt();
    }
  }

  // Cancel the timer operations associated with the given token. Returns the
  // number of operations that have been posted or dispatched.
  template <typename Time_Traits>
  std::size_t cancel_timer(timer_queue<Time_Traits>& timer_queue, void* token)
  {
    boost::asio::detail::mutex::scoped_lock lock(mutex_);
    op_queue<operation> ops;
    std::size_t n = timer_queue.cancel_timer(token, ops);
    lock.unlock();
    io_service_.post_deferred_completions(ops);
    return n;
  }

  // Run /dev/poll once until interrupted or events are ready to be dispatched.
  void run(bool block, op_queue<operation>& ops)
  {
    boost::asio::detail::mutex::scoped_lock lock(mutex_);

    // We can return immediately if there's no work to do and the reactor is
    // not supposed to block.
    if (!block && op_queue_[read_op].empty() && op_queue_[write_op].empty()
        && op_queue_[except_op].empty() && timer_queues_.all_empty())
      return;

    // Write the pending event registration changes to the /dev/poll descriptor.
    std::size_t events_size = sizeof(::pollfd) * pending_event_changes_.size();
    if (events_size > 0)
    {
      errno = 0;
      int result = ::write(dev_poll_fd_,
          &pending_event_changes_[0], events_size);
      if (result != static_cast<int>(events_size))
      {
        boost::system::error_code ec = boost::system::error_code(
            errno, boost::asio::error::get_system_category());
        for (std::size_t i = 0; i < pending_event_changes_.size(); ++i)
        {
          int descriptor = pending_event_changes_[i].fd;
          for (int j = 0; j < max_ops; ++j)
            op_queue_[j].cancel_operations(descriptor, ops, ec);
        }
      }
      pending_event_changes_.clear();
      pending_event_change_index_.clear();
    }

    int timeout = block ? get_timeout() : 0;
    lock.unlock();

    // Block on the /dev/poll descriptor.
    ::pollfd events[128] = { { 0 } };
    ::dvpoll dp = { 0 };
    dp.dp_fds = events;
    dp.dp_nfds = 128;
    dp.dp_timeout = timeout;
    int num_events = ::ioctl(dev_poll_fd_, DP_POLL, &dp);

    lock.lock();

    // Dispatch the waiting events.
    for (int i = 0; i < num_events; ++i)
    {
      int descriptor = events[i].fd;
      if (descriptor == interrupter_.read_descriptor())
      {
        interrupter_.reset();
      }
      else
      {
        bool more_reads = false;
        bool more_writes = false;
        bool more_except = false;

        // Exception operations must be processed first to ensure that any
        // out-of-band data is read before normal data.
        if (events[i].events & (POLLPRI | POLLERR | POLLHUP))
          more_except =
            op_queue_[except_op].perform_operations(descriptor, ops);
        else
          more_except = op_queue_[except_op].has_operation(descriptor);

        if (events[i].events & (POLLIN | POLLERR | POLLHUP))
          more_reads = op_queue_[read_op].perform_operations(descriptor, ops);
        else
          more_reads = op_queue_[read_op].has_operation(descriptor);

        if (events[i].events & (POLLOUT | POLLERR | POLLHUP))
          more_writes = op_queue_[write_op].perform_operations(descriptor, ops);
        else
          more_writes = op_queue_[write_op].has_operation(descriptor);

        if ((events[i].events & (POLLERR | POLLHUP)) != 0
              && !more_except && !more_reads && !more_writes)
        {
          // If we have an event and no operations associated with the
          // descriptor then we need to delete the descriptor from /dev/poll.
          // The poll operation can produce POLLHUP or POLLERR events when there
          // is no operation pending, so if we do not remove the descriptor we
          // can end up in a tight polling loop.
          ::pollfd ev = { 0 };
          ev.fd = descriptor;
          ev.events = POLLREMOVE;
          ev.revents = 0;
          ::write(dev_poll_fd_, &ev, sizeof(ev));
        }
        else
        {
          ::pollfd ev = { 0 };
          ev.fd = descriptor;
          ev.events = POLLERR | POLLHUP;
          if (more_reads)
            ev.events |= POLLIN;
          if (more_writes)
            ev.events |= POLLOUT;
          if (more_except)
            ev.events |= POLLPRI;
          ev.revents = 0;
          int result = ::write(dev_poll_fd_, &ev, sizeof(ev));
          if (result != sizeof(ev))
          {
            boost::system::error_code ec(errno,
                boost::asio::error::get_system_category());
            for (int j = 0; j < max_ops; ++j)
              op_queue_[j].cancel_operations(descriptor, ops, ec);
          }
        }
      }
    }
    timer_queues_.get_ready_timers(ops);
  }

  // Interrupt the select loop.
  void interrupt()
  {
    interrupter_.interrupt();
  }

private:
  // Create the /dev/poll file descriptor. Throws an exception if the descriptor
  // cannot be created.
  static int do_dev_poll_create()
  {
    int fd = ::open("/dev/poll", O_RDWR);
    if (fd == -1)
    {
      boost::throw_exception(
          boost::system::system_error(
            boost::system::error_code(errno,
              boost::asio::error::get_system_category()),
            "/dev/poll"));
    }
    return fd;
  }

  // Get the timeout value for the /dev/poll DP_POLL operation. The timeout
  // value is returned as a number of milliseconds. A return value of -1
  // indicates that the poll should block indefinitely.
  int get_timeout()
  {
    // By default we will wait no longer than 5 minutes. This will ensure that
    // any changes to the system clock are detected after no longer than this.
    return timer_queues_.wait_duration_msec(5 * 60 * 1000);
  }

  // Cancel all operations associated with the given descriptor. The do_cancel
  // function of the handler objects will be invoked. This function does not
  // acquire the dev_poll_reactor's mutex.
  void cancel_ops_unlocked(socket_type descriptor,
      const boost::system::error_code& ec)
  {
    bool need_interrupt = false;
    op_queue<operation> ops;
    for (int i = 0; i < max_ops; ++i)
      need_interrupt = op_queue_[i].cancel_operations(
          descriptor, ops, ec) || need_interrupt;
    io_service_.post_deferred_completions(ops);
    if (need_interrupt)
      interrupter_.interrupt();
  }

  // Add a pending event entry for the given descriptor.
  ::pollfd& add_pending_event_change(int descriptor)
  {
    hash_map<int, std::size_t>::iterator iter
      = pending_event_change_index_.find(descriptor);
    if (iter == pending_event_change_index_.end())
    {
      std::size_t index = pending_event_changes_.size();
      pending_event_changes_.reserve(pending_event_changes_.size() + 1);
      pending_event_change_index_.insert(std::make_pair(descriptor, index));
      pending_event_changes_.push_back(::pollfd());
      pending_event_changes_[index].fd = descriptor;
      pending_event_changes_[index].revents = 0;
      return pending_event_changes_[index];
    }
    else
    {
      return pending_event_changes_[iter->second];
    }
  }

  // The io_service implementation used to post completions.
  io_service_impl& io_service_;

  // Mutex to protect access to internal data.
  boost::asio::detail::mutex mutex_;

  // The /dev/poll file descriptor.
  int dev_poll_fd_;

  // Vector of /dev/poll events waiting to be written to the descriptor.
  std::vector< ::pollfd> pending_event_changes_;

  // Hash map to associate a descriptor with a pending event change index.
  hash_map<int, std::size_t> pending_event_change_index_;

  // The interrupter is used to break a blocking DP_POLL operation.
  select_interrupter interrupter_;

  // The queues of read, write and except operations.
  reactor_op_queue<socket_type> op_queue_[max_ops];

  // The timer queues.
  timer_queue_set timer_queues_;

  // Whether the service has been shut down.
  bool shutdown_;
};

} // namespace detail
} // namespace asio
} // namespace boost

#endif // defined(BOOST_ASIO_HAS_DEV_POLL)

#include <boost/asio/detail/pop_options.hpp>

#endif // BOOST_ASIO_DETAIL_DEV_POLL_REACTOR_HPP

ext: hpp

max_stars_repo_name: jonstewart/boost-svn

max_issues_repo_name: jonstewart/boost-svn

max_forks_repo_name: jonstewart/boost-svn


text:
#ifndef VOESTIMATOR_HPP_
#define VOESTIMATOR_HPP_

#include <iostream>
#include <stdio.h>
#include <signal.h>

#include <Eigen/Core>
#include <Eigen/Geometry>

#include <boost/shared_ptr.hpp>
#include <boost/function.hpp>

#include <lcm/lcm-cpp.hpp>
#include <bot_frames/bot_frames.h>
#include <bot_frames_cpp/bot_frames_cpp.hpp>
#include <lcmtypes/bot_core.hpp>

#include <pronto_utils/pronto_vis.hpp> // visualize pt clds

// A simple class which maintains an estimate of a head position
// and can publish it to LCM
class VoEstimator
{
public:
  VoEstimator(boost::shared_ptr<lcm::LCM> &lcm_, BotFrames* botframes_,
              std::string channel_extension_ = "");
  ~VoEstimator();

  void updatePosition(int64_t utime, int64_t utime_prev, Eigen::Isometry3d delta_camera);

  Eigen::Isometry3d getCameraPose(){ return local_to_head_*camera_to_head_.inverse(); }
  Eigen::Isometry3d getHeadPose(){ return local_to_head_; }
  void setHeadPose(Eigen::Isometry3d local_to_head_in){
    local_to_head_ = local_to_head_in;
    pose_initialized_ = true;
  }

  Eigen::Vector3d getHeadLinearRate(){ return head_lin_rate_; }
  Eigen::Vector3d getHeadRotationRate(){ return head_rot_rate_; }

  void publishPose(int64_t utime, std::string channel, Eigen::Isometry3d pose,
                   Eigen::Vector3d vel_lin, Eigen::Vector3d vel_ang);
  void publishUpdate(int64_t utime, Eigen::Isometry3d local_to_head, std::string channel, bool output_alpha_filter);

private:
  boost::shared_ptr<lcm::LCM> lcm_;
  pronto_vis* pc_vis_;

  // have we received the first pose estimate:?
  bool pose_initialized_;
  bool vo_initialized_;

  BotFrames* botframes_;
  bot::frames* botframes_cpp_;

  std::string channel_extension_;
  Eigen::Isometry3d camera_to_head_;
  Eigen::Isometry3d local_to_head_;

  Eigen::Isometry3d local_to_head_prev_;
  Eigen::Isometry3d delta_head_prev_;

  // Cache of rates: All are stored as RPY
  Eigen::Vector3d head_rot_rate_, head_lin_rate_;
  Eigen::Vector3d head_rot_rate_alpha_, head_lin_rate_alpha_;

};

#endif

max_stars_repo_name: liangfok/oh-distro

max_issues_repo_name: liangfok/oh-distro

max_forks_repo_name: liangfok/oh-distro


text:
// Copyright Louis Dionne 2013-2017
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)

#include <boost/hana/assert.hpp>
#include <boost/hana/concept/struct.hpp>
#include <boost/hana/equal.hpp>
#include <boost/hana/fold_right.hpp>
#include <boost/hana/integral_constant.hpp>

#include "minimal_struct.hpp"
#include <laws/base.hpp>
#include <support/minimal_product.hpp>
namespace hana = boost::hana;
using hana::test::ct_eq;

template <int i = 0>
struct undefined { };

struct MoveOnly {
    MoveOnly()                           = default;
    MoveOnly(MoveOnly&&)                 = default;
    MoveOnly(MoveOnly const&)            = delete;
    MoveOnly& operator=(MoveOnly&&)      = default;
    MoveOnly& operator=(MoveOnly const&) = delete;
};

int main() {
    constexpr auto pair = ::minimal_product;
    ct_eq<999> s{};
    hana::test::_injection<0> f{};

    BOOST_HANA_CONSTANT_CHECK(hana::equal(
        hana::fold_right(obj(), s, undefined<>{}),
        s
    ));

    BOOST_HANA_CONSTANT_CHECK(hana::equal(
        hana::fold_right(obj(ct_eq<0>{}), s, f),
        f(pair(hana::int_c<0>, ct_eq<0>{}), s)
    ));

    BOOST_HANA_CONSTANT_CHECK(hana::equal(
        hana::fold_right(obj(ct_eq<0>{}, ct_eq<1>{}), s, f),
        f(pair(hana::int_c<0>, ct_eq<0>{}), f(pair(hana::int_c<1>, ct_eq<1>{}), s))
    ));

    BOOST_HANA_CONSTANT_CHECK(hana::equal(
        hana::fold_right(obj(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}), s, f),
        f(pair(hana::int_c<0>, ct_eq<0>{}),
            f(pair(hana::int_c<1>, ct_eq<1>{}),
                f(pair(hana::int_c<2>, ct_eq<2>{}), s)))
    ));

    // fold_right with move-only members
    hana::fold_right(obj(MoveOnly{}), 0, [](auto, int) { return 0; });
    hana::fold_right(obj(MoveOnly{}, MoveOnly{}), 0, [](auto, int) { return 0; });
}


text:
#include "stdafx.h"
#define WIN32_LEAN_AND_MEAN

#include "CppUnitTest.h"

#include <iostream>
#include <set>
#include <distant/process.hpp>
#include <distant/virtual_memory.hpp>
#include <distant/system.hpp>
#include <distant/snapshot.hpp>

#include <boost/range/algorithm.hpp>
#include <boost/range.hpp>
#include <VersionHelpers.h>

using namespace Microsoft::VisualStudio::CppUnitTestFramework;

namespace distant_unit_tests
{
	TEST_CLASS(remote_thread_tests)
	{
	private:
		void check_comparison_sanity(const distant::remote_thread& lhs, const distant::remote_thread& rhs)
		{
			const auto run = [](const auto& lhs, const auto& rhs)
			{
				Assert::IsTrue(lhs == rhs);
				Assert::IsTrue(!(lhs != rhs));
				Assert::IsFalse(lhs != rhs);
			};

			run(lhs, rhs);
			run(rhs, lhs);
		}

		void test_thread_snapshot_and_std_thread()
		{
			using distant::snapshot;
			using distant::remote_thread;
			bool good = false;

			try
			{
				const auto current_process = distant::current_process();

				std::vector<remote_thread> threads_vector;

				snapshot<remote_thread> before_snapshot(current_process);
				for (auto i = 0; i < 5; ++i)
				{
					threads_vector.emplace_back(std::thread([&good]()
					{
						while (!good)
							std::this_thread::sleep_for(std::chrono::milliseconds(0));
					}));
				}
				snapshot<remote_thread> after_snapshot(current_process);

				for (const auto& thread : threads_vector)
				{
					Assert::IsTrue(boost::find(before_snapshot, thread) == before_snapshot.end());
					Assert::IsTrue(boost::find(after_snapshot, thread) != after_snapshot.end());
				}

				good = true;
				for (auto&& thread : threads_vector)
				{
					if (thread.id() != std::this_thread::get_id())
						thread.join();
				}

				for (const auto& thread : threads_vector)
					Assert::IsTrue(boost::find(after_snapshot, thread) == after_snapshot.end());

			}
			catch (distant::winapi_error& e)
			{
				std::wstringstream out; out << e;
				Assert::Fail(out.str().c_str());
			}
			catch (std::exception& e)
			{
				std::wstringstream out; out << e.what();
				Assert::Fail(out.str().c_str());
			}
		}

	public:
		TEST_METHOD(remote_thread)
		{
			this->test_thread_snapshot_and_std_thread();

			const auto current_thread = distant::current_thread();
			this->check_comparison_sanity(current_thread, current_thread);
		}
	};
}

max_stars_repo_name: Ostoic/distant

max_issues_repo_name: Ostoic/distant

max_forks_repo_name: Ostoic/distant


text:
#ifndef TISSOT_ANALYZER_HPP
#define TISSOT_ANALYZER_HPP

// Tissot, converts projecton source code (Proj4) to Boost.Geometry
// (or potentially other source code)
//
// Copyright (c) 2015 Barend Gehrels, Amsterdam, the Netherlands.
//
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)

#include "tissot_structs.hpp"
#include "tissot_util.hpp"

#include <boost/foreach.hpp>

namespace boost { namespace geometry { namespace proj4converter
{

class proj4_analyzer
{
public :
    proj4_analyzer(projection_properties& prop, std::string const& group)
    : m_prop(prop)
    , m_group(group)
    {
    }

    void analyze()
    {
        BOOST_FOREACH(projection& proj, m_prop.projections)
        {
            proj.subgroup = m_group;
            assign_model(proj.direction, proj);
        }

        // Sort on: subgroup, model, direction
        std::sort(m_prop.projections.begin(), m_prop.projections.end());

        std::size_t n = m_prop.projections.size();
        for (size_t i = 0; i < n; i++)
        {
            projection& proj = m_prop.projections[i];
            if (proj.direction == "inverse" ||
                (i < n - 1 && m_prop.projections[i + 1].direction == "inverse"))
            {
                proj.has_inverse = true;
            }
            if (proj.model == "ellipsoid")
            {
                m_prop.has_ellipsoid = true;
            }
            else if (proj.model == "spheroid")
            {
                m_prop.has_spheroid = true;
            }
            else if (proj.model == "guam")
            {
                m_prop.has_guam = true;
            }
        }

        std::vector<model> models;
        std::string previous_model;
        BOOST_FOREACH(projection& proj, m_prop.projections)
        {
            if (proj.model != previous_model)
            {
                model m;
                m.name = proj.model;
                m.subgroup = proj.subgroup;
                m.has_inverse = proj.direction == "inverse";
                if (m_prop.has_spheroid && m_prop.has_ellipsoid)
                {
                    m.condition = m.name == "ellipsoid" ? "if (par.es)" : "else";
                }
                models.push_back(m);
            }
            else if (proj.direction == "inverse")
            {
                models.back().has_inverse = true;
            }
            previous_model = proj.model;
        }

        // Copy the models separately to all derived projections - some of them
        // might be deleted later if not supported
        BOOST_FOREACH(derived& der, m_prop.derived_projections)
        {
            der.models = models;
        }
    }

private :

    bool check_model(std::string term, std::string const& prefix,
            const std::string& direction, std::string const& model,
            projection& proj)
    {
        // Default case, e.g. e_forward, s_forward, etc
        if (term == prefix + "_" + direction)
        {
            proj.model = model;
            return true;
        }

        // e.g. for healpix, e_healpix_forward, etc
        if (term == prefix + "_" +  m_group + "_" + direction)
        {
            proj.model = model;
            proj.subgroup = m_group;
            return true;
        }

        // e.g. for healpix, e_healpix_forward, etc
        if (term == prefix + "_r" + m_group + "_" + direction)
        {
            proj.model = model;
            proj.subgroup = "r" + m_group;
            return true;
        }

        // For e.g. gaum ("e_gaum_fwd")
        if (boost::ends_with(term, "inv"))
        {
            boost::replace_last(term, "inv", "inverse");
        }
        if (boost::ends_with(term, "fwd"))
        {
           boost::replace_last(term, "fwd", "forward");
        }

        if (term == prefix + "_" + model + "_" + direction) // e.g. e_gaum_forward
        {
            proj.model = model;
            return true;
        }

        return false;
    }

    bool assign_model(std::string direction, projection& proj)
    {
        std::string term = proj.raw_model;
        boost::replace_all(term, boost::to_upper_copy(direction), "");
        if (direction == "special_factors")
        {
            boost::replace_all(term, "INVERSE", "");
            direction = "inverse";
        }
        boost::replace_all(term, "(", "");
        boost::replace_all(term, ")", "");
        boost::replace_all(term, ";", "");

        boost::trim(term);

        if (check_model(term, "e", direction, "ellipsoid", proj)
            || check_model(term, "s", direction, "spheroid", proj)
            || check_model(term, "o", direction, "oblique", proj)
            || check_model(term, "t", direction, "transverse", proj)
            || check_model(term, "e", direction, "guam", proj))
        {
            return true;
        }
        else if (term == direction)
        {
            proj.model = "other";
            return true;
        }

        std::cerr << "ERROR IN MODEL " << term << std::endl;
        proj.model = "ERROR";
        return false;
    }

    projection_properties& m_prop;
    std::string m_group;
};

}}} // namespace boost::geometry::proj4converter

#endif // TISSOT_ANALYZER_HPP

max_stars_repo_name: barendgehrels/tissot

max_issues_repo_name: barendgehrels/tissot

max_forks_repo_name: barendgehrels/tissot


text:
//          Copyright Oliver Kowalke 2014.
// Distributed under the Boost Software License, Version 1.0.
//    (See accompanying file LICENSE_1_0.txt or copy at
//          http://www.boost.org/LICENSE_1_0.txt)

#ifndef BOOST_COROUTINES2_DETAIL_DECAY_COPY_H
#define BOOST_COROUTINES2_DETAIL_DECAY_COPY_H

#include <type_traits>

#include <boost/config.hpp>

#include <boost/context/detail/config.hpp>

#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
#endif

namespace boost {
namespace coroutines2 {
namespace detail {

template< typename T >
typename std::decay< T >::type
decay_copy( T && t) {
    return std::forward< T >( t);
}

}}}

#ifdef BOOST_HAS_ABI_HEADERS
#include BOOST_ABI_SUFFIX
#endif

#endif // BOOST_COROUTINES2_DETAIL_DECAY_COPY_H

max_stars_repo_name: rudylee/expo

max_issues_repo_name: rudylee/expo

max_forks_repo_name: rudylee/expo


text:
// Copyright (c) 2012-2017 VideoStitch SAS
// Copyright (c) 2018 stitchEm

#ifndef __BOUNDEDVALUE__
#define __BOUNDEDVALUE__

#include <array>
#include <memory>
#include <Eigen/Dense>

namespace VideoStitch {
namespace Calibration {

/**
@brief A bounded value is a value (real scalar) which is forced to lie on a bounded domain.
@details We use a 2D rotation matrix. This matrix is the "optimized" content.
@details This rotation matrix rotates the vector (0; 1).
@details Keeping only the X value, the initial domain is [-1;1].
@details This is then scaled and shifted so the final domain is [min;max]
*/
class BoundedValue {
 public:
  BoundedValue();
  virtual ~BoundedValue();

  /**
  @brief Returns whether the BoundedValue is constant
  */
  bool isConstant() const;

  /**
  @brief Set bounds to be min and max
  @param min the minimal allowed value
  @param max the maximal allowed value
  */
  void setBounds(double min, double max);

  /**
  @brief Estimate the double scalar from the matrix
  @return estimated value
  */
  double getValue() const;

  /**
  @brief Jacobian of value wrt matrix
  @param J the jacobian updated
  */
  void getJacobian(Eigen::Matrix<double, 1, 4> &J) const;

  /**
  @brief Update the rotation matrix so that the estimated value is val
  @param val the updated value
  */
  void setValue(double val);

  /**
  @brief Retrieve the content of the rotation matrix
  @return pointer to rotation matrix
  */
  double *getMinimizerPtr() const;

  /**
  @brief Update the content of the rotation matrix
  @param ptr the rotation matrix content to use
  */
  void setMinimizerValues(const double *ptr);

  /**
  @brief Tie the bounded value to another one (i.e. will share the underlying objects)
  @param other the other bounded value to be tied to
  */
  void tieTo(const BoundedValue &other);

  /**
  @brief Untie the bounded value (i.e. will have its own values independent from other objects)
  */
  void untie();

 private:
  double shift;
  double scale;
  std::shared_ptr<std::array<double, 4> > modifier;
};

}  // namespace Calibration
}  // namespace VideoStitch

#endif

max_stars_repo_name: tlalexander/stitchEm

max_issues_repo_name: doymcc/stitchEm

max_forks_repo_name: doymcc/stitchEm


text:
//  Copyright (c) 2007-2012 Hartmut Kaiser
//
//  Distributed under the Boost Software License, Version 1.0. (See accompanying
//  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

#if !defined(HPX_LCOS_FUTURE_CALLBACK_DEC_06_2008_1126AM)
#define HPX_LCOS_FUTURE_CALLBACK_DEC_06_2008_1126AM

#include <hpx/hpx_fwd.hpp>
#include <hpx/runtime/applier/applier.hpp>

#include <boost/bind.hpp>

///////////////////////////////////////////////////////////////////////////////
namespace hpx { namespace lcos
{
    ///////////////////////////////////////////////////////////////////////////
    template <typename Future>
    class future_callback
    {
    public:
        typedef typename Future::result_type result_type;
        typedef HPX_STD_FUNCTION<void(result_type const&)> callback_type;

        future_callback(Future const& future, callback_type cb)
        {
            hpx::applier::register_work(
                boost::bind(&future_callback::wait_for_future, future, cb),
                "future_callback");
        }

    private:
        // thread function for thread waiting on future
        static threads::thread_state
            wait_for_future(Future future, callback_type cb)
        {
            cb(future.get());
            return threads::terminated;
        }
    };

}}

#endif


text:
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Delaunay_triangulation_2.h>
#include <CGAL/Triangulation_vertex_base_with_info_2.h>
#include <Eigen/Dense>
#include <vtkPolyDataReader.h>
#include <vtkPolyDataWriter.h>
#include <vtkPolyData.h>
#include <vtkDoubleArray.h>
#include <vtkSmartPointer.h>
#include <functional>

typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
typedef K::Point_2 Point;
typedef CGAL::Triangulation_vertex_base_with_info_2<unsigned,K> Vb;
typedef CGAL::Triangulation_data_structure_2<Vb> Tds;
typedef CGAL::Delaunay_triangulation_2<K,Tds> Delaunay;
typedef Delaunay::Face_circulator Face_circulator;
typedef Eigen::Vector3d Vector3d;
typedef Eigen::VectorXd VectorXd;
typedef Eigen::Matrix3d Matrix3d;
typedef Eigen::Matrix3Xd Matrix3Xd;
typedef Eigen::Map<Matrix3Xd> Map3Xd;

// New structure to store first ring neighbors of a vertex
struct vertex_first_ring{
    size_t vertex_id;
    std::vector< std::pair<unsigned,unsigned> > faces;
    std::vector< unsigned > edges;
};

int main(){
    clock_t t1;
    t1 = clock();
    for(auto i=0; i < 1; ++i){
        // *************************** Triangulation *************************//
        auto reader = vtkSmartPointer<vtkPolyDataReader>::New();
        reader->SetFileName("T7.vtk");
        reader->Update();
        auto poly = reader->GetOutput();
        auto N = poly->GetNumberOfPoints();
        auto pts = (double*) poly->GetPoints()->GetData()->GetVoidPointer(0);
        Map3Xd points(pts,3,N);

        // Project points to unit sphere
        points.colwise().normalize();

        // Reset the center of the sphere to origin by translating
        Vector3d center = points.rowwise().mean();
        points = points.colwise() - center;

        // Rotate all points so that the point in 0th column is along z-axis
        Vector3d c = points.col(0);
        double_t cos_t = c(2);
        double_t sin_t = std::sqrt( 1 - cos_t*cos_t );
        Vector3d axis;
        axis << c(1), -c(0), 0.;
        Matrix3d rotMat, axis_cross, outer;
        axis_cross << 0. , -axis(2), axis(1),
                        axis(2), 0., -axis(0),
                        -axis(1), axis(0), 0.;

        outer.noalias() = axis*axis.transpose();

        rotMat = cos_t*Matrix3d::Identity() + sin_t*axis_cross + (1-cos_t)*outer;
        Matrix3Xd rPts(3,N);
        rPts = rotMat*points; // The points on a sphere rotated

        // Calculate the stereographic projections
        Vector3d p0;
        Map3Xd l0( &(rPts(0,1)), 3, N-1 );
        Matrix3Xd l(3,N-1), proj(3,N-1);
        p0 << 0,0,-1;
        c = rPts.col(0);
        l = (l0.colwise() - c).colwise().normalized();
        for( auto j=0; j < N-1; ++j ){
            proj.col(j) = ((p0(2) - l0(2,j))/l(2,j))*l.col(j) + l0.col(j);
        }
        // Insert the projected points in a CGAL vertex_with_info vector
        std::vector< std::pair< Point, unsigned> > verts;
        for( auto j=0; j < N-1; ++j )
            verts.push_back(std::make_pair(Point(proj(0,j),proj(1,j)),j+1));

        Delaunay dt( verts.begin(), verts.end() );

        // Write the finite faces of the triangulation to a VTK file
        vtkNew<vtkCellArray> triangles;
        for( auto ffi = dt.finite_faces_begin(); ffi != dt.finite_faces_end(); ++ffi){
            triangles->InsertNextCell(3);
            for(auto j=2; j >= 0; --j)
                triangles->InsertCellPoint(ffi->vertex(j)->info());
        }

        // Iterate over infinite faces
        Face_circulator fc = dt.incident_faces(dt.infinite_vertex()), done3(fc);
        if (fc != 0) {
            do{
                triangles->InsertNextCell(3);
                for(auto j=2; j >= 0; --j){
                    auto vh = fc->vertex(j);
                    auto id = dt.is_infinite(vh)? 0 : vh->info();
                    triangles->InsertCellPoint(id);
                }
            }while(++fc != done3);
        }
        poly->SetPolys(triangles);

        // Write to VTK file
        vtkNew<vtkPolyDataWriter> writer;
        writer->SetFileName("CGALStereoMesh.vtk");
        writer->SetInputData(poly);
        writer->Write();

        // *************************** Our data structure *************************//
        std::vector<vertex_first_ring> first_ring;
        std::set<std::set<unsigned>> tri, edges;

        // Iterate over all vertices and collect first ring neighbors
        for(auto fvi = dt.all_vertices_begin(); fvi != dt.all_vertices_end(); ++fvi){

            vertex_first_ring vfr;
            std::vector<Delaunay::Vertex_handle> rvh;
            auto vid = dt.is_infinite(fvi)? 0 : fvi->info();
            vfr.vertex_id = vid;
            Delaunay::Edge_circulator ec = dt.incident_edges(fvi), done(ec);

            // Lambda function to get the vertex id for the edge
            auto getVertexId = [](int a, int b){
                std::set<int> index{0,1,2};
                index.erase(a);
                index.erase(b);
                return *index.begin();
            };

            if( ec != 0){
                do{

                    auto fh = ec->first;
                    auto edgeIndex = getVertexId(fh->index(fvi),ec->second);
                    auto verH = fh->vertex(edgeIndex);
                    auto edgeId = dt.is_infinite(verH)? 0 : verH->info();
                    std::set<unsigned> edge{vid,edgeId};
                    auto tryInsertEdge = edges.insert(edge);
                    if(tryInsertEdge.second){
                        vfr.edges.push_back(edgeId);
                        rvh.push_back(verH);
                    }

                }while(++ec != done);
            }

            // Check which edges form a unique face
            auto numEdges = rvh.size();
            for( auto k = 0; k < numEdges; ++k){
                auto next = (k+1) % numEdges;
                // Check if face is formed
                if(dt.is_face(fvi,rvh[k],rvh[next] )){
                    // Check if face is unique
                    std::set<unsigned> face{vid,vfr.edges[k],vfr.edges[next]};
                    auto tryInsertFace = tri.insert(face);
                    if(tryInsertFace.second)
                        vfr.faces.push_back(std::make_pair(k,next));
                }
            }

            first_ring.push_back(vfr);
        }

        //*************************** Print first ring ******************************//
        auto edgeNum = 0;
        auto faceNum = 0;
        for( const auto & vfr : first_ring){
            std::cout<<" Center Point = " << vfr.vertex_id << std::endl;
            std::cout<<"\t Faces = "<< std::endl;
            for(const auto & face : vfr.faces){
                std::cout<<"\t\t"<< face.first << " " << face.second << std::endl;
                faceNum++;
            }
            std::cout<<"\t Edges = "<< std::endl;
            for(const auto & edge : vfr.edges){
                std::cout<<"\t\t"<< edge << std::endl;
                edgeNum++;
            }
        }
        std::cout<< "Number of faces = " << faceNum << std::endl;
        std::cout<< "Number of edges = " << edgeNum << std::endl;
    }
    float diff((float)clock() - (float)t1);
    std::cout << "Time elapsed : " << diff / CLOCKS_PER_SEC
              << " seconds" << std::endl;
    return 0;
}

ext: cxx


text:
//==================================================================================================
/*!
  @file

  @copyright 2017 NumScale SAS

  Distributed under the Boost Software License, Version 1.0.
  (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
**/
//==================================================================================================
#ifndef BOOST_SIMD_ALGORITHM_COUNT_IF_HPP_INCLUDED
#define BOOST_SIMD_ALGORITHM_COUNT_IF_HPP_INCLUDED

#include <boost/simd/range/segmented_aligned_range.hpp>
#include <boost/simd/function/nbtrue.hpp>
#include <boost/simd/pack.hpp>
#include <algorithm>

namespace boost { namespace simd
{
  /*!
    @ingroup group-algo

    Returns he number of elements in the range [first,last)
    for which pred returns true.

    @param first  Beginning of the range of elements
    @param last   End of the range of elements
    @param pred  predicate to apply to each element.

    @par Requirement

      - @c first, @c last and @c out must be pointers to Vectorizable type.

    @par Example:

      @snippet count_if.cpp count_if

    @par Possible output:

      @snippet count_if.txt count_if

  **/

  template<typename T, typename Pred>
  typename std::iterator_traits<const T*>::difference_type
  count_if(T const* first, T const* last, Pred pred)
  {
    auto pr = segmented_aligned_range(first,last);

    auto c  = std::count_if(pr.head.begin(), pr.head.end(), pred);
    for(pack<T> x : pr.body) c+= nbtrue(pred(x));
         c += std::count_if(pr.tail.begin(), pr.tail.end(), pred);

    return c;
  }
} }

#endif

max_stars_repo_name: SylvainCorlay/pythran

max_issues_repo_name: SylvainCorlay/pythran

max_forks_repo_name: SylvainCorlay/pythran


text:
#include <boost/algorithm/string.hpp>
#include <locale>
#include <iostream>
#include <vector>

int main()
{
  std::locale::global(std::locale("German"));
  std::vector<std::string> v;
  v.push_back("Boris");
  v.push_back("Schäling");
  std::cout << boost::algorithm::join(v, " ") << std::endl;
}

max_stars_repo_path: Boost/The Boost C++ Libraries/src/5.3.5/main.cpp


text:
///////////////////////////////////////////////////////////////////////////////
// statistics::survival::data::data::record.hpp                              //
//                                                                           //
//  Copyright 2009 Erwann Rogard. Distributed under the Boost                //
//  Software License, Version 1.0. (See accompanying file                    //
//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)         //
///////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_STATISTICS_SURVIVAL_DATA_DATA_RECORDER_HPP_ER_2009
#define BOOST_STATISTICS_SURVIVAL_DATA_DATA_RECORDER_HPP_ER_2009
#include <ostream>
#include <limits>
#include <boost/operators.hpp>
#include <boost/format.hpp>
#include <boost/math/special_functions/fpclassify.hpp> //isinf
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/statistics/survival/constant.hpp>
#include <boost/statistics/survival/data/data/event.hpp>

namespace boost{
namespace statistics{
namespace survival{
namespace data{

// Abstraction for entry time (t) and the failure time (rt).
//
// If not set during initialization, the failure time can be set later.
template<typename T>
class record : less_than_comparable<record<T> >{
protected:
    typedef constant<T> const_;
public:
    typedef T value_type;
    record(); //inf,inf
    record(value_type t);
    record(value_type t, value_type rt);
    // default copy/assign
    void set_failure_time(value_type rt);
    value_type entry_time()const;
    value_type failure_time()const;

    template<typename Archive>
    void serialize(Archive & ar, const unsigned int version);

    bool operator<(const record& other)const;

protected:
    value_type entry_time_;     //t
    value_type failure_time_;   //rt
};

template<typename T>
std::ostream& operator<<(std::ostream& out,const record<T>& r);

template<typename T>
typename record<T>::value_type
time_since_entry(const record<T>& r, typename record<T>::value_type t);

// TODO is_at_risk

template<typename T>
event<T>  make_event(const record<T>& r, typename record<T>::value_type t);

    // Implementation //

// Construct
template<typename T>
record<T>::record():entry_time_(const_::inf_),failure_time_(const_::inf_){}

template<typename T>
record<T>::record(value_type t):entry_time_(t),failure_time_(const_::inf_){}

template<typename T>
record<T>::record(value_type t,value_type rt)
:entry_time_(t),failure_time_(rt){}

// Assign
template<typename T>
void record<T>::set_failure_time(value_type rt){
    static const char* method = "statistics::survival::record::set_failure_time(%1%)";
    if(math::isinf(this->failure_time_)){
        this->failure_time_ = rt;
    }else{
        static const char* err = " error : overriding failure time";
        throw exception(
            format(method,rt).str(),
            err,
            *this
        );
    }
}

template<typename T>
template<typename Archive>
void record<T>::serialize(Archive & ar, const unsigned int version){
    ar & entry_time_;
    ar & failure_time_;
}

// Access

template<typename T>
typename record<T>::value_type
record<T>::entry_time()const{ return entry_time_; }

template<typename T>
typename record<T>::value_type
record<T>::failure_time()const{ return failure_time_; }

template<typename T>
std::ostream& operator<<(std::ostream& out,const record<T>& r){
    out << '(' <<  r.entry_time() << ',' << r.failure_time() << ')';
    return out;
}

template<typename T>
bool record<T>::operator<(const record<T>& other)const{
    return ( (this->entry_time()) < other.entry_time() );
}

template<typename T>
typename record<T>::value_type
time_since_entry(const record<T>& r, typename record<T>::value_type t)
{
    //Warning may be <0
    return t-r.entry_time();
}

// TODO is_at_risk

template<typename T>
event<T>  make_event(const record<T>& r, typename record<T>::value_type t){
    static const char* fun = "statistics::survival::make_event(%1%,%2)";
    typedef typename record<T>::value_type value_t;
    value_t eps = math::tools::epsilon<T>();
    value_t dt = time_since_entry(r,t);
    if(dt>eps){
        typedef event<T> result_type;
        bool b = ( r.failure_time() <= dt );
        value_t rt = b ? r.failure_time() : dt;
        return result_type(b, rt);
    }else{
        static const char* err = "error: time_since_entry = %1%";
        format f(fun); f%r%t;
        std::string str = f.str();
        f = format(err); f%dt; str+= f.str();
        throw std::runtime_error( str );
    }
}

}// data
}// survival
}// statistics
}// boost

#endif


text:
// see LICENSE.txt

#pragma once

#include <graphene/app/application.hpp>

#include <boost/program_options.hpp>
#include <fc/io/json.hpp>

namespace graphene { namespace app {

class abstract_plugin
{
   public:
      virtual ~abstract_plugin(){}
      virtual std::string plugin_name()const = 0;

      /**
       * @brief Perform early startup routines and register plugin indexes, callbacks, etc.
       *
       * Plugins MUST supply a method initialize() which will be called early in the application startup. This method
       * should contain early setup code such as initializing variables, adding indexes to the database, registering
       * callback methods from the database, adding APIs, etc., as well as applying any options in the @ref options map
       *
       * This method is called BEFORE the database is open, therefore any routines which require any chain state MUST
       * NOT be called by this method. These routines should be performed in startup() instead.
       *
       * @param options The options passed to the application, via configuration files or command line
       */
      virtual void plugin_initialize( const boost::program_options::variables_map& options ) = 0;

      /**
       * @brief Begin normal runtime operations
       *
       * Plugins MUST supply a method startup() which will be called at the end of application startup. This method
       * should contain code which schedules any tasks, or requires chain state.
       */
      virtual void plugin_startup() = 0;

      /**
       * @brief Cleanly shut down the plugin.
       *
       * This is called to request a clean shutdown (e.g. due to SIGINT or SIGTERM).
       */
      virtual void plugin_shutdown() = 0;

      /**
       * @brief Register the application instance with the plugin.
       *
       * This is called by the framework to set the application.
       */
      virtual void plugin_set_app( application* a ) = 0;

      /**
       * @brief Fill in command line parameters used by the plugin.
       *
       * @param command_line_options All options this plugin supports taking on the command-line
       * @param config_file_options All options this plugin supports storing in a configuration file
       *
       * This method populates its arguments with any
       * command-line and configuration file options the plugin supports.
       * If a plugin does not need these options, it
       * may simply provide an empty implementation of this method.
       */
      virtual void plugin_set_program_options(
         boost::program_options::options_description& command_line_options,
         boost::program_options::options_description& config_file_options
         ) = 0;
};

/**
 * Provides basic default implementations of abstract_plugin functions.
 */

class plugin : public abstract_plugin
{
   public:
      plugin();
      virtual ~plugin() override;

      virtual std::string plugin_name()const override;
      virtual void plugin_initialize( const boost::program_options::variables_map& options ) override;
      virtual void plugin_startup() override;
      virtual void plugin_shutdown() override;
      virtual void plugin_set_app( application* app ) override;
      virtual void plugin_set_program_options(
         boost::program_options::options_description& command_line_options,
         boost::program_options::options_description& config_file_options
         ) override;

      chain::database& database() { return *app().chain_database(); }
      application& app()const { assert(_app); return *_app; }
   protected:
      net::node_ptr p2p_node() const { return app().p2p_node(); }

   private:
      application* _app = nullptr;
};

/// @group Some useful tools for boost::program_options arguments using vectors of JSON strings
/// @{
template<typename T>
T dejsonify(const string& s, uint32_t max_depth)
{
   return fc::json::from_string(s).as<T>(max_depth);
}

namespace impl {
   template<typename T>
   T dejsonify( const string& s )
   {
      return graphene::app::dejsonify<T>( s, GRAPHENE_MAX_NESTED_OBJECTS );
   }
}

#define DEFAULT_VALUE_VECTOR(value) default_value({fc::json::to_string(value)}, fc::json::to_string(value))
#define LOAD_VALUE_SET(options, name, container, type) \
if( options.count(name) > 0 ) { \
      const std::vector<std::string>& ops = options[name].as<std::vector<std::string>>(); \
      std::transform(ops.begin(), ops.end(), std::inserter(container, container.end()), &graphene::app::impl::dejsonify<type>); \
}
/// @}

} } //graphene::app

max_stars_repo_name: EDCBlockchain/blockchain