<commit_before>#include <llvm/IR/Constants.h>
#include <llvm/Support/Casting.h>

#include <algorithm>
#include <string>
#include <unordered_map>
#include <vector>

#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/IR/Module.h"
#include "llvm/Pass.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Transforms/IPO/PassManagerBuilder.h"

using namespace llvm;

namespace {

class ExplicitConsdes : public ModulePass {
   private:
    struct FunctionEntry {
        uint32_t priority;
        Value *function;
        Value *param;
    };

    static bool priorityAsc(const FunctionEntry &a, const FunctionEntry &b) {
        return a.priority < b.priority;
    }

    static bool priorityDesc(const FunctionEntry &a, const FunctionEntry &b) {
        return a.priority > b.priority;
    }

    void fillFromInitializer(std::vector<FunctionEntry> &target,
                             Constant *init) {
        auto *ty = init->getType();
        if (!ty->isArrayTy()) {
            errs() << "explicit-consdes: unexpected type of global var "
                      "initializer\n";
            return;
        }

        auto *inner = ty->getArrayElementType();
        if (inner->getStructNumElements() != 3 ||
            !inner->getStructElementType(0)->isIntegerTy() ||
            !inner->getStructElementType(1)
                 ->getPointerElementType()
                 ->isFunctionTy() ||
            !inner->getStructElementType(2)->isPointerTy()) {
            errs() << "explicit-consdes: unexpected type of element in global "
                      "var initializer\n";
            return;
        }

        for (unsigned i = 0; i < init->getType()->getArrayNumElements(); ++i) {
            // type { i32, void ()*, i8* }
            auto *elem = init->getAggregateElement(i);

            FunctionEntry entry{};
            entry.priority =
                dyn_cast<ConstantInt>(elem->getAggregateElement(0u))
                    ->getZExtValue();
            entry.function = elem->getAggregateElement(1);
            entry.param = elem->getAggregateElement(2);
            target.push_back(std::move(entry));
        }
    }

    void insertCalls(std::vector<FunctionEntry> &entries, Instruction *before) {
        Instruction *after = nullptr;

        for (auto &entry : entries) {
            auto *call = CallInst::Create(
                dyn_cast<FunctionType>(
                    entry.function->getType()->getPointerElementType()),
                entry.function, "");
            call->setDebugLoc(DebugLoc::get(0,0, before->getDebugLoc().getScope()));
            if (after) {
                call->insertAfter(after);
            } else {
                call->insertBefore(before);
            }
            after = call;
        }
    }

   public:
    static char ID;

    ExplicitConsdes() : ModulePass(ID) {}

    bool runOnModule(Module &mod) override {
        using std::sort;
        using std::tuple;
        using std::vector;

        bool change = false;

        vector<FunctionEntry> ctors, dtors;

        GlobalVariable *dtorsVar = nullptr;
        GlobalVariable *ctorsVar = nullptr;

        for (auto &glob : mod.globals()) {
            if (glob.hasName() && glob.getName() == "llvm.global_dtors") {
                fillFromInitializer(dtors, glob.getInitializer());
                dtorsVar = &glob;
            }

            if (glob.hasName() && glob.getName() == "llvm.global_ctors" &&
                glob.hasInitializer()) {
                fillFromInitializer(ctors, glob.getInitializer());
                ctorsVar = &glob;
            }
        }

        if (ctors.empty() && dtors.empty()) {
            return false;
        }

        // sort them to call order
        sort(ctors.begin(), ctors.end(), priorityAsc);
        sort(dtors.begin(), dtors.end(), priorityDesc);

        // call constructors at the beginning of main
        auto *main = mod.getFunction("main");
        auto *ctorsBefore =
            main->getEntryBlock().getFirstNonPHIOrDbgOrLifetime();
        insertCalls(ctors, ctorsBefore);

        vector<Instruction *> dtorsBefore;

        // search for returns in main
        for (auto &block : *main) {
            if (isa<ReturnInst>(block.getTerminator())) {
                dtorsBefore.push_back(block.getTerminator());
            }
        }

        // and finally search for calls to exit in whole program
        for (auto &func : mod.functions()) {
            for (auto &block : func) {
                for (auto &inst : block) {
                    if (auto *call = dyn_cast<CallInst>(&inst)) {
                        if (call->isIndirectCall()) continue;
                        Function *called = call->getCalledFunction();
                        if (!called) continue;
                        auto *ty = called->getType()->getPointerElementType();
                        if (called->hasName() && called->getName() == "exit" &&
                            ty->getFunctionNumParams() == 1 &&
                            ty->getFunctionParamType(0)->isIntegerTy()) {
                            dtorsBefore.push_back(call);
                        }
                    }
                }
            }
        }

        for (auto *before : dtorsBefore) {
            insertCalls(dtors, before);
        }

        if (ctorsVar) {
            ctorsVar->eraseFromParent();
        }
        if (dtorsVar) {
            dtorsVar->eraseFromParent();
        }

        return true;
    }
};

char ExplicitConsdes::ID = 0;
static RegisterPass<ExplicitConsdes> X(
    "explicit-consdes",
    "Insert explicit calls of module constructors and destructors",
    false /* Only looks at CFG */, false /* Analysis Pass */);

static RegisterStandardPasses Y(PassManagerBuilder::EP_EarlyAsPossible,
                                [](const PassManagerBuilder &Builder,
                                   legacy::PassManagerBase &PM) {
                                    PM.add(new ExplicitConsdes());
                                });
}  // namespace

<commit_msg>ExplicitConsdes: style fixes<commit_after>#include <llvm/IR/Constants.h>
#include <llvm/IR/InstIterator.h>
#include <llvm/Support/Casting.h>

#include <algorithm>
#include <string>
#include <unordered_map>
#include <vector>

#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/IR/Module.h"
#include "llvm/Pass.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Transforms/IPO/PassManagerBuilder.h"

using namespace llvm;

namespace {

class ExplicitConsdes : public ModulePass {
   private:
    struct FunctionEntry {
        uint32_t priority;
        Value *function;
        Value *param;
    };

    static bool priorityAsc(const FunctionEntry &a, const FunctionEntry &b) {
        return a.priority < b.priority;
    }

    static bool priorityDesc(const FunctionEntry &a, const FunctionEntry &b) {
        return a.priority > b.priority;
    }

    void fillFromInitializer(std::vector<FunctionEntry> &target,
                             Constant *init) {
        auto *ty = init->getType();
        if (!ty->isArrayTy()) {
            errs() << "explicit-consdes: unexpected type of global var "
                      "initializer\n";
            return;
        }

        auto *inner = ty->getArrayElementType();
        if (inner->getStructNumElements() != 3 ||
            !inner->getStructElementType(0)->isIntegerTy() ||
            !inner->getStructElementType(1)
                 ->getPointerElementType()
                 ->isFunctionTy() ||
            !inner->getStructElementType(2)->isPointerTy()) {
            errs() << "explicit-consdes: unexpected type of element in global "
                      "var initializer\n";
            return;
        }

        for (unsigned i = 0; i < init->getType()->getArrayNumElements(); ++i) {
            // type { i32, void ()*, i8* }
            auto *elem = init->getAggregateElement(i);

            FunctionEntry entry{};
            entry.priority =
                dyn_cast<ConstantInt>(elem->getAggregateElement(0u))
                    ->getZExtValue();
            entry.function = elem->getAggregateElement(1);
            entry.param = elem->getAggregateElement(2);
            target.push_back(std::move(entry));
        }
    }

    void insertCalls(std::vector<FunctionEntry> &entries, Instruction *before) {
        Instruction *after = nullptr;

        for (auto &entry : entries) {
            auto *call = CallInst::Create(
                dyn_cast<FunctionType>(
                    entry.function->getType()->getPointerElementType()),
                entry.function, "");
            call->setDebugLoc(DebugLoc::get(0,0, before->getDebugLoc().getScope()));
            if (after) {
                call->insertAfter(after);
            } else {
                call->insertBefore(before);
            }
            after = call;
        }
    }

   public:
    static char ID;

    ExplicitConsdes() : ModulePass(ID) {}

    bool runOnModule(Module &mod) override {
        using std::sort;
        using std::tuple;
        using std::vector;

        bool change = false;

        vector<FunctionEntry> ctors, dtors;

        GlobalVariable *dtorsVar = nullptr;
        GlobalVariable *ctorsVar = nullptr;

        for (auto &glob : mod.globals()) {
            if (glob.hasName() && glob.getName() == "llvm.global_dtors") {
                fillFromInitializer(dtors, glob.getInitializer());
                dtorsVar = &glob;
            }

            if (glob.hasName() && glob.getName() == "llvm.global_ctors" &&
                glob.hasInitializer()) {
                fillFromInitializer(ctors, glob.getInitializer());
                ctorsVar = &glob;
            }
        }

        if (ctors.empty() && dtors.empty()) {
            return false;
        }

        // sort them to call order
        sort(ctors.begin(), ctors.end(), priorityAsc);
        sort(dtors.begin(), dtors.end(), priorityDesc);

        // call constructors at the beginning of main
        auto *main = mod.getFunction("main");
        auto *ctorsBefore =
            main->getEntryBlock().getFirstNonPHIOrDbgOrLifetime();
        insertCalls(ctors, ctorsBefore);

        vector<Instruction *> dtorsBefore;

        // search for returns in main
        for (auto &block : *main) {
            if (isa<ReturnInst>(block.getTerminator())) {
                dtorsBefore.push_back(block.getTerminator());
            }
        }

        // and finally search for calls to exit in whole program
        for (auto &func : mod.functions()) {
            for (auto &inst : instructions(func)) {
                auto *call = dyn_cast<CallInst>(&inst);
                if (!call)
                    continue;

                if (call->isIndirectCall())
                    continue;

                Function *called = call->getCalledFunction();
                if (!called)
                    continue;

                auto *ty = called->getType()->getPointerElementType();
                if (called->hasName() && called->getName() == "exit" &&
                    ty->getFunctionNumParams() == 1 &&
                    ty->getFunctionParamType(0)->isIntegerTy()) {
                    dtorsBefore.push_back(call);
                }
            }
        }

        for (auto *before : dtorsBefore) {
            insertCalls(dtors, before);
        }

        if (ctorsVar) {
            ctorsVar->eraseFromParent();
        }
        if (dtorsVar) {
            dtorsVar->eraseFromParent();
        }

        return true;
    }
};

char ExplicitConsdes::ID = 0;
static RegisterPass<ExplicitConsdes> X(
    "explicit-consdes",
    "Insert explicit calls of module constructors and destructors",
    false /* Only looks at CFG */, false /* Analysis Pass */);

static RegisterStandardPasses Y(PassManagerBuilder::EP_EarlyAsPossible,
                                [](const PassManagerBuilder &Builder,
                                   legacy::PassManagerBase &PM) {
                                    PM.add(new ExplicitConsdes());
                                });
}  // namespace

<|endoftext|>


<commit_before>#include "TFile.h"
#include "TTree.h"
#include "TTreeReader.h"
#include "TTreeReaderArray.h"

#include "gtest/gtest.h"

#include "data.h"

#include <fstream>

TEST(TTreeReaderArray, MultiReaders) {
   // See https://root.cern.ch/phpBB3/viewtopic.php?f=3&t=22790
   TTree* tree = new TTree("TTreeReaderArrayTree", "In-memory test tree");
   double Double[6] = {42.f, 43.f, 44.f, 45.f, 46.f, 47.f};
   tree->Branch("D", &Double, "D[4]/D");

   tree->Fill();
   tree->Fill();
   tree->Fill();

   TTreeReader TR(tree);
   TTreeReaderArray<double> trDouble0(TR, "D");
   TTreeReaderArray<double> trDouble1(TR, "D");
   TTreeReaderArray<double> trDouble2(TR, "D");
   TTreeReaderArray<double> trDouble3(TR, "D");
   TTreeReaderArray<double> trDouble4(TR, "D");
   TTreeReaderArray<double> trDouble5(TR, "D");

   TR.SetEntry(1);

   EXPECT_EQ(4u, trDouble0.GetSize());
   EXPECT_EQ(4u, trDouble1.GetSize());
   EXPECT_EQ(4u, trDouble2.GetSize());
   EXPECT_EQ(4u, trDouble3.GetSize());
   EXPECT_EQ(4u, trDouble4.GetSize());
   EXPECT_EQ(4u, trDouble5.GetSize());
   for (int i = 0; i < 4; ++i) {
      EXPECT_DOUBLE_EQ(Double[i], trDouble0[i]);
      EXPECT_DOUBLE_EQ(Double[i], trDouble1[i]);
      EXPECT_DOUBLE_EQ(Double[i], trDouble2[i]);
      EXPECT_DOUBLE_EQ(Double[i], trDouble3[i]);
      EXPECT_DOUBLE_EQ(Double[i], trDouble4[i]);
      EXPECT_DOUBLE_EQ(Double[i], trDouble5[i]);
   }
}
<commit_msg>Remove unused include.<commit_after>#include "TFile.h"
#include "TTree.h"
#include "TTreeReader.h"
#include "TTreeReaderArray.h"

#include "gtest/gtest.h"

#include <fstream>

TEST(TTreeReaderArray, MultiReaders) {
   // See https://root.cern.ch/phpBB3/viewtopic.php?f=3&t=22790
   TTree* tree = new TTree("TTreeReaderArrayTree", "In-memory test tree");
   double Double[6] = {42.f, 43.f, 44.f, 45.f, 46.f, 47.f};
   tree->Branch("D", &Double, "D[4]/D");

   tree->Fill();
   tree->Fill();
   tree->Fill();

   TTreeReader TR(tree);
   TTreeReaderArray<double> trDouble0(TR, "D");
   TTreeReaderArray<double> trDouble1(TR, "D");
   TTreeReaderArray<double> trDouble2(TR, "D");
   TTreeReaderArray<double> trDouble3(TR, "D");
   TTreeReaderArray<double> trDouble4(TR, "D");
   TTreeReaderArray<double> trDouble5(TR, "D");

   TR.SetEntry(1);

   EXPECT_EQ(4u, trDouble0.GetSize());
   EXPECT_EQ(4u, trDouble1.GetSize());
   EXPECT_EQ(4u, trDouble2.GetSize());
   EXPECT_EQ(4u, trDouble3.GetSize());
   EXPECT_EQ(4u, trDouble4.GetSize());
   EXPECT_EQ(4u, trDouble5.GetSize());
   for (int i = 0; i < 4; ++i) {
      EXPECT_DOUBLE_EQ(Double[i], trDouble0[i]);
      EXPECT_DOUBLE_EQ(Double[i], trDouble1[i]);
      EXPECT_DOUBLE_EQ(Double[i], trDouble2[i]);
      EXPECT_DOUBLE_EQ(Double[i], trDouble3[i]);
      EXPECT_DOUBLE_EQ(Double[i], trDouble4[i]);
      EXPECT_DOUBLE_EQ(Double[i], trDouble5[i]);
   }
}
<|endoftext|>


<commit_before>#include "TLeaf.h"
#include "TROOT.h"
#include "TTree.h"
#include "TTreeReader.h"
#include "TTreeReaderValue.h"
#include "TTreeReaderArray.h"

#include "gtest/gtest.h"

TTree* MakeTree() {
   double x[3]{};
   unsigned int ny;
   int* y = nullptr;

   TTree* tree = new TTree("T", "test tree");
   tree->Branch("one", &x, "x/D[3]");
   tree->Branch("two", &ny, "ny/i");
   tree->Branch("three", &y, "y/I[ny]");

   x[1] = 42.;
   ny = 42;
   y = new int[42]{};
   y[0] = 17;
   tree->Fill();
   delete [] y;

   x[2] = 43.;
   ny = 5;
   y = new int[5]{};
   y[4] = 7;
   tree->Fill();
   delete [] y;

   tree->ResetBranchAddresses();

   return tree;
}

TEST(TTreeReaderBasic, Interfaces) {
   TTree* tree = MakeTree();

   TTreeReader tr(tree);
   TTreeReaderArray<double> x(tr, "one.x");
   TTreeReaderArray<int> y(tr, "three.y");
   TTreeReaderValue<unsigned int> ny(tr, "two.ny");

   // Before reading data:
   EXPECT_NE(tr.begin(), tr.end());
   //MISSING: EXPECT_EQ(2, tr.end() - tr.begin());
   EXPECT_EQ(-1, tr.GetCurrentEntry());
   EXPECT_EQ(2, tr.GetEntries(false));
   EXPECT_EQ(TTreeReader::kEntryNotLoaded, tr.GetEntryStatus());
   EXPECT_EQ(tree, tr.GetTree());
   EXPECT_FALSE(tr.IsChain());

   EXPECT_EQ(nullptr, ny.GetAddress());
   EXPECT_FALSE(ny.IsValid());
   EXPECT_STREQ("two.ny", ny.GetBranchName());
   EXPECT_EQ(ROOT::Internal::TTreeReaderValueBase::kReadNothingYet, ny.GetReadStatus());
   EXPECT_EQ(ROOT::Internal::TTreeReaderValueBase::kSetupNotSetup, ny.GetSetupStatus());
   EXPECT_EQ(ROOT::Internal::TTreeReaderValueBase::kReadNothingYet, ny.ProxyRead());

   // Skip to second entry:
   EXPECT_TRUE(tr.Next());
   EXPECT_TRUE(tr.Next());

   EXPECT_NE(tr.begin(), tr.end());
   //MISSING: EXPECT_EQ(2, tr.end() - tr.begin());
   EXPECT_EQ(1, tr.GetCurrentEntry());
   EXPECT_EQ(2, tr.GetEntries(false));

   EXPECT_EQ(5, *ny);
   EXPECT_NE(nullptr, ny.GetAddress());
   EXPECT_TRUE(ny.IsValid());
   EXPECT_EQ(ny.GetAddress(), ny.Get());
   EXPECT_STREQ("two", ny.GetBranchName());
   EXPECT_STREQ("ny", ny.GetLeaf()->GetName());
   EXPECT_EQ(ROOT::Internal::TTreeReaderValueBase::kReadSuccess, ny.GetReadStatus());
   EXPECT_EQ(ROOT::Internal::TTreeReaderValueBase::kSetupMatch, ny.GetSetupStatus());
   EXPECT_EQ(ROOT::Internal::TTreeReaderValueBase::kReadSuccess, ny.ProxyRead());

   //FAILS: EXPECT_EQ(3, x.GetSize());
   //FAILS: EXPECT_EQ(5, y.GetSize());
   //FAILS: EXPECT_DOUBLE_EQ(42., x[2]);
   //FAILS: EXPECT_EQ(7, y[4]);

   EXPECT_FALSE(tr.Next());
   //FAILS: EXPECT_FALSE(ny.IsValid());
}

TEST(TTreeReaderBasic, ErrorProbing) {
   TTreeReader tr("doesNotExist", gROOT);
   EXPECT_EQ(TTreeReader::kEntryNoTree, tr.GetEntryStatus());
   EXPECT_EQ(nullptr, tr.GetTree());

   tr.SetTree(nullptr);
   EXPECT_EQ(TTreeReader::kEntryNoTree, tr.GetEntryStatus());
   EXPECT_EQ(nullptr, tr.GetTree());
}

TEST(TTreeReaderBasic, Range) {
   TTree* tree = MakeTree();
   TTreeReader tr(tree);

   EXPECT_EQ(TTreeReader::kEntryValid, tr.SetEntriesRange(1, 1));
   EXPECT_EQ(0, tr.GetCurrentEntry());
   EXPECT_TRUE(tr.Next());
   EXPECT_EQ(1, tr.GetCurrentEntry());
   EXPECT_EQ(TTreeReader::kEntryValid, tr.GetEntryStatus());

   // Read beyond end:
   EXPECT_FALSE(tr.Next());
   EXPECT_EQ(TTreeReader::kEntryNotFound, tr.GetEntryStatus());
   EXPECT_EQ(1, tr.GetCurrentEntry());
}
<commit_msg>Fix signed / unsigned.<commit_after>#include "TLeaf.h"
#include "TROOT.h"
#include "TTree.h"
#include "TTreeReader.h"
#include "TTreeReaderValue.h"
#include "TTreeReaderArray.h"

#include "gtest/gtest.h"

TTree* MakeTree() {
   double x[3]{};
   unsigned int ny;
   int* y = nullptr;

   TTree* tree = new TTree("T", "test tree");
   tree->Branch("one", &x, "x/D[3]");
   tree->Branch("two", &ny, "ny/i");
   tree->Branch("three", &y, "y/I[ny]");

   x[1] = 42.;
   ny = 42;
   y = new int[42]{};
   y[0] = 17;
   tree->Fill();
   delete [] y;

   x[2] = 43.;
   ny = 5;
   y = new int[5]{};
   y[4] = 7;
   tree->Fill();
   delete [] y;

   tree->ResetBranchAddresses();

   return tree;
}

TEST(TTreeReaderBasic, Interfaces) {
   TTree* tree = MakeTree();

   TTreeReader tr(tree);
   TTreeReaderArray<double> x(tr, "one.x");
   TTreeReaderArray<int> y(tr, "three.y");
   TTreeReaderValue<unsigned int> ny(tr, "two.ny");

   // Before reading data:
   EXPECT_NE(tr.begin(), tr.end());
   //MISSING: EXPECT_EQ(2, tr.end() - tr.begin());
   EXPECT_EQ(-1, tr.GetCurrentEntry());
   EXPECT_EQ(2, tr.GetEntries(false));
   EXPECT_EQ(TTreeReader::kEntryNotLoaded, tr.GetEntryStatus());
   EXPECT_EQ(tree, tr.GetTree());
   EXPECT_FALSE(tr.IsChain());

   EXPECT_EQ(nullptr, ny.GetAddress());
   EXPECT_FALSE(ny.IsValid());
   EXPECT_STREQ("two.ny", ny.GetBranchName());
   EXPECT_EQ(ROOT::Internal::TTreeReaderValueBase::kReadNothingYet, ny.GetReadStatus());
   EXPECT_EQ(ROOT::Internal::TTreeReaderValueBase::kSetupNotSetup, ny.GetSetupStatus());
   EXPECT_EQ(ROOT::Internal::TTreeReaderValueBase::kReadNothingYet, ny.ProxyRead());

   // Skip to second entry:
   EXPECT_TRUE(tr.Next());
   EXPECT_TRUE(tr.Next());

   EXPECT_NE(tr.begin(), tr.end());
   //MISSING: EXPECT_EQ(2, tr.end() - tr.begin());
   EXPECT_EQ(1, tr.GetCurrentEntry());
   EXPECT_EQ(2, tr.GetEntries(false));

   EXPECT_EQ(5u, *ny);
   EXPECT_NE(nullptr, ny.GetAddress());
   EXPECT_TRUE(ny.IsValid());
   EXPECT_EQ(ny.GetAddress(), ny.Get());
   EXPECT_STREQ("two", ny.GetBranchName());
   EXPECT_STREQ("ny", ny.GetLeaf()->GetName());
   EXPECT_EQ(ROOT::Internal::TTreeReaderValueBase::kReadSuccess, ny.GetReadStatus());
   EXPECT_EQ(ROOT::Internal::TTreeReaderValueBase::kSetupMatch, ny.GetSetupStatus());
   EXPECT_EQ(ROOT::Internal::TTreeReaderValueBase::kReadSuccess, ny.ProxyRead());

   //FAILS: EXPECT_EQ(3, x.GetSize());
   //FAILS: EXPECT_EQ(5, y.GetSize());
   //FAILS: EXPECT_DOUBLE_EQ(42., x[2]);
   //FAILS: EXPECT_EQ(7, y[4]);

   EXPECT_FALSE(tr.Next());
   //FAILS: EXPECT_FALSE(ny.IsValid());
}

TEST(TTreeReaderBasic, ErrorProbing) {
   TTreeReader tr("doesNotExist", gROOT);
   EXPECT_EQ(TTreeReader::kEntryNoTree, tr.GetEntryStatus());
   EXPECT_EQ(nullptr, tr.GetTree());

   tr.SetTree(nullptr);
   EXPECT_EQ(TTreeReader::kEntryNoTree, tr.GetEntryStatus());
   EXPECT_EQ(nullptr, tr.GetTree());
}

TEST(TTreeReaderBasic, Range) {
   TTree* tree = MakeTree();
   TTreeReader tr(tree);

   EXPECT_EQ(TTreeReader::kEntryValid, tr.SetEntriesRange(1, 1));
   EXPECT_EQ(0, tr.GetCurrentEntry());
   EXPECT_TRUE(tr.Next());
   EXPECT_EQ(1, tr.GetCurrentEntry());
   EXPECT_EQ(TTreeReader::kEntryValid, tr.GetEntryStatus());

   // Read beyond end:
   EXPECT_FALSE(tr.Next());
   EXPECT_EQ(TTreeReader::kEntryNotFound, tr.GetEntryStatus());
   EXPECT_EQ(1, tr.GetCurrentEntry());
}
<|endoftext|>


<commit_before>#include "mongo_smasher.h"
#include <list>
#include <functional>
#include <fstream>
#include <cstdlib>
#include <exception>
#include <stdexcept>
#include <sstream>
#include <bsoncxx/json.hpp>
#include <bsoncxx/view_or_value.hpp>
#include <bsoncxx/document/value.hpp>
#include <bsoncxx/types/value.hpp>
#include <mongocxx/client.hpp>
#include <mongocxx/instance.hpp>
#include <boost/filesystem/path.hpp>
#include <cppformat/format.h>
#include <regex>
#include "logger.h"
#include "randomizer.h"
#include "process_unit.h"
#include "collection_consumer.h"
#include "collection_producer.h"
#include <chrono>
#include <thread>
#include <sstream>
#include <cppformat/format.h>
#include <iostream>

using namespace std;

namespace bsx = bsoncxx;
using str_view = bsoncxx::stdx::string_view;
using bsoncxx::stdx::make_unique;

namespace mongo_smasher {

template <>
typename enum_view_definition<frequency_type>::type
    enum_view_definition<frequency_type>::str_array = {"linear", "cyclic_gaussian", "sinusoidal"};

void run_stream(Config const& config) {
  // Load the file
  std::ifstream model_file_stream(config.model_file, std::ios::in | std::ios::binary);
  if (!model_file_stream) {
    log(log_level::fatal, "Cannot read file \"%s\".\n", config.model_file.c_str());
    return;
  }

  std::string root_path = boost::filesystem::path(config.model_file).parent_path().string();
  log(log_level::debug, "Path to search dictionaries is \"%s\"\n", root_path.c_str());

  std::string json_data;
  model_file_stream.seekg(0, std::ios::end);
  json_data.resize(model_file_stream.tellg());
  model_file_stream.seekg(0, std::ios::beg);
  model_file_stream.read(&json_data.front(), json_data.size());

  log(log_level::debug, "Json file contains:\n---\n%s\n---\n", json_data.c_str());

  // This parsed model must be kept alive til the end of run_stream
  // because objects use string_views pointing inside it
  // TODO: enforce it one way or another
  auto model = bsoncxx::from_json(json_data);
  log(log_level::debug, "Json data parsed successfully\n");
  auto view = model.view();

  // Building randomizer to cache the file contents
  Randomizer randomizer(view["values"].get_document().view(), root_path.data());

  // Connect to data base
  // TODO: Manage failures properly.
  std::string db_uri = fmt::format("mongodb://{}:{}", config.host, config.port);
  mongo_smasher::log(mongo_smasher::log_level::info, "Connecting to %s.\n", db_uri.c_str());
  // TODO add the logger here
  mongocxx::instance inst{};
  if (view["collections"].type() != bsx::type::k_document) {
    log(log_level::fatal, "what");
  }

  ThreadPilot pilot{};
  DocumentBatch::queue_t queue{100};

  // Create producers
  std::list<ThreadRunner<CollectionProducer>> producers;
  for (size_t i = 0; i < config.nb_producers; ++i) {
    producers.emplace_back(pilot, queue, view, root_path.data());
  }

  std::list<ThreadRunner<CollectionConsumer>> consumers;
  for (size_t i = 0; i < config.nb_consumers; ++i) {
    consumers.emplace_back(pilot, queue, db_uri);
  }

  for (;;) {
    size_t producers_idle{0};
    for (auto& t : producers) {
      producers_idle += t.hosted.measure_idle_time();
    }
    size_t consumers_idle{0};
    for (auto& t : consumers) {
      consumers_idle += t.hosted.measure_idle_time();
    }

    constexpr size_t const us_per_ms = 1e3;  // microseconds per milliseconds
    log(log_level::info, "Producers idle: %4lums, consumers idle: %4lums, queue size: %lu\n",
        producers_idle / us_per_ms, consumers_idle / us_per_ms, queue.size());
    std::this_thread::sleep_for(std::chrono::seconds{1});
  }

  for (auto& t : consumers) {
    t.thread.join();
  }

  for (auto& t : producers) {
    t.thread.join();
  }
};

}  // namespace mongo_smasher
<commit_msg>Remove biased first idle values.<commit_after>#include "mongo_smasher.h"
#include <list>
#include <functional>
#include <fstream>
#include <cstdlib>
#include <exception>
#include <stdexcept>
#include <sstream>
#include <bsoncxx/json.hpp>
#include <bsoncxx/view_or_value.hpp>
#include <bsoncxx/document/value.hpp>
#include <bsoncxx/types/value.hpp>
#include <mongocxx/client.hpp>
#include <mongocxx/instance.hpp>
#include <boost/filesystem/path.hpp>
#include <cppformat/format.h>
#include <regex>
#include "logger.h"
#include "randomizer.h"
#include "process_unit.h"
#include "collection_consumer.h"
#include "collection_producer.h"
#include <chrono>
#include <thread>
#include <sstream>
#include <cppformat/format.h>
#include <iostream>

using namespace std;

namespace bsx = bsoncxx;
using str_view = bsoncxx::stdx::string_view;
using bsoncxx::stdx::make_unique;

namespace mongo_smasher {

template <>
typename enum_view_definition<frequency_type>::type
    enum_view_definition<frequency_type>::str_array = {"linear", "cyclic_gaussian", "sinusoidal"};

void run_stream(Config const& config) {
  // Load the file
  std::ifstream model_file_stream(config.model_file, std::ios::in | std::ios::binary);
  if (!model_file_stream) {
    log(log_level::fatal, "Cannot read file \"%s\".\n", config.model_file.c_str());
    return;
  }

  std::string root_path = boost::filesystem::path(config.model_file).parent_path().string();
  log(log_level::debug, "Path to search dictionaries is \"%s\"\n", root_path.c_str());

  std::string json_data;
  model_file_stream.seekg(0, std::ios::end);
  json_data.resize(model_file_stream.tellg());
  model_file_stream.seekg(0, std::ios::beg);
  model_file_stream.read(&json_data.front(), json_data.size());

  log(log_level::debug, "Json file contains:\n---\n%s\n---\n", json_data.c_str());

  // This parsed model must be kept alive til the end of run_stream
  // because objects use string_views pointing inside it
  // TODO: enforce it one way or another
  auto model = bsoncxx::from_json(json_data);
  log(log_level::debug, "Json data parsed successfully\n");
  auto view = model.view();

  // Building randomizer to cache the file contents
  Randomizer randomizer(view["values"].get_document().view(), root_path.data());

  // Connect to data base
  // TODO: Manage failures properly.
  std::string db_uri = fmt::format("mongodb://{}:{}", config.host, config.port);
  mongo_smasher::log(mongo_smasher::log_level::info, "Connecting to %s.\n", db_uri.c_str());
  // TODO add the logger here
  mongocxx::instance inst{};
  if (view["collections"].type() != bsx::type::k_document) {
    log(log_level::fatal, "what");
  }

  ThreadPilot pilot{};
  DocumentBatch::queue_t queue{100};

  // Create producers
  std::list<ThreadRunner<CollectionProducer>> producers;
  for (size_t i = 0; i < config.nb_producers; ++i) {
    producers.emplace_back(pilot, queue, view, root_path.data());
  }

  std::list<ThreadRunner<CollectionConsumer>> consumers;
  for (size_t i = 0; i < config.nb_consumers; ++i) {
    consumers.emplace_back(pilot, queue, db_uri);
  }

  size_t nb_loops{0};
  for (;;) {
    size_t producers_idle{0};
    for (auto& t : producers) {
      producers_idle += t.hosted.measure_idle_time();
    }
    size_t consumers_idle{0};
    for (auto& t : consumers) {
      consumers_idle += t.hosted.measure_idle_time();
    }

    constexpr size_t const us_per_ms = 1e3;  // microseconds per milliseconds
    // Drops the first line of idle : value are hugely biased by the cache filling
    if (nb_loops)
      log(log_level::info, "Producers idle: %4lums, consumers idle: %4lums, queue size: %lu\n",
          producers_idle / us_per_ms, consumers_idle / us_per_ms, queue.size());
    std::this_thread::sleep_for(std::chrono::seconds{1});
    ++nb_loops;
  }

  for (auto& t : consumers) {
    t.thread.join();
  }

  for (auto& t : producers) {
    t.thread.join();
  }
};

}  // namespace mongo_smasher
<|endoftext|>


<commit_before>
//snippet-sourcedescription:[update_item.cpp demonstrates how to update an item in an Amazon DynamoDB table.]
//snippet-keyword:[C++]
//snippet-keyword:[Code Sample]
//snippet-keyword:[Amazon DynamoDB]
//snippet-service:[dynamodb]
//snippet-sourcetype:[full-example]
//snippet-sourcedate:[]
//snippet-sourceauthor:[AWS]

/*
Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.

This file is licensed under the Apache License, Version 2.0 (the "License").
You may not use this file except in compliance with the License. A copy of
the License is located at

http://aws.amazon.com/apache2.0/

This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied. See the License for the
specific language governing permissions and limitations under the License.
*/
//snippet-start:[dynamodb.cpp.update_item.inc]
#include <aws/core/Aws.h>
#include <aws/core/utils/Outcome.h>
#include <aws/dynamodb/DynamoDBClient.h>
#include <aws/dynamodb/model/UpdateItemRequest.h>
#include <aws/dynamodb/model/UpdateItemResult.h>
#include <iostream>
//snippet-end:[dynamodb.cpp.update_item.inc]

/**
* Update a DynamoDB item in a table.
*
* Takes the name of the table, an item to update (primary key value), and the
* greeting to update it with.
*
* The primary key used is "Name", and the greeting will be added to the
* "Greeting" field.
*
* This code expects that you have AWS credentials set up per:
* http://docs.aws.amazon.com/sdk-for-cpp/v1/developer-guide/credentials.html
*/
int main(int argc, char** argv)
{
    const std::string USAGE = "\n" \
        "Usage:\n"
        "    update_item <table> <name> <fld:val> ..\n\n"
        "Where:\n"
        "    table    - the table to put the item in.\n"
        "    name     - a name to update\n"
        "    fld:val  - field name:new updated value pairs\n\n"
        "Additional fields can be specified by appending them to the end of the\n"
        "input.\n\n"
        "Examples:\n"
        "    update_item SiteColors text default:000000 bold:b22222\n"
        "    update_item SiteColors background default:eeeeee code:d3d3d3\n\n";

    if (argc < 3)
    {
        std::cout << USAGE;
        return 1;
    }

    Aws::SDKOptions options;
    Aws::InitAPI(options);
    {
        const Aws::String table(argv[1]);
        const Aws::String name(argv[2]);

        // snippet-start:[dynamodb.cpp.update_item.code]
        Aws::Client::ClientConfiguration clientConfig;
        Aws::DynamoDB::DynamoDBClient dynamoClient(clientConfig);

        Aws::DynamoDB::Model::UpdateItemRequest uir;
        uir.SetTableName(table);

        Aws::DynamoDB::Model::AttributeValue av;
        av.SetS(name);
        uir.AddKey("Name", av);

        for (int x = 3; x < argc; x++)
        {
            const Aws::String arg(argv[x]);
            const Aws::Vector<Aws::String>& flds = Aws::Utils::StringUtils::Split(arg, ':');
            if (flds.size() == 2)
            {
                Aws::DynamoDB::Model::AttributeValue val;
                val.SetS(flds[1]);
                Aws::DynamoDB::Model::AttributeValueUpdate avu;
                avu.SetValue(val);
                uir.AddAttributeUpdates(flds[0], avu);
            }
            else
            {
                std::cout << "Invalid argument: " << arg << std::endl << USAGE;
                return 1;
            }
        }

        const Aws::DynamoDB::Model::UpdateItemOutcome& result = dynamoClient.UpdateItem(uir);
        if (!result.IsSuccess())
        {
            std::cout << result.GetError().GetMessage() << std::endl;
            return 1;
        }
        std::cout << "Done!" << std::endl;
        // snippet-end:[dynamodb.cpp.update_item.code]
    }
    Aws::ShutdownAPI(options);
    return 0;
}<commit_msg>Modify C++ update_item.cpp to use an update expression<commit_after>
//snippet-sourcedescription:[update_item.cpp demonstrates how to update an item in an Amazon DynamoDB table.]
//snippet-service:[dynamodb]
//snippet-keyword:[Amazon DynamoDB]
//snippet-keyword:[C++]
//snippet-keyword:[Code Sample]
//snippet-sourcetype:[full-example]
//snippet-sourcedate:[05-24-2019]
//snippet-sourceauthor:[AWS]

/*
Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.

This file is licensed under the Apache License, Version 2.0 (the "License").
You may not use this file except in compliance with the License. A copy of
the License is located at

http://aws.amazon.com/apache2.0/

This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied. See the License for the
specific language governing permissions and limitations under the License.
*/
//snippet-start:[dynamodb.cpp.update_item.inc]
#include <aws/core/Aws.h>
#include <aws/core/utils/Outcome.h>
#include <aws/dynamodb/DynamoDBClient.h>
#include <aws/dynamodb/model/UpdateItemRequest.h>
#include <aws/dynamodb/model/UpdateItemResult.h>
#include <iostream>
//snippet-end:[dynamodb.cpp.update_item.inc]

/**
 * Update a DynamoDB table item
 *
 * Accepts the table name, the key value to update, the attribute name
 * to update, and the new attribute value. If an attribute of the specified
 * name does not exist, it is added to the key value.
 *
 * The specified table must have a key called "Name".
 *
 * The example code only sets/updates an attribute value. It processes
 * the attribute value as a string, even if the value could be interpreted
 * as a number. Also, the example code does not remove an existing attribute
 * from the key value. Adding support for number values or removal of an
 * attribute would require simple modifications that should be self-evident.
 */
int main(int argc, char** argv)
{
    const std::string USAGE = "\n"
        "Usage:\n"
        "    update_item <tableName> <keyValue> <attribute=value> ..\n\n"
        "Where:\n"
        "    tableName       - name of the table to put the item in\n"
        "    keyValue        - the key value to update\n"
        "    attribute=value - attribute=updated value\n\n"
        "Examples:\n"
        "    update_item SiteColors text default=000000\n"
        "    update_item SiteColors background code=d3d3d3\n\n";

    if (argc < 4)
    {
        std::cout << USAGE;
        return 1;
    }

    Aws::SDKOptions options;
    Aws::InitAPI(options);
    {
        const Aws::String tableName(argv[1]);
        const Aws::String keyValue(argv[2]);
        const Aws::String attributeNameAndValue(argv[3]);

        // snippet-start:[dynamodb.cpp.update_item.code]
        Aws::Client::ClientConfiguration clientConfig;
        Aws::DynamoDB::DynamoDBClient dynamoClient(clientConfig);

        // *** Define UpdateItem request arguments
        // Define TableName argument
        Aws::DynamoDB::Model::UpdateItemRequest request;
        request.SetTableName(tableName);

        // Define KeyName argument
        Aws::DynamoDB::Model::AttributeValue attribValue;
        attribValue.SetS(keyValue);
        request.AddKey("Name", attribValue);

        // Construct the SET update expression argument
        Aws::String update_expression("SET #a = :valueA");
        request.SetUpdateExpression(update_expression);

        // Parse the attribute name and value. Syntax: "name=value"
        auto parsed = Aws::Utils::StringUtils::Split(attributeNameAndValue, '=');
        // parsed[0] == attribute name, parsed[1] == attribute value
        if (parsed.size() != 2)
        {
            std::cout << "Invalid argument syntax: " << attributeNameAndValue << USAGE;
            return 1;
        }

        // Construct attribute name argument
        // Note: Setting the ExpressionAttributeNames argument is required only
        // when the name is a reserved word, such as "default". Otherwise, the
        // name can be included in the update_expression, as in
        // "SET MyAttributeName = :valueA"
        Aws::Map<Aws::String, Aws::String> expressionAttributeNames;
        expressionAttributeNames["#a"] = parsed[0];
        request.SetExpressionAttributeNames(expressionAttributeNames);

        // Construct attribute value argument
        Aws::DynamoDB::Model::AttributeValue attributeUpdatedValue;
        attributeUpdatedValue.SetS(parsed[1]);
        Aws::Map<Aws::String, Aws::DynamoDB::Model::AttributeValue> expressionAttributeValues;
        expressionAttributeValues[":valueA"] = attributeUpdatedValue;
        request.SetExpressionAttributeValues(expressionAttributeValues);

        // Update the item
        const Aws::DynamoDB::Model::UpdateItemOutcome& result = dynamoClient.UpdateItem(request);
        if (!result.IsSuccess())
        {
            std::cout << result.GetError().GetMessage() << std::endl;
            return 1;
        }
        std::cout << "Item was updated" << std::endl;
        // snippet-end:[dynamodb.cpp.update_item.code]
    }
    Aws::ShutdownAPI(options);
    return 0;
}<|endoftext|>


<commit_before>#include <random>

#include <DO/Sara/Graphics.hpp>

GRAPHICS_MAIN()
{
  using namespace std;
  using namespace DO::Sara;

  // Uniform distributions.
  auto rng = std::mt19937{};
  auto uni_0_255 = std::uniform_int_distribution<unsigned char>{};
  auto uni_0_300 = std::uniform_int_distribution<int>{0, 300};

  auto uniform_color_dist = [&]() {
    return Color3ub{uni_0_255(rng), uni_0_255(rng), uni_0_255(rng)};
  };

  // Create a white image and display it on a window.
  auto image = Image<Rgb8>{300, 300};
  image.flat_array().fill(White8);

  create_window(300, 300);
  display(image);
  get_key();

  // Draw random colors on an image surface.
  for (auto y = 0; y < image.height(); ++y)
    for (auto x = 0; x < image.width(); ++x)
      draw_point(image, x, y, uniform_color_dist());

  display(image);
  get_key();

  // Display random rectangles.
  image.flat_array().fill(White8);
  display(image);
  get_key();

  for (int i = 0; i < 10; ++i)
  {
    const auto x = uni_0_300(rng);
    const auto y = uni_0_300(rng);
    const auto w = uni_0_300(rng);
    const auto h = uni_0_300(rng);
    fill_rect(image, x, y, w, h, uniform_color_dist());
  }

  display(image);
  get_key();
  close_window();

  return 0;
}
<commit_msg>MAINT: fix compilation error with VS 2015.<commit_after>#include <random>

#include <DO/Sara/Graphics.hpp>

GRAPHICS_MAIN()
{
  using namespace std;
  using namespace DO::Sara;

  // Uniform distributions.
  auto rng = std::mt19937{};
  auto uni_0_255 = std::uniform_int_distribution<>{0, 255};
  auto uni_0_300 = std::uniform_int_distribution<>{0, 300};

  auto uniform_color_dist = [&]() {
    return Color3ub(uni_0_255(rng), uni_0_255(rng), uni_0_255(rng));
  };

  // Create a white image and display it on a window.
  auto image = Image<Rgb8>{300, 300};
  image.flat_array().fill(White8);

  create_window(300, 300);
  display(image);
  get_key();

  // Draw random colors on an image surface.
  for (auto y = 0; y < image.height(); ++y)
    for (auto x = 0; x < image.width(); ++x)
      draw_point(image, x, y, uniform_color_dist());

  display(image);
  get_key();

  // Display random rectangles.
  image.flat_array().fill(White8);
  display(image);
  get_key();

  for (int i = 0; i < 10; ++i)
  {
    const auto x = uni_0_300(rng);
    const auto y = uni_0_300(rng);
    const auto w = uni_0_300(rng);
    const auto h = uni_0_300(rng);
    fill_rect(image, x, y, w, h, uniform_color_dist());
  }

  display(image);
  get_key();
  close_window();

  return 0;
}
<|endoftext|>


<commit_before>// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.

#include <gtest/gtest.h>

#include <string>

#include "parquet/column/properties.h"
#include "parquet/file/reader.h"

namespace parquet {

namespace test {

TEST(TestReaderProperties, Basics) {
  ReaderProperties props;

  ASSERT_EQ(DEFAULT_BUFFER_SIZE, props.buffer_size());
  ASSERT_EQ(DEFAULT_USE_BUFFERED_STREAM, props.is_buffered_stream_enabled());
}

TEST(TestWriterProperties, Basics) {
  std::shared_ptr<WriterProperties> props = WriterProperties::Builder().build();

  ASSERT_EQ(DEFAULT_PAGE_SIZE, props->data_pagesize());
  ASSERT_EQ(DEFAULT_DICTIONARY_PAGE_SIZE_LIMIT, props->dictionary_pagesize_limit());
  ASSERT_EQ(DEFAULT_WRITER_VERSION, props->version());
}

}  // namespace test
}  // namespace parquet
<commit_msg>PARQUET-724: Test more advanced properties setting<commit_after>// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.

#include <gtest/gtest.h>

#include <string>

#include "parquet/column/properties.h"
#include "parquet/file/reader.h"

namespace parquet {

using schema::ColumnPath;

namespace test {

TEST(TestReaderProperties, Basics) {
  ReaderProperties props;

  ASSERT_EQ(DEFAULT_BUFFER_SIZE, props.buffer_size());
  ASSERT_EQ(DEFAULT_USE_BUFFERED_STREAM, props.is_buffered_stream_enabled());
}

TEST(TestWriterProperties, Basics) {
  std::shared_ptr<WriterProperties> props = WriterProperties::Builder().build();

  ASSERT_EQ(DEFAULT_PAGE_SIZE, props->data_pagesize());
  ASSERT_EQ(DEFAULT_DICTIONARY_PAGE_SIZE_LIMIT, props->dictionary_pagesize_limit());
  ASSERT_EQ(DEFAULT_WRITER_VERSION, props->version());
}

TEST(TestWriterProperties, AdvancedHandling) {
  WriterProperties::Builder builder;
  builder.compression("gzip", Compression::GZIP);
  builder.compression(Compression::SNAPPY);
  builder.encoding(Encoding::DELTA_BINARY_PACKED);
  builder.encoding("delta-length", Encoding::DELTA_LENGTH_BYTE_ARRAY);
  std::shared_ptr<WriterProperties> props = builder.build();

  ASSERT_EQ(Compression::GZIP, props->compression(ColumnPath::FromDotString("gzip")));
  ASSERT_EQ(
      Compression::SNAPPY, props->compression(ColumnPath::FromDotString("delta-length")));
  ASSERT_EQ(
      Encoding::DELTA_BINARY_PACKED, props->encoding(ColumnPath::FromDotString("gzip")));
  ASSERT_EQ(Encoding::DELTA_LENGTH_BYTE_ARRAY,
      props->encoding(ColumnPath::FromDotString("delta-length")));
}

}  // namespace test
}  // namespace parquet
<|endoftext|>


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

ContinuousComponentModel::ContinuousComponentModel(map<string, double> &in_hypers) {
  count = 0;
  score = 0;
  p_hypers = &in_hypers;
  hyper_r = (*p_hypers)["r"];
  hyper_nu = (*p_hypers)["nu"];
  hyper_s = (*p_hypers)["s"];
  hyper_mu = (*p_hypers)["mu"];
  init_suffstats();
  set_log_Z_0();
}

ContinuousComponentModel::ContinuousComponentModel(map<string, double> &in_hypers, int COUNT, double SUM_X, double SUM_X_SQ) {
  count = COUNT;
  sum_x = SUM_X;
  sum_x_squared = SUM_X_SQ;
  p_hypers = &in_hypers;
  hyper_r = (*p_hypers)["r"];
  hyper_nu = (*p_hypers)["nu"];
  hyper_s = (*p_hypers)["s"];
  hyper_mu = (*p_hypers)["mu"];
  set_log_Z_0();
  score = calc_marginal_logp();
}

void ContinuousComponentModel::get_hyper_doubles(double &r, double &nu,
	       	double &s, double &mu) const {
  r = hyper_r;
  nu = hyper_nu;
  s = hyper_s;
  mu = hyper_mu;
}

double ContinuousComponentModel::calc_marginal_logp() const {
  double r, nu, s, mu;
  int count;
  double sum_x, sum_x_squared;
  get_hyper_doubles(r, nu, s, mu);
  get_suffstats(count, sum_x, sum_x_squared);
  numerics::update_continuous_hypers(count, sum_x, sum_x_squared, r, nu, s, mu);
  return numerics::calc_continuous_logp(count, r, nu, s, log_Z_0);
}

double ContinuousComponentModel::calc_element_predictive_logp(double element) const {
  if(isnan(element)) return 0;
  double r, nu, s, mu;
  int count;
  double sum_x, sum_x_squared;
  get_hyper_doubles(r, nu, s, mu);
  get_suffstats(count, sum_x, sum_x_squared);
  //
  numerics::insert_to_continuous_suffstats(count, sum_x, sum_x_squared, element);
  numerics::update_continuous_hypers(count, sum_x, sum_x_squared, r, nu, s, mu);

  double logp_prime = numerics::calc_continuous_logp(count, r, nu, s, log_Z_0);
  return logp_prime - score;
}

double ContinuousComponentModel::calc_element_predictive_logp_constrained(double element, vector<double> constraints) const {
  if(isnan(element)) return 0;
  double r, nu, s, mu;
  int count;
  double sum_x, sum_x_squared;
  get_hyper_doubles(r, nu, s, mu);
  get_suffstats(count, sum_x, sum_x_squared);
  //
  for(int constraint_idx=0; constraint_idx<constraints.size();
      constraint_idx++) {
    double constraint = constraints[constraint_idx];
    numerics::insert_to_continuous_suffstats(count, sum_x, sum_x_squared,
					     constraint);
  }
  numerics::update_continuous_hypers(count, sum_x, sum_x_squared, r, nu, s, mu);
  double baseline = numerics::calc_continuous_logp(count, r, nu, s, log_Z_0);
  //
  get_hyper_doubles(r, nu, s, mu);
  numerics::insert_to_continuous_suffstats(count, sum_x, sum_x_squared, element);
  numerics::update_continuous_hypers(count, sum_x, sum_x_squared, r, nu, s, mu);
  double updated = numerics::calc_continuous_logp(count, r, nu, s, log_Z_0);
  double predictive_logp = updated - baseline;
  return predictive_logp;
}

vector<double> ContinuousComponentModel::calc_hyper_conditionals(string which_hyper, vector<double> hyper_grid) const {
  double r, nu, s, mu;
  int count;
  double sum_x, sum_x_squared;
  get_hyper_doubles(r, nu, s, mu);
  get_suffstats(count, sum_x, sum_x_squared);

  if(which_hyper=="r") {
    return numerics::calc_continuous_r_conditionals(hyper_grid, count, sum_x,
						    sum_x_squared, nu, s, mu);
  } else if(which_hyper=="nu"){
    return numerics::calc_continuous_nu_conditionals(hyper_grid, count, sum_x,
						     sum_x_squared, r, s, mu);
  } else if(which_hyper=="s"){
    return numerics::calc_continuous_s_conditionals(hyper_grid, count, sum_x,
						    sum_x_squared, r, nu, mu);
  } else if(which_hyper=="mu"){
    return numerics::calc_continuous_mu_conditionals(hyper_grid, count, sum_x,
						     sum_x_squared, r, nu, s);
  } else {
    // error condition
    vector<double> error;
    return error;
  }
}

double ContinuousComponentModel::insert_element(double element) {
  if(isnan(element)) return 0;
  double score_0 = score;
  numerics::insert_to_continuous_suffstats(count, sum_x, sum_x_squared, element);
  score = calc_marginal_logp();
  double delta_score = score - score_0;
  return delta_score;
}

double ContinuousComponentModel::remove_element(double element) {
  if(isnan(element)) return 0;
  double score_0 = score;
  numerics::remove_from_continuous_suffstats(count, sum_x, sum_x_squared, element);
  score = calc_marginal_logp();
  double delta_score = score - score_0;
  return delta_score;
}

double ContinuousComponentModel::incorporate_hyper_update() {
  double score_0 = score;
  // hypers[which_hyper] = value; // set by owner of hypers object
  set_log_Z_0();
  score = calc_marginal_logp();
  double score_delta = score - score_0;
  return score_delta;
}

void ContinuousComponentModel::set_log_Z_0() {
  double r, nu, s, mu;
  get_hyper_doubles(r, nu, s, mu);
  log_Z_0 = numerics::calc_continuous_logp(0, r, nu, s, 0);
}

void ContinuousComponentModel::init_suffstats() {
	sum_x = 0.;
	sum_x_squared = 0.;
}

void ContinuousComponentModel::get_suffstats(int &count_out, double &sum_x_out,
					     double &sum_x_squared_out) const {
  count_out = count;
  sum_x_out = sum_x;
  sum_x_squared_out = sum_x_squared;
}

double ContinuousComponentModel::get_draw(int random_seed) const {
  // get modified suffstats
  double r, nu, s, mu;
  int count;
  double sum_x, sum_x_squared;
  get_hyper_doubles(r, nu, s, mu);
  get_suffstats(count, sum_x, sum_x_squared);
  numerics::update_continuous_hypers(count, sum_x, sum_x_squared, r, nu, s, mu);
  //
  boost::mt19937  _engine(random_seed);
  boost::uniform_01<boost::mt19937> _dist(_engine);
  boost::random::student_t_distribution<double> student_t(nu);
  double student_t_draw = student_t(_dist);
  // FIXME: should 's' be divided by 2 as well here to reconcile Murphy with Teh?
  // http://www.cs.ubc.ca/~murphyk/Teaching/CS340-Fall07/reading/NG.pdf
  // http://www.stats.ox.ac.uk/~teh/research/notes/GaussianInverseGamma.pdf
  double coeff = sqrt((s * (r+1)) / (nu / 2. * r));
  double draw = student_t_draw * coeff + mu;
  return draw;
}

double ContinuousComponentModel::get_draw_constrained(int random_seed, vector<double> constraints) const {
  // get modified suffstats
  double r, nu, s, mu;
  int count;
  double sum_x, sum_x_squared;
  get_hyper_doubles(r, nu, s, mu);
  get_suffstats(count, sum_x, sum_x_squared);
  for(int constraint_idx=0; constraint_idx<constraints.size();
      constraint_idx++) {
    double constraint = constraints[constraint_idx];
    numerics::insert_to_continuous_suffstats(count, sum_x, sum_x_squared,
					     constraint);
  }
  numerics::update_continuous_hypers(count, sum_x, sum_x_squared, r, nu, s, mu);
  //
  boost::mt19937  _engine(random_seed);
  boost::uniform_01<boost::mt19937> _dist(_engine);
  boost::random::student_t_distribution<double> student_t(nu);
  double student_t_draw = student_t(_dist);
  double coeff = sqrt((s * (r+1)) / (nu / 2. * r));
  double draw = student_t_draw * coeff + mu;
  return draw;
}

// For simple predictive probability
double ContinuousComponentModel::get_predictive_cdf(double element, vector<double> constraints) const {
  // get modified suffstats
  double r, nu, s, mu;
  int count;
  double sum_x, sum_x_squared;
  get_hyper_doubles(r, nu, s, mu);
  get_suffstats(count, sum_x, sum_x_squared);
  for(int constraint_idx=0; constraint_idx<constraints.size();
      constraint_idx++) {
    double constraint = constraints[constraint_idx];
    numerics::insert_to_continuous_suffstats(count, sum_x, sum_x_squared,
               constraint);
  }
  numerics::update_continuous_hypers(count, sum_x, sum_x_squared, r, nu, s, mu);

  boost::math::students_t dist(nu);
  double coeff = sqrt((s * (r+1)) / (nu / 2. * r));
  // manipulate the number so it will fit in the standard t (reverse of the draw proceedure)
  double rev_draw = (element-mu)/ coeff ;
  double cdfval = boost::math::cdf(dist, rev_draw);

  return cdfval;
}

// For simple predictive probability
double ContinuousComponentModel::get_predictive_pdf(double element, vector<double> constraints) const {
  // get modified suffstats
  double r, nu, s, mu;
  int count;
  double sum_x, sum_x_squared;
  get_hyper_doubles(r, nu, s, mu);
  get_suffstats(count, sum_x, sum_x_squared);
  for(int constraint_idx=0; constraint_idx<constraints.size();
      constraint_idx++) {
    double constraint = constraints[constraint_idx];
    numerics::insert_to_continuous_suffstats(count, sum_x, sum_x_squared,
               constraint);
  }
  numerics::update_continuous_hypers(count, sum_x, sum_x_squared, r, nu, s, mu);

  boost::math::students_t dist(nu);
  double coeff = sqrt((s * (r+1)) / (nu / 2. * r));
  // manipulate the number so it will fit in the standard t (reverse of the draw proceedure)
  double rev_draw = (element-mu)/ coeff ;
  double pdfval = boost::math::pdf(dist, rev_draw);

  return pdfval;
}

map<string, double> ContinuousComponentModel::_get_suffstats() const {
	map<string, double> suffstats;
	suffstats["sum_x"] = sum_x;
	suffstats["sum_x_squared"] = sum_x_squared;
  	return suffstats;
}

<commit_msg>BUGFIX: incorporate_hyper_updage: pull in updated hypers from p_hypers<commit_after>/*
* Copyright 2013 Baxter, Lovell, Mangsingkha, Saeedi
*
*   Licensed under the Apache License, Version 2.0 (the "License");
*   you may not use this file except in compliance with the License.
*   You may obtain a copy of the License at
*
*       http://www.apache.org/licenses/LICENSE-2.0
*
*   Unless required by applicable law or agreed to in writing, software
*   distributed under the License is distributed on an "AS IS" BASIS,
*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*   See the License for the specific language governing permissions and
*   limitations under the License.
*/
#include "ContinuousComponentModel.h"
using namespace std;

ContinuousComponentModel::ContinuousComponentModel(map<string, double> &in_hypers) {
  count = 0;
  score = 0;
  p_hypers = &in_hypers;
  hyper_r = (*p_hypers)["r"];
  hyper_nu = (*p_hypers)["nu"];
  hyper_s = (*p_hypers)["s"];
  hyper_mu = (*p_hypers)["mu"];
  init_suffstats();
  set_log_Z_0();
}

ContinuousComponentModel::ContinuousComponentModel(map<string, double> &in_hypers, int COUNT, double SUM_X, double SUM_X_SQ) {
  count = COUNT;
  sum_x = SUM_X;
  sum_x_squared = SUM_X_SQ;
  p_hypers = &in_hypers;
  hyper_r = (*p_hypers)["r"];
  hyper_nu = (*p_hypers)["nu"];
  hyper_s = (*p_hypers)["s"];
  hyper_mu = (*p_hypers)["mu"];
  set_log_Z_0();
  score = calc_marginal_logp();
}

void ContinuousComponentModel::get_hyper_doubles(double &r, double &nu,
	       	double &s, double &mu) const {
  r = hyper_r;
  nu = hyper_nu;
  s = hyper_s;
  mu = hyper_mu;
}

double ContinuousComponentModel::calc_marginal_logp() const {
  double r, nu, s, mu;
  int count;
  double sum_x, sum_x_squared;
  get_hyper_doubles(r, nu, s, mu);
  get_suffstats(count, sum_x, sum_x_squared);
  numerics::update_continuous_hypers(count, sum_x, sum_x_squared, r, nu, s, mu);
  return numerics::calc_continuous_logp(count, r, nu, s, log_Z_0);
}

double ContinuousComponentModel::calc_element_predictive_logp(double element) const {
  if(isnan(element)) return 0;
  double r, nu, s, mu;
  int count;
  double sum_x, sum_x_squared;
  get_hyper_doubles(r, nu, s, mu);
  get_suffstats(count, sum_x, sum_x_squared);
  //
  numerics::insert_to_continuous_suffstats(count, sum_x, sum_x_squared, element);
  numerics::update_continuous_hypers(count, sum_x, sum_x_squared, r, nu, s, mu);

  double logp_prime = numerics::calc_continuous_logp(count, r, nu, s, log_Z_0);
  return logp_prime - score;
}

double ContinuousComponentModel::calc_element_predictive_logp_constrained(double element, vector<double> constraints) const {
  if(isnan(element)) return 0;
  double r, nu, s, mu;
  int count;
  double sum_x, sum_x_squared;
  get_hyper_doubles(r, nu, s, mu);
  get_suffstats(count, sum_x, sum_x_squared);
  //
  for(int constraint_idx=0; constraint_idx<constraints.size();
      constraint_idx++) {
    double constraint = constraints[constraint_idx];
    numerics::insert_to_continuous_suffstats(count, sum_x, sum_x_squared,
					     constraint);
  }
  numerics::update_continuous_hypers(count, sum_x, sum_x_squared, r, nu, s, mu);
  double baseline = numerics::calc_continuous_logp(count, r, nu, s, log_Z_0);
  //
  get_hyper_doubles(r, nu, s, mu);
  numerics::insert_to_continuous_suffstats(count, sum_x, sum_x_squared, element);
  numerics::update_continuous_hypers(count, sum_x, sum_x_squared, r, nu, s, mu);
  double updated = numerics::calc_continuous_logp(count, r, nu, s, log_Z_0);
  double predictive_logp = updated - baseline;
  return predictive_logp;
}

vector<double> ContinuousComponentModel::calc_hyper_conditionals(string which_hyper, vector<double> hyper_grid) const {
  double r, nu, s, mu;
  int count;
  double sum_x, sum_x_squared;
  get_hyper_doubles(r, nu, s, mu);
  get_suffstats(count, sum_x, sum_x_squared);

  if(which_hyper=="r") {
    return numerics::calc_continuous_r_conditionals(hyper_grid, count, sum_x,
						    sum_x_squared, nu, s, mu);
  } else if(which_hyper=="nu"){
    return numerics::calc_continuous_nu_conditionals(hyper_grid, count, sum_x,
						     sum_x_squared, r, s, mu);
  } else if(which_hyper=="s"){
    return numerics::calc_continuous_s_conditionals(hyper_grid, count, sum_x,
						    sum_x_squared, r, nu, mu);
  } else if(which_hyper=="mu"){
    return numerics::calc_continuous_mu_conditionals(hyper_grid, count, sum_x,
						     sum_x_squared, r, nu, s);
  } else {
    // error condition
    vector<double> error;
    return error;
  }
}

double ContinuousComponentModel::insert_element(double element) {
  if(isnan(element)) return 0;
  double score_0 = score;
  numerics::insert_to_continuous_suffstats(count, sum_x, sum_x_squared, element);
  score = calc_marginal_logp();
  double delta_score = score - score_0;
  return delta_score;
}

double ContinuousComponentModel::remove_element(double element) {
  if(isnan(element)) return 0;
  double score_0 = score;
  numerics::remove_from_continuous_suffstats(count, sum_x, sum_x_squared, element);
  score = calc_marginal_logp();
  double delta_score = score - score_0;
  return delta_score;
}

double ContinuousComponentModel::incorporate_hyper_update() {
  hyper_r = get(*p_hypers, (string) "r");
  hyper_nu = get(*p_hypers, (string) "nu");
  hyper_s = get(*p_hypers, (string) "s");
  hyper_mu = get(*p_hypers, (string) "mu");
  double score_0 = score;
  // hypers[which_hyper] = value; // set by owner of hypers object
  set_log_Z_0();
  score = calc_marginal_logp();
  double score_delta = score - score_0;
  return score_delta;
}

void ContinuousComponentModel::set_log_Z_0() {
  double r, nu, s, mu;
  get_hyper_doubles(r, nu, s, mu);
  log_Z_0 = numerics::calc_continuous_logp(0, r, nu, s, 0);
}

void ContinuousComponentModel::init_suffstats() {
	sum_x = 0.;
	sum_x_squared = 0.;
}

void ContinuousComponentModel::get_suffstats(int &count_out, double &sum_x_out,
					     double &sum_x_squared_out) const {
  count_out = count;
  sum_x_out = sum_x;
  sum_x_squared_out = sum_x_squared;
}

double ContinuousComponentModel::get_draw(int random_seed) const {
  // get modified suffstats
  double r, nu, s, mu;
  int count;
  double sum_x, sum_x_squared;
  get_hyper_doubles(r, nu, s, mu);
  get_suffstats(count, sum_x, sum_x_squared);
  numerics::update_continuous_hypers(count, sum_x, sum_x_squared, r, nu, s, mu);
  //
  boost::mt19937  _engine(random_seed);
  boost::uniform_01<boost::mt19937> _dist(_engine);
  boost::random::student_t_distribution<double> student_t(nu);
  double student_t_draw = student_t(_dist);
  // FIXME: should 's' be divided by 2 as well here to reconcile Murphy with Teh?
  // http://www.cs.ubc.ca/~murphyk/Teaching/CS340-Fall07/reading/NG.pdf
  // http://www.stats.ox.ac.uk/~teh/research/notes/GaussianInverseGamma.pdf
  double coeff = sqrt((s * (r+1)) / (nu / 2. * r));
  double draw = student_t_draw * coeff + mu;
  return draw;
}

double ContinuousComponentModel::get_draw_constrained(int random_seed, vector<double> constraints) const {
  // get modified suffstats
  double r, nu, s, mu;
  int count;
  double sum_x, sum_x_squared;
  get_hyper_doubles(r, nu, s, mu);
  get_suffstats(count, sum_x, sum_x_squared);
  for(int constraint_idx=0; constraint_idx<constraints.size();
      constraint_idx++) {
    double constraint = constraints[constraint_idx];
    numerics::insert_to_continuous_suffstats(count, sum_x, sum_x_squared,
					     constraint);
  }
  numerics::update_continuous_hypers(count, sum_x, sum_x_squared, r, nu, s, mu);
  //
  boost::mt19937  _engine(random_seed);
  boost::uniform_01<boost::mt19937> _dist(_engine);
  boost::random::student_t_distribution<double> student_t(nu);
  double student_t_draw = student_t(_dist);
  double coeff = sqrt((s * (r+1)) / (nu / 2. * r));
  double draw = student_t_draw * coeff + mu;
  return draw;
}

// For simple predictive probability
double ContinuousComponentModel::get_predictive_cdf(double element, vector<double> constraints) const {
  // get modified suffstats
  double r, nu, s, mu;
  int count;
  double sum_x, sum_x_squared;
  get_hyper_doubles(r, nu, s, mu);
  get_suffstats(count, sum_x, sum_x_squared);
  for(int constraint_idx=0; constraint_idx<constraints.size();
      constraint_idx++) {
    double constraint = constraints[constraint_idx];
    numerics::insert_to_continuous_suffstats(count, sum_x, sum_x_squared,
               constraint);
  }
  numerics::update_continuous_hypers(count, sum_x, sum_x_squared, r, nu, s, mu);

  boost::math::students_t dist(nu);
  double coeff = sqrt((s * (r+1)) / (nu / 2. * r));
  // manipulate the number so it will fit in the standard t (reverse of the draw proceedure)
  double rev_draw = (element-mu)/ coeff ;
  double cdfval = boost::math::cdf(dist, rev_draw);

  return cdfval;
}

// For simple predictive probability
double ContinuousComponentModel::get_predictive_pdf(double element, vector<double> constraints) const {
  // get modified suffstats
  double r, nu, s, mu;
  int count;
  double sum_x, sum_x_squared;
  get_hyper_doubles(r, nu, s, mu);
  get_suffstats(count, sum_x, sum_x_squared);
  for(int constraint_idx=0; constraint_idx<constraints.size();
      constraint_idx++) {
    double constraint = constraints[constraint_idx];
    numerics::insert_to_continuous_suffstats(count, sum_x, sum_x_squared,
               constraint);
  }
  numerics::update_continuous_hypers(count, sum_x, sum_x_squared, r, nu, s, mu);

  boost::math::students_t dist(nu);
  double coeff = sqrt((s * (r+1)) / (nu / 2. * r));
  // manipulate the number so it will fit in the standard t (reverse of the draw proceedure)
  double rev_draw = (element-mu)/ coeff ;
  double pdfval = boost::math::pdf(dist, rev_draw);

  return pdfval;
}

map<string, double> ContinuousComponentModel::_get_suffstats() const {
	map<string, double> suffstats;
	suffstats["sum_x"] = sum_x;
	suffstats["sum_x_squared"] = sum_x_squared;
  	return suffstats;
}

<|endoftext|>


<commit_before>#include "multiVolumes.h"

namespace cura
{

void carveMultipleVolumes(std::vector<Slicer*> &volumes, bool alternate_carve_order)
{
    //Go trough all the volumes, and remove the previous volume outlines from our own outline, so we never have overlapped areas.
    for (unsigned int volume_1_idx = 1; volume_1_idx < volumes.size(); volume_1_idx++)
    {
        Slicer& volume_1 = *volumes[volume_1_idx];
        if (volume_1.mesh->getSettingBoolean("infill_mesh")
            || volume_1.mesh->getSettingBoolean("anti_overhang_mesh")
            || volume_1.mesh->getSettingBoolean("support_mesh")
            )
        {
            continue;
        }
        for (unsigned int volume_2_idx = 0; volume_2_idx < volume_1_idx; volume_2_idx++)
        {
            Slicer& volume_2 = *volumes[volume_2_idx];
            if (volume_2.mesh->getSettingBoolean("infill_mesh")
                || volume_2.mesh->getSettingBoolean("anti_overhang_mesh")
                || volume_2.mesh->getSettingBoolean("support_mesh")
                )
            {
                continue;
            }
            if (!volume_1.mesh->getAABB().hit(volume_2.mesh->getAABB()))
            {
                continue;
            }
            for (unsigned int layerNr = 0; layerNr < volume_1.layers.size(); layerNr++)
            {
                SlicerLayer& layer1 = volume_1.layers[layerNr];
                SlicerLayer& layer2 = volume_2.layers[layerNr];
                if (alternate_carve_order && layerNr % 2 == 0)
                {
                    layer2.polygons = layer2.polygons.difference(layer1.polygons);
                }
                else
                {
                    layer1.polygons = layer1.polygons.difference(layer2.polygons);
                }
            }
        }
    }
}

//Expand each layer a bit and then keep the extra overlapping parts that overlap with other volumes.
//This generates some overlap in dual extrusion, for better bonding in touching parts.
void generateMultipleVolumesOverlap(std::vector<Slicer*> &volumes)
{
    if (volumes.size() < 2)
    {
        return;
    }

    int offset_to_merge_other_merged_volumes = 20;
    for (Slicer* volume : volumes)
    {
        int overlap = volume->mesh->getSettingInMicrons("multiple_mesh_overlap");
        if (volume->mesh->getSettingBoolean("infill_mesh")
            || volume->mesh->getSettingBoolean("anti_overhang_mesh")
            || volume->mesh->getSettingBoolean("support_mesh")
            || overlap == 0)
        {
            continue;
        }
        AABB3D aabb(volume->mesh->getAABB());
        aabb.expandXY(overlap); // expand to account for the case where two models and their bounding boxes are adjacent along the X or Y-direction
        for (unsigned int layer_nr = 0; layer_nr < volume->layers.size(); layer_nr++)
        {
            Polygons all_other_volumes;
            for (Slicer* other_volume : volumes)
            {
                if (other_volume->mesh->getSettingBoolean("infill_mesh")
                    || other_volume->mesh->getSettingBoolean("anti_overhang_mesh")
                    || other_volume->mesh->getSettingBoolean("support_mesh")
                    || !other_volume->mesh->getAABB().hit(aabb)
                    || other_volume == volume
                )
                {
                    continue;
                }
                SlicerLayer& other_volume_layer = other_volume->layers[layer_nr];
                all_other_volumes = all_other_volumes.unionPolygons(other_volume_layer.polygons.offset(offset_to_merge_other_merged_volumes));
            }

            SlicerLayer& volume_layer = volume->layers[layer_nr];
            volume_layer.polygons = volume_layer.polygons.unionPolygons(all_other_volumes.intersection(volume_layer.polygons.offset(overlap / 2)));
        }
    }
}

void MultiVolumes::carveCuttingMeshes(std::vector<Slicer*>& volumes, const std::vector<Mesh>& meshes)
{
    for (unsigned int carving_mesh_idx = 0; carving_mesh_idx < volumes.size(); carving_mesh_idx++)
    {
        const Mesh& cutting_mesh = meshes[carving_mesh_idx];
        if (!cutting_mesh.getSettingBoolean("cutting_mesh"))
        {
            continue;
        }
        Slicer& cutting_mesh_volume = *volumes[carving_mesh_idx];
        for (unsigned int layer_nr = 0; layer_nr < cutting_mesh_volume.layers.size(); layer_nr++)
        {
            Polygons& cutting_mesh_layer = cutting_mesh_volume.layers[layer_nr].polygons;
            Polygons new_outlines;
            for (unsigned int carved_mesh_idx = 0; carved_mesh_idx < volumes.size(); carved_mesh_idx++)
            {
                const Mesh& carved_mesh = meshes[carved_mesh_idx];
                if (carved_mesh_idx == carving_mesh_idx || carved_mesh.getSettingBoolean("cutting_mesh"))
                {
                    continue;
                }
                Slicer& carved_volume = *volumes[carved_mesh_idx];
                Polygons& carved_mesh_layer = carved_volume.layers[layer_nr].polygons;
                Polygons intersection = cutting_mesh_layer.intersection(carved_mesh_layer);
                new_outlines.add(intersection);
                carved_mesh_layer = carved_mesh_layer.difference(cutting_mesh_layer);
            }
            cutting_mesh_layer = new_outlines;
        }
    }
}

}//namespace cura
<commit_msg>Remove superfluous check against itself<commit_after>//Copyright (c) 2017 Ultimaker B.V.
//CuraEngine is released under the terms of the AGPLv3 or higher.

#include "multiVolumes.h"

namespace cura
{

void carveMultipleVolumes(std::vector<Slicer*> &volumes, bool alternate_carve_order)
{
    //Go trough all the volumes, and remove the previous volume outlines from our own outline, so we never have overlapped areas.
    for (unsigned int volume_1_idx = 1; volume_1_idx < volumes.size(); volume_1_idx++)
    {
        Slicer& volume_1 = *volumes[volume_1_idx];
        if (volume_1.mesh->getSettingBoolean("infill_mesh")
            || volume_1.mesh->getSettingBoolean("anti_overhang_mesh")
            || volume_1.mesh->getSettingBoolean("support_mesh")
            )
        {
            continue;
        }
        for (unsigned int volume_2_idx = 0; volume_2_idx < volume_1_idx; volume_2_idx++)
        {
            Slicer& volume_2 = *volumes[volume_2_idx];
            if (volume_2.mesh->getSettingBoolean("infill_mesh")
                || volume_2.mesh->getSettingBoolean("anti_overhang_mesh")
                || volume_2.mesh->getSettingBoolean("support_mesh")
                )
            {
                continue;
            }
            if (!volume_1.mesh->getAABB().hit(volume_2.mesh->getAABB()))
            {
                continue;
            }
            for (unsigned int layerNr = 0; layerNr < volume_1.layers.size(); layerNr++)
            {
                SlicerLayer& layer1 = volume_1.layers[layerNr];
                SlicerLayer& layer2 = volume_2.layers[layerNr];
                if (alternate_carve_order && layerNr % 2 == 0)
                {
                    layer2.polygons = layer2.polygons.difference(layer1.polygons);
                }
                else
                {
                    layer1.polygons = layer1.polygons.difference(layer2.polygons);
                }
            }
        }
    }
}

//Expand each layer a bit and then keep the extra overlapping parts that overlap with other volumes.
//This generates some overlap in dual extrusion, for better bonding in touching parts.
void generateMultipleVolumesOverlap(std::vector<Slicer*> &volumes)
{
    if (volumes.size() < 2)
    {
        return;
    }

    int offset_to_merge_other_merged_volumes = 20;
    for (Slicer* volume : volumes)
    {
        int overlap = volume->mesh->getSettingInMicrons("multiple_mesh_overlap");
        if (volume->mesh->getSettingBoolean("infill_mesh")
            || volume->mesh->getSettingBoolean("anti_overhang_mesh")
            || volume->mesh->getSettingBoolean("support_mesh")
            || overlap == 0)
        {
            continue;
        }
        AABB3D aabb(volume->mesh->getAABB());
        aabb.expandXY(overlap); // expand to account for the case where two models and their bounding boxes are adjacent along the X or Y-direction
        for (unsigned int layer_nr = 0; layer_nr < volume->layers.size(); layer_nr++)
        {
            Polygons all_other_volumes;
            for (Slicer* other_volume : volumes)
            {
                if (other_volume->mesh->getSettingBoolean("infill_mesh")
                    || other_volume->mesh->getSettingBoolean("anti_overhang_mesh")
                    || other_volume->mesh->getSettingBoolean("support_mesh")
                    || !other_volume->mesh->getAABB().hit(aabb)
                    || other_volume == volume
                )
                {
                    continue;
                }
                SlicerLayer& other_volume_layer = other_volume->layers[layer_nr];
                all_other_volumes = all_other_volumes.unionPolygons(other_volume_layer.polygons.offset(offset_to_merge_other_merged_volumes));
            }

            SlicerLayer& volume_layer = volume->layers[layer_nr];
            volume_layer.polygons = volume_layer.polygons.unionPolygons(all_other_volumes.intersection(volume_layer.polygons.offset(overlap / 2)));
        }
    }
}

void MultiVolumes::carveCuttingMeshes(std::vector<Slicer*>& volumes, const std::vector<Mesh>& meshes)
{
    for (unsigned int carving_mesh_idx = 0; carving_mesh_idx < volumes.size(); carving_mesh_idx++)
    {
        const Mesh& cutting_mesh = meshes[carving_mesh_idx];
        if (!cutting_mesh.getSettingBoolean("cutting_mesh"))
        {
            continue;
        }
        Slicer& cutting_mesh_volume = *volumes[carving_mesh_idx];
        for (unsigned int layer_nr = 0; layer_nr < cutting_mesh_volume.layers.size(); layer_nr++)
        {
            Polygons& cutting_mesh_layer = cutting_mesh_volume.layers[layer_nr].polygons;
            Polygons new_outlines;
            for (unsigned int carved_mesh_idx = 0; carved_mesh_idx < volumes.size(); carved_mesh_idx++)
            {
                const Mesh& carved_mesh = meshes[carved_mesh_idx];
                if (carved_mesh.getSettingBoolean("cutting_mesh"))
                {
                    continue;
                }
                Slicer& carved_volume = *volumes[carved_mesh_idx];
                Polygons& carved_mesh_layer = carved_volume.layers[layer_nr].polygons;
                Polygons intersection = cutting_mesh_layer.intersection(carved_mesh_layer);
                new_outlines.add(intersection);
                carved_mesh_layer = carved_mesh_layer.difference(cutting_mesh_layer);
            }
            cutting_mesh_layer = new_outlines;
        }
    }
}

}//namespace cura
<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil c-basic-offset: 3 -*- */
// vim:cindent:ts=3:sw=3:et:tw=80:sta:
/*************************************************************** cppdom-cpr beg
 *
 * cppdom was forked from the original xmlpp version 0.6 under the LGPL. This
 * new, branched xmlpp is under the same LGPL (of course) and is being
 * maintained by:
 *      Kevin Meinert   <subatomic@users.sourceforge.net>
 *      Allen Bierbaum  <allenb@users.sourceforge.net>
 *      Ben Scott       <nonchocoboy@users.sourceforge.net>
 *
 * -----------------------------------------------------------------
 *
 * xmlpp - an xml parser and validator written in C++
 * copyright (c) 2000-2001 Michael Fink
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 *
 * -----------------------------------------------------------------
 * File:          $RCSfile$
 * Date modified: $Date$
 * Version:       $Revision$
 * -----------------------------------------------------------------
 *
 ************************************************************ cppdom-cpr-end */
#include <TestCases/ErrorTest.h>
#include <Suites.h>
#include <iostream>

#include <cppdom/cppdom.h>

namespace cppdomtest
{
   CPPUNIT_TEST_SUITE_REGISTRATION(ErrorTest);

   void
   ErrorTest::testCreation()
   {
      const cppdom::Error error(cppdom::xml_instream_error, "Blah", __FILE__, __LINE__);
      CPPUNIT_ASSERT(error.getError() == cppdom::xml_instream_error);
      CPPUNIT_ASSERT(error.getStrError() == "error in the infile stream");
      CPPUNIT_ASSERT(error.getString() == "error in the infile stream: Blah");
      CPPUNIT_ASSERT(error.getInfo() == "test/suite/ErrorTest.cpp:52");
   }
}
<commit_msg>Fixed test<commit_after>/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil c-basic-offset: 3 -*- */
// vim:cindent:ts=3:sw=3:et:tw=80:sta:
/*************************************************************** cppdom-cpr beg
 *
 * cppdom was forked from the original xmlpp version 0.6 under the LGPL. This
 * new, branched xmlpp is under the same LGPL (of course) and is being
 * maintained by:
 *      Kevin Meinert   <subatomic@users.sourceforge.net>
 *      Allen Bierbaum  <allenb@users.sourceforge.net>
 *      Ben Scott       <nonchocoboy@users.sourceforge.net>
 *
 * -----------------------------------------------------------------
 *
 * xmlpp - an xml parser and validator written in C++
 * copyright (c) 2000-2001 Michael Fink
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 *
 * -----------------------------------------------------------------
 * File:          $RCSfile$
 * Date modified: $Date$
 * Version:       $Revision$
 * -----------------------------------------------------------------
 *
 ************************************************************ cppdom-cpr-end */
#include <TestCases/ErrorTest.h>
#include <Suites.h>
#include <iostream>

#include <cppdom/cppdom.h>

namespace cppdomtest
{
   CPPUNIT_TEST_SUITE_REGISTRATION(ErrorTest);

   void
   ErrorTest::testCreation()
   {
      const cppdom::Error error(cppdom::xml_instream_error, "Blah", __FILE__, __LINE__);
      CPPUNIT_ASSERT(error.getError() == cppdom::xml_instream_error);
      CPPUNIT_ASSERT(error.getStrError() == "error in the infile stream");
      CPPUNIT_ASSERT(error.getString() == "error in the infile stream: Blah");
      CPPUNIT_ASSERT(error.getInfo() == "test/suite/TestCases/ErrorTest.cpp:52");
   }
}
<|endoftext|>


<commit_before>#include "dptrace.h"
#include "../logger.h"

TraceDPMatrix::IndexedTrans::IndexedTrans (const EvaluatedMachineState::Trans& t, StateIndex s, StateIndex d, InputToken i)
{
  init (t.logWeight, t.transIndex);
  src = s;
  dest = d;
  in = i;
}

size_t calcBlockSize (size_t storageColumns, size_t totalColumns) {
  const double s = pow ((double) storageColumns, 2) - 4*totalColumns;
  return s >= 0 ? ceil ((storageColumns + sqrt(s)) / 2) : 1;
}

TraceDPMatrix::TraceDPMatrix (const EvaluatedMachine& eval, const GaussianModelParams& modelParams, const TraceMoments& moments, const TraceParams& traceParams, size_t bb) :
  eval (eval),
  modelParams (modelParams),
  moments (moments),
  traceParams (traceParams),
  coeffs (modelParams, traceParams, eval.outputTokenizer),
  outLen (moments.sample.size()),
  nStates (eval.nStates()),
  nOutToks (eval.outputTokenizer.tok2sym.size()),
  nColumns (outLen + 1),
  blockBytes (bb),
  blockSize (blockBytes
	     ? max ((OutputIndex) 2,
		    min ((OutputIndex) nColumns,
			 (OutputIndex) calcBlockSize (blockBytes / (nStates * sizeof(double)), outLen)))
	     : nColumns),
  nCheckpoints (1 + ((nColumns - 1) / blockSize))
{
  LogThisAt(7,"Indexing " << nStates << "-state machine" << endl);
  LogThisAt(9,"Machine:" << endl << eval.toJsonString() << endl);

  nTrans = 0;
  transByOut.resize (nOutToks);
  for (StateIndex dest = 0; dest < nStates; ++dest)
    for (const auto& inTok_outStateTransMap: eval.state[dest].incoming)
      for (const auto& outTok_stateTransMap: inTok_outStateTransMap.second)
	for (const auto& src_trans: outTok_stateTransMap.second) {
	  Assert (outTok_stateTransMap.first || (src_trans.first <= dest), "Input-blinded machine is not topologically sorted (transition from %d to %d has no output)", src_trans.first, dest);
	  transByOut[outTok_stateTransMap.first].push_back (IndexedTrans (src_trans.second, src_trans.first, dest, inTok_outStateTransMap.first));
	  ++nTrans;
	}

  const OutputIndex storageColumns = blockSize + nCheckpoints - 1;
  LogThisAt(7,"Creating " << storageColumns << "-column (" << (outLen+1) << "-sample) * " << nStates << "-state matrix" << endl);
  columnStorage.resize (storageColumns, vguard<double> (nStates, -numeric_limits<double>::infinity()));
}
<commit_msg>fixed large-sequence DP checkpointing<commit_after>#include "dptrace.h"
#include "../logger.h"

TraceDPMatrix::IndexedTrans::IndexedTrans (const EvaluatedMachineState::Trans& t, StateIndex s, StateIndex d, InputToken i)
{
  init (t.logWeight, t.transIndex);
  src = s;
  dest = d;
  in = i;
}

// S = storageColumns, M = maxStorageColumns, T = totalColumns, X = blockSize
// X + (T/X) = S
// If M is large enough, we can set S=M so that all available storage is used:
//  X + (T/X) = M
//  X^2 - MX + T = 0
//  X = (M + sqrt(M^2 - 4T)) / 2
// The condition for this is M^2 - 4T >= 0
// Otherwise, we just minimize S via dS/dX=0, yielding X=sqrt(T) and S=2*sqrt(T)
size_t calcBlockSize (size_t maxStorageColumns, size_t totalColumns) {
  const double discriminant = pow ((double) maxStorageColumns, 2) - 4 * (double) totalColumns;
  return ceil (discriminant >= 0 ? ((maxStorageColumns + sqrt(discriminant)) / 2) : sqrt ((double) totalColumns));
}

TraceDPMatrix::TraceDPMatrix (const EvaluatedMachine& eval, const GaussianModelParams& modelParams, const TraceMoments& moments, const TraceParams& traceParams, size_t bb) :
  eval (eval),
  modelParams (modelParams),
  moments (moments),
  traceParams (traceParams),
  coeffs (modelParams, traceParams, eval.outputTokenizer),
  outLen (moments.sample.size()),
  nStates (eval.nStates()),
  nOutToks (eval.outputTokenizer.tok2sym.size()),
  nColumns (outLen + 1),
  blockBytes (bb),
  blockSize (blockBytes
	     ? max ((OutputIndex) 2,
		    min ((OutputIndex) nColumns,
			 (OutputIndex) calcBlockSize (blockBytes / (nStates * sizeof(double)), outLen)))
	     : nColumns),
  nCheckpoints (1 + ((nColumns - 1) / blockSize))
{
  LogThisAt(7,"Indexing " << nStates << "-state machine" << endl);
  LogThisAt(9,"Machine:" << endl << eval.toJsonString() << endl);

  nTrans = 0;
  transByOut.resize (nOutToks);
  for (StateIndex dest = 0; dest < nStates; ++dest)
    for (const auto& inTok_outStateTransMap: eval.state[dest].incoming)
      for (const auto& outTok_stateTransMap: inTok_outStateTransMap.second)
	for (const auto& src_trans: outTok_stateTransMap.second) {
	  Assert (outTok_stateTransMap.first || (src_trans.first <= dest), "Input-blinded machine is not topologically sorted (transition from %d to %d has no output)", src_trans.first, dest);
	  transByOut[outTok_stateTransMap.first].push_back (IndexedTrans (src_trans.second, src_trans.first, dest, inTok_outStateTransMap.first));
	  ++nTrans;
	}

  const OutputIndex storageColumns = blockSize + nCheckpoints - 1;
  LogThisAt(8,"Block size is " << blockSize << " columns, # of checkpoint columns is " << nCheckpoints << endl);
  LogThisAt(7,"Creating " << storageColumns << "-column * " << nStates << "-state matrix" << endl);
  columnStorage.resize (storageColumns, vguard<double> (nStates, -numeric_limits<double>::infinity()));
}
<|endoftext|>