<commit_before>//===--- IRGen.cpp - Swift LLVM IR Generation -----------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
//  This file implements the entrypoints into IR generation.
//
//===----------------------------------------------------------------------===//

#include "swift/Subsystems.h"
#include "swift/IRGen/Options.h"
#include "swift/AST/AST.h"
#include "swift/AST/Diagnostics.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/PassManager.h"
#include "llvm/Analysis/Verifier.h"
#include "llvm/Assembly/PrintModulePass.h"
#include "llvm/Bitcode/ReaderWriter.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Transforms/IPO/PassManagerBuilder.h"
#include "llvm/Transforms/IPO.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Linker.h"

#include "IRGenModule.h"

using namespace swift;
using namespace irgen;
using namespace llvm;

static bool isBinaryOutput(OutputKind kind) {
  switch (kind) {
  case OutputKind::Module:
  case OutputKind::LLVMAssembly:
  case OutputKind::NativeAssembly:
    return false;
  case OutputKind::LLVMBitcode:
  case OutputKind::ObjectFile:
    return true;
  }
  llvm_unreachable("bad output kind!");
}

static void addSwiftARCOptPass(const PassManagerBuilder &Builder,
                               PassManagerBase &PM) {
  if (Builder.OptLevel > 0)
    PM.add(createSwiftARCOptPass());
}

static void addSwiftExpandPass(const PassManagerBuilder &Builder,
                               PassManagerBase &PM) {
  if (Builder.OptLevel > 0)
    PM.add(createSwiftARCExpandPass());
}

void swift::performIRGeneration(Options &Opts, llvm::Module *Module,
                                TranslationUnit *TU,
                                SILModule *SILMod,
                                unsigned StartElem) {
  assert(!TU->Ctx.hadError());

  std::unique_ptr<LLVMContext> Context;
  std::unique_ptr<llvm::Module> ModuleOwner;
  if (!Module) {
    Context.reset(new LLVMContext);
    ModuleOwner.reset(new llvm::Module(Opts.OutputFilename, *Context));
    Module = ModuleOwner.get();
  }

  Module->setTargetTriple(Opts.Triple);

  std::string Error;
  const Target *Target =
    TargetRegistry::lookupTarget(Opts.Triple, Error);
  if (!Target) {
    TU->Ctx.Diags.diagnose(SourceLoc(), diag::no_llvm_target,
                           Opts.Triple, Error);
    return;
  }

  // The integer values 0-3 map exactly to the values of this enum.
  CodeGenOpt::Level OptLevel = static_cast<CodeGenOpt::Level>(Opts.OptLevel);

  // Set up TargetOptions.
  // Things that maybe we should collect from the command line:
  //   - CPU
  //   - features
  //   - relocation model
  //   - code model
  TargetOptions TargetOpts;
//  TargetOpts.NoFramePointerElimNonLeaf = true;

  // Create a target machine.
  TargetMachine *TargetMachine
    = Target->createTargetMachine(Opts.Triple, /*cpu*/ "generic",
                                  /*features*/ "",
                                  TargetOpts, Reloc::Default,
                                  CodeModel::Default, OptLevel);
  if (!TargetMachine) {
    TU->Ctx.Diags.diagnose(SourceLoc(), diag::no_llvm_target,
                           Opts.Triple, "no LLVM target machine");
    return;
  }

  // Set the module's string representation.
  const llvm::DataLayout *DataLayout = TargetMachine->getDataLayout();
  assert(DataLayout && "target machine didn't set DatLayout?");
  Module->setDataLayout(DataLayout->getStringRepresentation());

  // Emit the translation unit.
  IRGenModule IRM(TU->Ctx, Opts, *Module, *DataLayout, SILMod);
  IRM.emitTranslationUnit(TU, StartElem);

  DEBUG(llvm::dbgs() << "module before passes:\n";
        IRM.Module.dump());

  // Bail out if there are any errors.
  if (TU->Ctx.hadError()) return;

  // Ugly standard library optimization hack, part 1: pull in the relevant
  // IR from swift.swift.
  // FIXME: We should pre-generate a swift.bc; it would be substantially
  // faster we could skip both generating and optimizing the standard library.
  // FIXME: Figure out how to get this working for the REPL.
  bool UseStandardLibraryHack = Opts.OptLevel != 0;
  if (UseStandardLibraryHack) {
    for (auto ModPair : TU->getImportedModules()) {
      if (isa<BuiltinModule>(ModPair.second) ||
          isa<LoadedModule>(ModPair.second))
        continue;

      TranslationUnit *SubTU = cast<TranslationUnit>(ModPair.second);

      if (SubTU->Name.str() == "swift") {
        Options SubOpts;
        SubOpts.Triple = Opts.Triple;
        SubOpts.OutputKind = OutputKind::Module;
        SubOpts.OptLevel = 2;
	SubOpts.DebugInfo = Opts.DebugInfo;
        llvm::Module SubModule(SubTU->Name.str(), Module->getContext());
        performCaptureAnalysis(SubTU);
        performIRGeneration(SubOpts, &SubModule, SubTU, SILMod);

        SmallVector<GlobalValue*, 8> DeclsToErase;
        for (llvm::Function &F : SubModule)
          if (!F.isDeclaration() && F.hasExternalLinkage())
            F.setLinkage(llvm::GlobalValue::AvailableExternallyLinkage);
        for (llvm::GlobalVariable &G : SubModule.getGlobalList()) {
          if (!G.isDeclaration() && G.hasExternalLinkage())
            G.setLinkage(llvm::GlobalValue::AvailableExternallyLinkage);
          if (G.hasAppendingLinkage())
            DeclsToErase.push_back(&G);
        }
        for (llvm::GlobalAlias &A : SubModule.getAliasList())
          if (!A.isDeclaration() && A.hasExternalLinkage())
            A.setLinkage(llvm::GlobalValue::AvailableExternallyLinkage);

        for (auto G : DeclsToErase)
          G->eraseFromParent();

        std::string ErrorMessage;
        if (llvm::Linker::LinkModules(Module, &SubModule,
                                      llvm::Linker::DestroySource,
                                      &ErrorMessage)) {
          llvm::errs() << "Error linking swift modules\n";
          llvm::errs() << ErrorMessage << "\n";
          return;
        }
      }
    }
  }

  llvm::OwningPtr<raw_fd_ostream> RawOS;
  formatted_raw_ostream FormattedOS;
  if (!Opts.OutputFilename.empty()) {
    // Try to open the output file.  Clobbering an existing file is fine.
    // Open in binary mode if we're doing binary output.
    llvm::sys::fs::OpenFlags OSFlags = llvm::sys::fs::F_None;
    if (isBinaryOutput(Opts.OutputKind))
      OSFlags |= llvm::sys::fs::F_Binary;
    RawOS.reset(new raw_fd_ostream(Opts.OutputFilename.c_str(),
                                   Error, OSFlags));
    if (RawOS->has_error() || !Error.empty()) {
      TU->Ctx.Diags.diagnose(SourceLoc(), diag::error_opening_output,
                             Opts.OutputFilename, Error);
      RawOS->clear_error();
      return;
    }

    // Most output kinds want a formatted output stream.  It's not clear
    // why writing an object file does.
    if (Opts.OutputKind != OutputKind::LLVMBitcode)
      FormattedOS.setStream(*RawOS, formatted_raw_ostream::PRESERVE_STREAM);
  }

  // Set up a pipeline.
  PassManagerBuilder PMBuilder;
  PMBuilder.OptLevel = Opts.OptLevel;
  if (Opts.OptLevel != 0)
    PMBuilder.Inliner = llvm::createFunctionInliningPass(200);

  // If the optimizer is enabled, we run the ARCOpt pass in the scalar optimizer
  // and the Expand pass as late as possible.
  PMBuilder.addExtension(PassManagerBuilder::EP_ScalarOptimizerLate,
                         addSwiftARCOptPass);
  PMBuilder.addExtension(PassManagerBuilder::EP_OptimizerLast,
                         addSwiftExpandPass);

  // Configure the function passes.
  FunctionPassManager FunctionPasses(Module);
  FunctionPasses.add(new llvm::DataLayout(*DataLayout));
  if (Opts.Verify)
    FunctionPasses.add(createVerifierPass());
  PMBuilder.populateFunctionPassManager(FunctionPasses);

  // Run the function passes.
  FunctionPasses.doInitialization();
  for (auto I = Module->begin(), E = Module->end(); I != E; ++I)
    if (!I->isDeclaration())
      FunctionPasses.run(*I);
  FunctionPasses.doFinalization();

  // Configure the module passes.
  PassManager ModulePasses;
  ModulePasses.add(new llvm::DataLayout(*DataLayout));
  PMBuilder.populateModulePassManager(ModulePasses);
  if (Opts.Verify)
    ModulePasses.add(createVerifierPass());

  // Do it.
  ModulePasses.run(*Module);

  PassManager EmitPasses;

  // Ugly standard library optimization hack, part 2: eliminate the crap
  // we don't need anymore from the module.
  // FIXME: It would be nice if LLVM provided a simpler way to do this...
  if (UseStandardLibraryHack) {
    for (llvm::Function &F : *Module)
      if (F.hasAvailableExternallyLinkage()) {
        F.deleteBody();
        F.setLinkage(llvm::GlobalValue::ExternalLinkage);
      }
    for (llvm::GlobalVariable &G : Module->getGlobalList())
      if (G.hasAvailableExternallyLinkage()) {
        G.setInitializer(nullptr);
        G.setLinkage(llvm::GlobalValue::ExternalLinkage);
      }
    for (llvm::GlobalAlias &A : Module->getAliasList())
      if (A.hasAvailableExternallyLinkage()) {
        A.setAliasee(nullptr);
        A.setLinkage(llvm::GlobalValue::ExternalLinkage);
      }
    bool changed;
    do {
      std::vector<llvm::GlobalValue *> vals;
      for (llvm::GlobalVariable &G : Module->getGlobalList()) {
        G.removeDeadConstantUsers();
        if ((G.hasLocalLinkage() || G.isDeclaration()) && G.use_empty()) {
          vals.push_back(&G);
        }
      }
      for (llvm::Function &F : *Module) {
        F.removeDeadConstantUsers();
        if ((F.hasLocalLinkage() || F.isDeclaration()) && F.use_empty()) {
          vals.push_back(&F);
        }
      }
      for (llvm::GlobalAlias &A : Module->getAliasList()) {
        A.removeDeadConstantUsers();
        if ((A.hasLocalLinkage() || A.isDeclaration()) && A.use_empty()) {
          vals.push_back(&A);
        }
      }
      for (auto val : vals) val->eraseFromParent();
      changed = !vals.empty();
    } while (changed);
  }

  // Set up the final emission passes.
  switch (Opts.OutputKind) {
  case OutputKind::Module:
    break;
  case OutputKind::LLVMAssembly:
    EmitPasses.add(createPrintModulePass(&FormattedOS));
    break;
  case OutputKind::LLVMBitcode:
    EmitPasses.add(createBitcodeWriterPass(*RawOS));
    break;
  case OutputKind::NativeAssembly:
  case OutputKind::ObjectFile: {
    TargetMachine::CodeGenFileType FileType;
    FileType = (Opts.OutputKind == OutputKind::NativeAssembly
                  ? TargetMachine::CGFT_AssemblyFile
                  : TargetMachine::CGFT_ObjectFile);

    if (TargetMachine->addPassesToEmitFile(EmitPasses, FormattedOS,
                                           FileType, !Opts.Verify)) {
      TU->Ctx.Diags.diagnose(SourceLoc(), diag::error_codegen_init_fail);
      return;
    }
    break;
  }
  }

  EmitPasses.run(*Module);
}
<commit_msg>typo.<commit_after>//===--- IRGen.cpp - Swift LLVM IR Generation -----------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
//  This file implements the entrypoints into IR generation.
//
//===----------------------------------------------------------------------===//

#include "swift/Subsystems.h"
#include "swift/IRGen/Options.h"
#include "swift/AST/AST.h"
#include "swift/AST/Diagnostics.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/PassManager.h"
#include "llvm/Analysis/Verifier.h"
#include "llvm/Assembly/PrintModulePass.h"
#include "llvm/Bitcode/ReaderWriter.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Transforms/IPO/PassManagerBuilder.h"
#include "llvm/Transforms/IPO.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Linker.h"

#include "IRGenModule.h"

using namespace swift;
using namespace irgen;
using namespace llvm;

static bool isBinaryOutput(OutputKind kind) {
  switch (kind) {
  case OutputKind::Module:
  case OutputKind::LLVMAssembly:
  case OutputKind::NativeAssembly:
    return false;
  case OutputKind::LLVMBitcode:
  case OutputKind::ObjectFile:
    return true;
  }
  llvm_unreachable("bad output kind!");
}

static void addSwiftARCOptPass(const PassManagerBuilder &Builder,
                               PassManagerBase &PM) {
  if (Builder.OptLevel > 0)
    PM.add(createSwiftARCOptPass());
}

static void addSwiftExpandPass(const PassManagerBuilder &Builder,
                               PassManagerBase &PM) {
  if (Builder.OptLevel > 0)
    PM.add(createSwiftARCExpandPass());
}

void swift::performIRGeneration(Options &Opts, llvm::Module *Module,
                                TranslationUnit *TU,
                                SILModule *SILMod,
                                unsigned StartElem) {
  assert(!TU->Ctx.hadError());

  std::unique_ptr<LLVMContext> Context;
  std::unique_ptr<llvm::Module> ModuleOwner;
  if (!Module) {
    Context.reset(new LLVMContext);
    ModuleOwner.reset(new llvm::Module(Opts.OutputFilename, *Context));
    Module = ModuleOwner.get();
  }

  Module->setTargetTriple(Opts.Triple);

  std::string Error;
  const Target *Target =
    TargetRegistry::lookupTarget(Opts.Triple, Error);
  if (!Target) {
    TU->Ctx.Diags.diagnose(SourceLoc(), diag::no_llvm_target,
                           Opts.Triple, Error);
    return;
  }

  // The integer values 0-3 map exactly to the values of this enum.
  CodeGenOpt::Level OptLevel = static_cast<CodeGenOpt::Level>(Opts.OptLevel);

  // Set up TargetOptions.
  // Things that maybe we should collect from the command line:
  //   - CPU
  //   - features
  //   - relocation model
  //   - code model
  TargetOptions TargetOpts;
//  TargetOpts.NoFramePointerElimNonLeaf = true;

  // Create a target machine.
  TargetMachine *TargetMachine
    = Target->createTargetMachine(Opts.Triple, /*cpu*/ "generic",
                                  /*features*/ "",
                                  TargetOpts, Reloc::Default,
                                  CodeModel::Default, OptLevel);
  if (!TargetMachine) {
    TU->Ctx.Diags.diagnose(SourceLoc(), diag::no_llvm_target,
                           Opts.Triple, "no LLVM target machine");
    return;
  }

  // Set the module's string representation.
  const llvm::DataLayout *DataLayout = TargetMachine->getDataLayout();
  assert(DataLayout && "target machine didn't set DataLayout?");
  Module->setDataLayout(DataLayout->getStringRepresentation());

  // Emit the translation unit.
  IRGenModule IRM(TU->Ctx, Opts, *Module, *DataLayout, SILMod);
  IRM.emitTranslationUnit(TU, StartElem);

  DEBUG(llvm::dbgs() << "module before passes:\n";
        IRM.Module.dump());

  // Bail out if there are any errors.
  if (TU->Ctx.hadError()) return;

  // Ugly standard library optimization hack, part 1: pull in the relevant
  // IR from swift.swift.
  // FIXME: We should pre-generate a swift.bc; it would be substantially
  // faster we could skip both generating and optimizing the standard library.
  // FIXME: Figure out how to get this working for the REPL.
  bool UseStandardLibraryHack = Opts.OptLevel != 0;
  if (UseStandardLibraryHack) {
    for (auto ModPair : TU->getImportedModules()) {
      if (isa<BuiltinModule>(ModPair.second) ||
          isa<LoadedModule>(ModPair.second))
        continue;

      TranslationUnit *SubTU = cast<TranslationUnit>(ModPair.second);

      if (SubTU->Name.str() == "swift") {
        Options SubOpts;
        SubOpts.Triple = Opts.Triple;
        SubOpts.OutputKind = OutputKind::Module;
        SubOpts.OptLevel = 2;
	SubOpts.DebugInfo = Opts.DebugInfo;
        llvm::Module SubModule(SubTU->Name.str(), Module->getContext());
        performCaptureAnalysis(SubTU);
        performIRGeneration(SubOpts, &SubModule, SubTU, SILMod);

        SmallVector<GlobalValue*, 8> DeclsToErase;
        for (llvm::Function &F : SubModule)
          if (!F.isDeclaration() && F.hasExternalLinkage())
            F.setLinkage(llvm::GlobalValue::AvailableExternallyLinkage);
        for (llvm::GlobalVariable &G : SubModule.getGlobalList()) {
          if (!G.isDeclaration() && G.hasExternalLinkage())
            G.setLinkage(llvm::GlobalValue::AvailableExternallyLinkage);
          if (G.hasAppendingLinkage())
            DeclsToErase.push_back(&G);
        }
        for (llvm::GlobalAlias &A : SubModule.getAliasList())
          if (!A.isDeclaration() && A.hasExternalLinkage())
            A.setLinkage(llvm::GlobalValue::AvailableExternallyLinkage);

        for (auto G : DeclsToErase)
          G->eraseFromParent();

        std::string ErrorMessage;
        if (llvm::Linker::LinkModules(Module, &SubModule,
                                      llvm::Linker::DestroySource,
                                      &ErrorMessage)) {
          llvm::errs() << "Error linking swift modules\n";
          llvm::errs() << ErrorMessage << "\n";
          return;
        }
      }
    }
  }

  llvm::OwningPtr<raw_fd_ostream> RawOS;
  formatted_raw_ostream FormattedOS;
  if (!Opts.OutputFilename.empty()) {
    // Try to open the output file.  Clobbering an existing file is fine.
    // Open in binary mode if we're doing binary output.
    llvm::sys::fs::OpenFlags OSFlags = llvm::sys::fs::F_None;
    if (isBinaryOutput(Opts.OutputKind))
      OSFlags |= llvm::sys::fs::F_Binary;
    RawOS.reset(new raw_fd_ostream(Opts.OutputFilename.c_str(),
                                   Error, OSFlags));
    if (RawOS->has_error() || !Error.empty()) {
      TU->Ctx.Diags.diagnose(SourceLoc(), diag::error_opening_output,
                             Opts.OutputFilename, Error);
      RawOS->clear_error();
      return;
    }

    // Most output kinds want a formatted output stream.  It's not clear
    // why writing an object file does.
    if (Opts.OutputKind != OutputKind::LLVMBitcode)
      FormattedOS.setStream(*RawOS, formatted_raw_ostream::PRESERVE_STREAM);
  }

  // Set up a pipeline.
  PassManagerBuilder PMBuilder;
  PMBuilder.OptLevel = Opts.OptLevel;
  if (Opts.OptLevel != 0)
    PMBuilder.Inliner = llvm::createFunctionInliningPass(200);

  // If the optimizer is enabled, we run the ARCOpt pass in the scalar optimizer
  // and the Expand pass as late as possible.
  PMBuilder.addExtension(PassManagerBuilder::EP_ScalarOptimizerLate,
                         addSwiftARCOptPass);
  PMBuilder.addExtension(PassManagerBuilder::EP_OptimizerLast,
                         addSwiftExpandPass);

  // Configure the function passes.
  FunctionPassManager FunctionPasses(Module);
  FunctionPasses.add(new llvm::DataLayout(*DataLayout));
  if (Opts.Verify)
    FunctionPasses.add(createVerifierPass());
  PMBuilder.populateFunctionPassManager(FunctionPasses);

  // Run the function passes.
  FunctionPasses.doInitialization();
  for (auto I = Module->begin(), E = Module->end(); I != E; ++I)
    if (!I->isDeclaration())
      FunctionPasses.run(*I);
  FunctionPasses.doFinalization();

  // Configure the module passes.
  PassManager ModulePasses;
  ModulePasses.add(new llvm::DataLayout(*DataLayout));
  PMBuilder.populateModulePassManager(ModulePasses);
  if (Opts.Verify)
    ModulePasses.add(createVerifierPass());

  // Do it.
  ModulePasses.run(*Module);

  PassManager EmitPasses;

  // Ugly standard library optimization hack, part 2: eliminate the crap
  // we don't need anymore from the module.
  // FIXME: It would be nice if LLVM provided a simpler way to do this...
  if (UseStandardLibraryHack) {
    for (llvm::Function &F : *Module)
      if (F.hasAvailableExternallyLinkage()) {
        F.deleteBody();
        F.setLinkage(llvm::GlobalValue::ExternalLinkage);
      }
    for (llvm::GlobalVariable &G : Module->getGlobalList())
      if (G.hasAvailableExternallyLinkage()) {
        G.setInitializer(nullptr);
        G.setLinkage(llvm::GlobalValue::ExternalLinkage);
      }
    for (llvm::GlobalAlias &A : Module->getAliasList())
      if (A.hasAvailableExternallyLinkage()) {
        A.setAliasee(nullptr);
        A.setLinkage(llvm::GlobalValue::ExternalLinkage);
      }
    bool changed;
    do {
      std::vector<llvm::GlobalValue *> vals;
      for (llvm::GlobalVariable &G : Module->getGlobalList()) {
        G.removeDeadConstantUsers();
        if ((G.hasLocalLinkage() || G.isDeclaration()) && G.use_empty()) {
          vals.push_back(&G);
        }
      }
      for (llvm::Function &F : *Module) {
        F.removeDeadConstantUsers();
        if ((F.hasLocalLinkage() || F.isDeclaration()) && F.use_empty()) {
          vals.push_back(&F);
        }
      }
      for (llvm::GlobalAlias &A : Module->getAliasList()) {
        A.removeDeadConstantUsers();
        if ((A.hasLocalLinkage() || A.isDeclaration()) && A.use_empty()) {
          vals.push_back(&A);
        }
      }
      for (auto val : vals) val->eraseFromParent();
      changed = !vals.empty();
    } while (changed);
  }

  // Set up the final emission passes.
  switch (Opts.OutputKind) {
  case OutputKind::Module:
    break;
  case OutputKind::LLVMAssembly:
    EmitPasses.add(createPrintModulePass(&FormattedOS));
    break;
  case OutputKind::LLVMBitcode:
    EmitPasses.add(createBitcodeWriterPass(*RawOS));
    break;
  case OutputKind::NativeAssembly:
  case OutputKind::ObjectFile: {
    TargetMachine::CodeGenFileType FileType;
    FileType = (Opts.OutputKind == OutputKind::NativeAssembly
                  ? TargetMachine::CGFT_AssemblyFile
                  : TargetMachine::CGFT_ObjectFile);

    if (TargetMachine->addPassesToEmitFile(EmitPasses, FormattedOS,
                                           FileType, !Opts.Verify)) {
      TU->Ctx.Diags.diagnose(SourceLoc(), diag::error_codegen_init_fail);
      return;
    }
    break;
  }
  }

  EmitPasses.run(*Module);
}
<|endoftext|>


<commit_before>/*
 *  Agent.cpp
 *  openc2e
 *
 *  Created by Alyssa Milburn on Tue May 25 2004.
 *  Copyright (c) 2004 Alyssa Milburn. All rights reserved.
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser 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
 *  Lesser General Public License for more details.
 *
 */

#include "Agent.h"
#include "World.h"
#include "physics.h"
#include <iostream>
#include <sstream>
#include "caosVM.h"
#include "SDLBackend.h"

Agent::Agent(unsigned char f, unsigned char g, unsigned short s, unsigned int p) :
  visible(true), family(f), genus(g), species(s), zorder(p), vm(0), timerrate(0) {
	velx.setFloat(0.0f);
	vely.setFloat(0.0f);
	accg = 0.3f;
	range = 500;
	sufferphysics = false;
	x = 0.0f; y = 0.0f;
	clac[0] = 1; // activate 1
	clik = -1;

	// AgentRef stuff
	self.ref = this;
	self.next = self.prev = &self;

	dying = false;
	unid = -1;

	zorder_iter = world.agents.insert(this);

	soundslot = 0;
}

void Agent::zotstack() {
	std::list<caosVM *>::iterator i = vmstack.begin();
	while (i != vmstack.end()) {
		world.freeVM(*i);
	}
	vmstack.clear();
}

Agent::~Agent() {
	world.agents.erase(zorder_iter);
	if (vm)
		world.freeVM(vm);
	zotstack();
	zotrefs();
	if (unid != -1)
		world.freeUNID(unid);
}

void Agent::moveTo(float _x, float _y) {
	x = _x; y = _y;
}

script *Agent::findScript(unsigned short event) {
	return world.scriptorium.getScript(family, genus, species, event);
}

void Agent::fireScript(unsigned short event) {
	if (dying) return;

	script *s = findScript(event);
	if (!vm) vm = world.getVM(this);
	if (vm->fireScript(s, (event == 9))) {
		vm->setTarg(this);
		zotstack();
	}

	// This slows us down too much :)
#if 0
	std::cout << "Agent::fireScript fired " << (unsigned int)family << " " << (unsigned int)genus << " " << species << " ";
	const std::string n = world.catalogue.getAgentName(family, genus, species);
	if (n.size())
		std::cout << "(" << n << ") ";
	std::cout << (unsigned int)event << std::endl;
#endif
}

void Agent::positionAudio(SoundSlot *slot) {
	assert(slot);

	float xoffset = x - world.camera.getXCentre();
	float yoffset = y - world.camera.getYCentre();
	int distance = (sqrt(xoffset*xoffset + yoffset*yoffset) * 1000) / 255;
	int angle = (atanf(abs(yoffset) / abs(xoffset)) / (2*M_PI)) * 360;
	if (xoffset < 0) angle += 180;
	if (yoffset < 0) angle += 90;

	slot->adjustPanning(angle, distance);
}

void Agent::tick() {
	if (dying) return;

	if (soundslot) positionAudio(soundslot);

	if (sufferphysics && accg) {
		float newvely = vely.floatValue + accg;
		float destx = x + velx.floatValue;
		float desty = y + newvely;
		//std::cout << x << ", " << y << ": " << destx << ", " << desty << "! " << accg << "\n";
		Room *r1 = world.map.roomAt((unsigned int)x, (unsigned int)y);
		if (!r1) {
//			std::cout << "not doing physics on agent " << identify() << ", outside room system!\n";
		}
		Room *r2 = world.map.roomAt((unsigned int)destx + getWidth(), (unsigned int)desty + getHeight());
		Room *r3 = world.map.roomAt((unsigned int)destx, (unsigned int)desty);

		//if (r1 && (r1 == r2) && (r2 == r3)) {
			// If the object is already in a room, and the destination point is also in the room,
			// for now we don't bother checking. We *should*, because (crazily) it could take a
			// path out of the room and back in again, once we're doing more than dumb velocity.
		//	vely.setFloat(newvely);
		//	moveTo(destx, desty);
		/*} else */ if (r1) { // if we *are* actually in a room
			// Otherwise, check the motion pixel-by-pixel. Oh boy.

			bool moved = false, collided = false;

			int ix = x, iy = y, idestx = destx, idesty = desty;
			int dx = (ix < idestx ? 1 : -1);
			int dy = (iy < idesty ? 1 : -1);

			while (ix != idestx || iy != idesty) {
				// We just alternate here. There's probably a more
				// accurate method, but meh

				if (iy != idesty) {
					iy += dy;

					Room *room1 = world.map.roomAt(ix, iy);
					Room *room2 = world.map.roomAt(ix + getWidth(), iy + getHeight());
					if ((!room1) || (!room2)) {
						iy -= dy;
						collided = true;
						break;
					}
				}

				if (ix != idestx) {
					ix += dx;

					Room *room1 = world.map.roomAt(ix, iy);
					Room *room2 = world.map.roomAt(ix + getWidth(), iy + getHeight());
					if ((!room1) || (!room2)) {
						ix -= dx;
						collided = true;
						break;
					}
				}
				moved = true;
			}

			vely.setFloat(newvely);

			if (moved) { // if we did actually try and go somewhere
				// TODO: this totally destroys floatness!
				x = ix;
				y = iy;

				if (collided) {
					fireScript(6);
					if (vm) vm->setVariables(velx, vely);
					vely.setFloat(0);
				}
			}
		}
	} else {
		if (vely.hasDecimal())
			y = y + vely.getFloat();
		if (velx.hasDecimal())
			x = x + velx.getFloat();
	}

	if (timerrate) {
		tickssincelasttimer++;
		if (tickssincelasttimer == timerrate) {
			fireScript(9);
			tickssincelasttimer = 0;
		}
	}

	if (vm) {
		vm->tick();
		if (vm->stopped()) {
			world.freeVM(vm);
			vm = NULL;
		}
	}
	if (!vm && !vmstack.empty()) {
		vm = vmstack.front();
		vmstack.pop_front();
	}
}

void Agent::kill() {
	// Should we remove from the ENUM etc stuff?
	assert(!dying);
	dying = true; // what a world, what a world...
	if (vm)
		vm->stop();
	zotstack();
	zotrefs();
	world.killqueue.push_back(this);
}

void Agent::zotrefs() {
	while (self.next != &self)
		self.next->clear();
}

void Agent::setZOrder(unsigned int z) {
	zorder = z;
	world.agents.erase(zorder_iter);
	zorder_iter = world.agents.insert(this);
}

int Agent::getUNID() {
	  if (unid != -1)
			  return unid;
	  return unid = world.getUNID(this);
}

std::string Agent::identify() const {
	std::ostringstream o;
	o << (int)family << " " << (int)genus << " " << species << " ";
	const std::string n = world.catalogue.getAgentName(family, genus, species);
	if (n.size())
		o << "(" + n + ")";
	if (unid != -1)
		o << " unid " << unid;
	else
		o << " (no unid assigned)";
	return o.str();
}

bool agentzorder::operator ()(const Agent *s1, const Agent *s2) const {
	return s1->zorder < s2->zorder;
}

void Agent::pushVM(caosVM *newvm) {
	assert(newvm);
	if (vm)
		vmstack.push_front(vm);
	vm = newvm;
}

void Agent::stopScript() {
	zotstack();
	vm->stop();
}

/* vim: set noet: */
<commit_msg>whoops! do physics for all agents who want it, even without accg!<commit_after>/*
 *  Agent.cpp
 *  openc2e
 *
 *  Created by Alyssa Milburn on Tue May 25 2004.
 *  Copyright (c) 2004 Alyssa Milburn. All rights reserved.
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser 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
 *  Lesser General Public License for more details.
 *
 */

#include "Agent.h"
#include "World.h"
#include "physics.h"
#include <iostream>
#include <sstream>
#include "caosVM.h"
#include "SDLBackend.h"

Agent::Agent(unsigned char f, unsigned char g, unsigned short s, unsigned int p) :
  visible(true), family(f), genus(g), species(s), zorder(p), vm(0), timerrate(0) {
	velx.setFloat(0.0f);
	vely.setFloat(0.0f);
	accg = 0.3f;
	range = 500;
	sufferphysics = false;
	x = 0.0f; y = 0.0f;
	clac[0] = 1; // activate 1
	clik = -1;

	// AgentRef stuff
	self.ref = this;
	self.next = self.prev = &self;

	dying = false;
	unid = -1;

	zorder_iter = world.agents.insert(this);

	soundslot = 0;
}

void Agent::zotstack() {
	std::list<caosVM *>::iterator i = vmstack.begin();
	while (i != vmstack.end()) {
		world.freeVM(*i);
	}
	vmstack.clear();
}

Agent::~Agent() {
	world.agents.erase(zorder_iter);
	if (vm)
		world.freeVM(vm);
	zotstack();
	zotrefs();
	if (unid != -1)
		world.freeUNID(unid);
}

void Agent::moveTo(float _x, float _y) {
	x = _x; y = _y;
}

script *Agent::findScript(unsigned short event) {
	return world.scriptorium.getScript(family, genus, species, event);
}

void Agent::fireScript(unsigned short event) {
	if (dying) return;

	script *s = findScript(event);
	if (!vm) vm = world.getVM(this);
	if (vm->fireScript(s, (event == 9))) {
		vm->setTarg(this);
		zotstack();
	}

	// This slows us down too much :)
#if 0
	std::cout << "Agent::fireScript fired " << (unsigned int)family << " " << (unsigned int)genus << " " << species << " ";
	const std::string n = world.catalogue.getAgentName(family, genus, species);
	if (n.size())
		std::cout << "(" << n << ") ";
	std::cout << (unsigned int)event << std::endl;
#endif
}

void Agent::positionAudio(SoundSlot *slot) {
	assert(slot);

	float xoffset = x - world.camera.getXCentre();
	float yoffset = y - world.camera.getYCentre();
	int distance = (sqrt(xoffset*xoffset + yoffset*yoffset) * 1000) / 255;
	int angle = (atanf(abs(yoffset) / abs(xoffset)) / (2*M_PI)) * 360;
	if (xoffset < 0) angle += 180;
	if (yoffset < 0) angle += 90;

	slot->adjustPanning(angle, distance);
}

void Agent::tick() {
	if (dying) return;

	if (soundslot) positionAudio(soundslot);

	if (sufferphysics) {
		float newvely = vely.floatValue + accg;
		float destx = x + velx.floatValue;
		float desty = y + newvely;
		//std::cout << x << ", " << y << ": " << destx << ", " << desty << "! " << accg << "\n";
		Room *r1 = world.map.roomAt((unsigned int)x, (unsigned int)y);
		if (!r1) {
//			std::cout << "not doing physics on agent " << identify() << ", outside room system!\n";
		}
		Room *r2 = world.map.roomAt((unsigned int)destx + getWidth(), (unsigned int)desty + getHeight());
		Room *r3 = world.map.roomAt((unsigned int)destx, (unsigned int)desty);

		//if (r1 && (r1 == r2) && (r2 == r3)) {
			// If the object is already in a room, and the destination point is also in the room,
			// for now we don't bother checking. We *should*, because (crazily) it could take a
			// path out of the room and back in again, once we're doing more than dumb velocity.
		//	vely.setFloat(newvely);
		//	moveTo(destx, desty);
		/*} else */ if (r1) { // if we *are* actually in a room
			// Otherwise, check the motion pixel-by-pixel. Oh boy.

			bool moved = false, collided = false;

			int ix = x, iy = y, idestx = destx, idesty = desty;
			int dx = (ix < idestx ? 1 : -1);
			int dy = (iy < idesty ? 1 : -1);

			while (ix != idestx || iy != idesty) {
				// We just alternate here. There's probably a more
				// accurate method, but meh

				if (iy != idesty) {
					iy += dy;

					Room *room1 = world.map.roomAt(ix, iy);
					Room *room2 = world.map.roomAt(ix + getWidth(), iy + getHeight());
					if ((!room1) || (!room2)) {
						iy -= dy;
						collided = true;
						break;
					}
				}

				if (ix != idestx) {
					ix += dx;

					Room *room1 = world.map.roomAt(ix, iy);
					Room *room2 = world.map.roomAt(ix + getWidth(), iy + getHeight());
					if ((!room1) || (!room2)) {
						ix -= dx;
						collided = true;
						break;
					}
				}
				moved = true;
			}

			vely.setFloat(newvely);

			if (moved) { // if we did actually try and go somewhere
				// TODO: this totally destroys floatness!
				x = ix;
				y = iy;

				if (collided) {
					fireScript(6);
					if (vm) vm->setVariables(velx, vely);
					vely.setFloat(0);
				}
			}
		}
	} else {
		if (vely.hasDecimal())
			y = y + vely.getFloat();
		if (velx.hasDecimal())
			x = x + velx.getFloat();
	}

	if (timerrate) {
		tickssincelasttimer++;
		if (tickssincelasttimer == timerrate) {
			fireScript(9);
			tickssincelasttimer = 0;
		}
	}

	if (vm) {
		vm->tick();
		if (vm->stopped()) {
			world.freeVM(vm);
			vm = NULL;
		}
	}
	if (!vm && !vmstack.empty()) {
		vm = vmstack.front();
		vmstack.pop_front();
	}
}

void Agent::kill() {
	// Should we remove from the ENUM etc stuff?
	assert(!dying);
	dying = true; // what a world, what a world...
	if (vm)
		vm->stop();
	zotstack();
	zotrefs();
	world.killqueue.push_back(this);
}

void Agent::zotrefs() {
	while (self.next != &self)
		self.next->clear();
}

void Agent::setZOrder(unsigned int z) {
	zorder = z;
	world.agents.erase(zorder_iter);
	zorder_iter = world.agents.insert(this);
}

int Agent::getUNID() {
	  if (unid != -1)
			  return unid;
	  return unid = world.getUNID(this);
}

std::string Agent::identify() const {
	std::ostringstream o;
	o << (int)family << " " << (int)genus << " " << species << " ";
	const std::string n = world.catalogue.getAgentName(family, genus, species);
	if (n.size())
		o << "(" + n + ")";
	if (unid != -1)
		o << " unid " << unid;
	else
		o << " (no unid assigned)";
	return o.str();
}

bool agentzorder::operator ()(const Agent *s1, const Agent *s2) const {
	return s1->zorder < s2->zorder;
}

void Agent::pushVM(caosVM *newvm) {
	assert(newvm);
	if (vm)
		vmstack.push_front(vm);
	vm = newvm;
}

void Agent::stopScript() {
	zotstack();
	vm->stop();
}

/* vim: set noet: */
<|endoftext|>


<commit_before>#include <iostream>
#include <filesystem>
#include <vector>
#include <map>
#include <string>
#include <fstream>

using namespace std;

#if (__cplusplus >= 201703L && (!defined(__GNUC__) || (__GNUC__*100+__GNUC_MINOR__) >= 800))
#include <filesystem>
namespace fs = std::filesystem;
#define USE_FILESYSTEM
#elif !defined(__MINGW32__) && !defined(__ANDROID__) && (!defined(__GNUC__) || (__GNUC__*100+__GNUC_MINOR__) >= 503)
#define USE_FILESYSTEM
#ifdef WIN32
#include <filesystem>
namespace fs = std::experimental::filesystem;
#else
#include <experimental/filesystem>
namespace fs = std::experimental::filesystem;
#endif
#else
//for mac
#include <filesystem>
namespace fs = std::__fs::filesystem;
#endif

enum class Platform {
    platform_windows,    // platform_ prefix to avoid #define subsitutions on linux
    platform_osx,
    platform_linux,
};

constexpr Platform buildPlatform =
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)
Platform::platform_windows
#elif __APPLE__
#include <TargetConditionals.h>
    #if TARGET_OS_MAC
Platform::platform_osx
    #endif
#elif __linux__
Platform::platform_linux
#endif
; // error here: platform not detected from supported list

bool build = false;
bool setup = false;
bool removeUnusedPorts = false;
bool noPkgConfig = false;
fs::path portsFile;
fs::path sdkRootPath;
fs::path patchPath;
string triplet;

map<string, string> ports;
map<string, fs::path> patches;

fs::path initialDir = fs::current_path();
fs::path vcpkgDir = fs::current_path() / "vcpkg";
fs::path cloneDir = fs::current_path() / "vcpkg_clone";

string platformToString(Platform p);
bool readCommandLine(int argc, char* argv[]);
void execute(string command);

int main(int argc, char* argv[])
try
{
    if (readCommandLine(argc, argv))
    {
        if (setup)
        {
            if (!fs::is_directory("vcpkg"))
            {
                execute("git clone https://github.com/microsoft/vcpkg.git");
                execute("git clone --progress -v vcpkg vcpkg_clone");
                fs::current_path("vcpkg");
                #ifdef WIN32
                    execute(".\\bootstrap-vcpkg.bat -disableMetrics");
                #else
                    execute("./bootstrap-vcpkg.sh -disableMetrics");
                #endif
            }
            else
            {
                fs::current_path("vcpkg");
            }

            if (fs::exists(sdkRootPath / "contrib" / "cmake" / "vcpkg_extra_triplets" / (triplet + ".cmake")))
            {
                if (fs::exists(vcpkgDir / "triplets" / (triplet + ".cmake")))
                {
                    fs::remove(vcpkgDir / "triplets" / (triplet + ".cmake"));
                }
                cout << "Copying triplet from SDK: " << triplet << endl;
                fs::copy(sdkRootPath / "contrib" / "cmake" / "vcpkg_extra_triplets" / (triplet+".cmake"), vcpkgDir / "triplets" / (triplet + ".cmake"));
            }
            else if (!fs::exists(vcpkgDir / "triplets" / (triplet + ".cmake")))
            {
                cout << "triplet not found in the SDK or in vcpkg: " << triplet << endl;
                exit(1);
            }

            for (auto portPair : ports)
            {
                const string& portname = portPair.first;
                const string& portversion = portPair.second;

                if (fs::is_directory(vcpkgDir / "ports" / portname))
                {
                    cout << "Removing " << (vcpkgDir / "ports" / portname).u8string() << endl;
                    fs::remove_all(vcpkgDir / "ports" / portname);
                }
                if (portversion.size() == 40)
                {
                    fs::current_path(cloneDir);
                    execute("git checkout --quiet " + portversion);
                    cout << "Copying port for " << portname << " from vcpkg commit " << portversion << endl;
                    fs::copy(cloneDir / "ports" / portname, vcpkgDir / "ports" / portname, fs::copy_options::recursive);
                    fs::current_path(vcpkgDir / "ports" / portname);

                    auto patch = patches.find(portname);
                    if (patch != patches.end()) {
                        cout << "Applying patch " << patch->second.u8string() << " for port " << portname << "\n";
                        execute("git apply --verbose --directory=ports/" + portname + " " + (patchPath / patch->second).u8string());
                    }
                    fs::current_path(vcpkgDir);
                }
                else
                {
                    cout << "Copying port for " << portname << " from SDK customized port " << portversion << endl;
                    fs::copy(sdkRootPath / "contrib" / "cmake" / "vcpkg_extra_ports" / portname / portversion, vcpkgDir / "ports" / portname, fs::copy_options::recursive);
                }
            }

            if (removeUnusedPorts)
            {
                for (auto dir = fs::directory_iterator(vcpkgDir / "ports"); dir != fs::directory_iterator(); ++dir)
                {
                    if (ports.find(dir->path().filename().u8string()) == ports.end())
                    {
                        fs::remove_all(dir->path());
                    }
                }
            }

            if (noPkgConfig)
            {
                cout << "Performing no-op substitution of vcpkg_fixup_pkgconfig and PKGCONFIG to skip pkgconfig integration/checks\n";
                ofstream vcpkg_fixup_pkgconfig(vcpkgDir / "scripts" / "cmake" / "vcpkg_fixup_pkgconfig.cmake", std::ios::trunc);
                if (!vcpkg_fixup_pkgconfig)
                {
                    cout << "Could not open vcpkg script file to suppress pkgconfig\n";
                    return 1;
                }

                vcpkg_fixup_pkgconfig <<
                "function(vcpkg_fixup_pkgconfig)\n"
                "endfunction()\n"
                "set(PKGCONFIG \":\")\n"; // i.e., use no-op : operator
            }

        }
        else if (build)
        {

            if (!fs::is_directory("vcpkg"))
            {
                cout << "This command should be run from just outside 'vcpkg' folder - maybe it is not set up?" << endl;
                return 1;
            }
            else
            {
                fs::current_path("vcpkg");
            }

            for (auto portPair : ports)
            {
                #ifdef WIN32
                    execute("vcpkg install --triplet " + triplet + " " + portPair.first);
                #else
                    execute("./vcpkg install --triplet " + triplet + " " + portPair.first);
                #endif
            }
        }
    }

    return 0;
}
catch (exception& e)
{
    cout << "exception: " << e.what() << endl;
    return 1;
}

string platformToString(Platform p)
{
    switch (p) {
        case Platform::platform_windows:
        return "windows";
        case Platform::platform_osx:
        return "osx";
        case Platform::platform_linux:
        return "linux";
        default:
        throw std::logic_error("Unhandled platform enumerator");
    }
}

void execute(string command)
{
    cout << "Executing: " << command << endl;
    int result = system(command.c_str());
    if (result != 0)
    {
        cout << "Command failed with result code " << result << ". Command was: " << command <<endl;
        exit(1);
    }
}

bool showSyntax()
{
    cout << "build3rdParty --setup [--removeunusedports] [--nopkgconfig] --ports <ports override file> --triplet <triplet> --sdkroot <path>" << endl;
    cout << "build3rdParty --build --ports <ports override file> --triplet <triplet>" << endl;
    return false;
}

bool readCommandLine(int argc, char* argv[])
{
    if (argc <= 1) return showSyntax();

    std::vector<char*> myargv1(argv + 1, argv + argc);
    std::vector<char*> myargv2;

    for (auto it = myargv1.begin(); it != myargv1.end(); ++it)
    {
        if (std::string(*it) == "--ports")
        {
            if (++it == myargv1.end()) return showSyntax();
            portsFile = *it;
        }
        else if (std::string(*it) == "--triplet")
        {
            if (++it == myargv1.end()) return showSyntax();
            triplet = *it;
        }
        else if (std::string(*it) == "--sdkroot")
        {
            if (++it == myargv1.end()) return showSyntax();
            sdkRootPath = *it;
        }
        else if (std::string(*it) == "--setup")
        {
            setup = true;
        }
        else if (std::string(*it) == "--removeunusedports" && setup)
        {
            removeUnusedPorts = true;
        }
        else if (std::string(*it) == "--nopkgconfig" && setup)
        {
            noPkgConfig = true;
        }
        else if (std::string(*it) == "--build")
        {
            build = true;
        }
        else
        {
            myargv2.push_back(*it);
        }
    }

    if (!myargv2.empty())
    {
        cout << "unknown parameter: " << myargv2[0] << endl;
        return false;
    }

    if (!(setup || build) || portsFile.empty() || triplet.empty())
    {
        return showSyntax();
    }

    if (setup && sdkRootPath.empty())
    {
        return showSyntax();
    }

    patchPath = sdkRootPath / "contrib" / "cmake" / "vcpkg_patches";

    ifstream portsIn(portsFile.string().c_str());
    while (portsIn)
    {
        string s;
        getline(portsIn, s);

        // remove comments
        auto hashpos = s.find("#");
        if (hashpos != string::npos) s.erase(hashpos);

        // remove whitespace
        while (!s.empty() && (s.front() == ' ' || s.front() == '\t')) s.erase(0, 1);
        while (!s.empty() && (s.back() == ' ' || s.back() == '\t')) s.pop_back();
        if (s.empty()) continue;

        // check if port should be skipped for this platform
        if (s.find(" ") != string::npos)
        {
            string platformTest = s.substr(s.find_last_of(' ') + 1);
            s.erase(s.find_first_of(' '));
            if (!platformTest.empty() && platformTest[0] == '!')
            {
                if (platformTest.substr(1) == platformToString(buildPlatform))
                {
                    cout << "Skipping " << s << " because " << platformTest <<"\n";
                    continue;
                }
            }
            else
            {
                if (platformTest != platformToString(buildPlatform))
                {
                    cout << "Skipping " << s << " because " << platformTest << "\n";
                    continue;
                }
            }
        }

        // if not, extract the exclude expressions so we don't have to worry about them
        s = s.substr(0, s.find("!"));

        // extract port/version map
        auto slashpos = s.find("/");
        if (slashpos == string::npos)
        {
            cout << "bad port: " << s << endl;
            return 1;
        }
        string portname = s.substr(0, slashpos);

        auto colonpos = s.find(':');
        string portversion = s.substr(slashpos + 1, colonpos - (slashpos + 1));

        auto existing = ports.find(portname);
        if (existing != ports.end() && existing->second != portversion)
        {
            cout << "conflicting port versions: " << portname << " " << existing->second << " " << portversion << endl;
            return 1;
        }
        ports[portname] = portversion;

        if (build) continue;

        if (colonpos != string::npos)
        {
            fs::path patch = s.substr(colonpos + 1);
            auto existingPatch = patches.find(portname);
            if (existingPatch != patches.end() && existingPatch->second != patch)
            {
                cout << "Conflicting patch files: " << patch << " and " << existingPatch->second << " for " << portname << "\n";
                return 1;
            }
            if (!fs::exists(patchPath / patch))
            {
                cout << "Nonexistent patch " << patch << " for " << portname << ", patches must be in " << patchPath.u8string() << "\n";
            }
            cout << "Got patch " << patch << " for " << portname << "\n";
            patches[portname] = patchPath / patch;
        }
    }

    return true;
}
<commit_msg>small build3rdParty tool adjustment<commit_after>#include <iostream>
#include <filesystem>
#include <vector>
#include <map>
#include <string>
#include <fstream>

using namespace std;

#if (__cplusplus >= 201703L && (!defined(__GNUC__) || (__GNUC__*100+__GNUC_MINOR__) >= 800))
#include <filesystem>
namespace fs = std::filesystem;
#define USE_FILESYSTEM
#elif !defined(__MINGW32__) && !defined(__ANDROID__) && (!defined(__GNUC__) || (__GNUC__*100+__GNUC_MINOR__) >= 503)
#define USE_FILESYSTEM
#ifdef WIN32
#include <filesystem>
namespace fs = std::experimental::filesystem;
#else
#include <experimental/filesystem>
namespace fs = std::experimental::filesystem;
#endif
#else
//for mac
#include <filesystem>
namespace fs = std::__fs::filesystem;
#endif

enum class Platform {
    platform_windows,    // platform_ prefix to avoid #define subsitutions on linux
    platform_osx,
    platform_linux,
};

constexpr Platform buildPlatform =
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)
Platform::platform_windows
#elif __APPLE__
#include <TargetConditionals.h>
    #if TARGET_OS_MAC
Platform::platform_osx
    #endif
#elif __linux__
Platform::platform_linux
#endif
; // error here: platform not detected from supported list

bool build = false;
bool setup = false;
bool removeUnusedPorts = false;
bool noPkgConfig = false;
fs::path portsFile;
fs::path sdkRootPath;
fs::path patchPath;
string triplet;

map<string, string> ports;
map<string, fs::path> patches;

fs::path initialDir = fs::current_path();
fs::path vcpkgDir = fs::current_path() / "vcpkg";
fs::path cloneDir = fs::current_path() / "vcpkg_clone";

string platformToString(Platform p);
bool readCommandLine(int argc, char* argv[]);
void execute(string command);

int main(int argc, char* argv[])
try
{
    if (readCommandLine(argc, argv))
    {
        if (setup)
        {
            if (!fs::is_directory("vcpkg"))
            {
                execute("git clone https://github.com/microsoft/vcpkg.git");
                execute("git clone --progress -v vcpkg vcpkg_clone");
                fs::current_path("vcpkg");
                #ifdef WIN32
                    execute(".\\bootstrap-vcpkg.bat -disableMetrics");
                #else
                    execute("./bootstrap-vcpkg.sh -disableMetrics");
                #endif
            }
            else
            {
                fs::current_path("vcpkg");
            }

            if (fs::exists(sdkRootPath / "contrib" / "cmake" / "vcpkg_extra_triplets" / (triplet + ".cmake")))
            {
                if (fs::exists(vcpkgDir / "triplets" / (triplet + ".cmake")))
                {
                    fs::remove(vcpkgDir / "triplets" / (triplet + ".cmake"));
                }
                cout << "Copying triplet from SDK: " << triplet << endl;
                fs::copy(sdkRootPath / "contrib" / "cmake" / "vcpkg_extra_triplets" / (triplet+".cmake"), vcpkgDir / "triplets" / (triplet + ".cmake"));
            }
            else if (!fs::exists(vcpkgDir / "triplets" / (triplet + ".cmake")))
            {
                cout << "triplet not found in the SDK or in vcpkg: " << triplet << endl;
                exit(1);
            }

            for (auto portPair : ports)
            {
                const string& portname = portPair.first;
                const string& portversion = portPair.second;

                if (fs::is_directory(vcpkgDir / "ports" / portname))
                {
                    cout << "Removing " << (vcpkgDir / "ports" / portname).u8string() << endl;
                    fs::remove_all(vcpkgDir / "ports" / portname);
                }
                if (portversion.size() == 40)
                {
                    fs::current_path(cloneDir);
                    execute("git checkout --quiet " + portversion);
                    cout << "Copying port for " << portname << " from vcpkg commit " << portversion << endl;
                    fs::copy(cloneDir / "ports" / portname, vcpkgDir / "ports" / portname, fs::copy_options::recursive);
                    fs::current_path(vcpkgDir / "ports" / portname);

                    auto patch = patches.find(portname);
                    if (patch != patches.end()) {
                        cout << "Applying patch " << patch->second.u8string() << " for port " << portname << "\n";
                        execute("git apply --verbose --directory=ports/" + portname + " " + patch->second.u8string());
                    }
                    fs::current_path(vcpkgDir);
                }
                else
                {
                    cout << "Copying port for " << portname << " from SDK customized port " << portversion << endl;
                    fs::copy(sdkRootPath / "contrib" / "cmake" / "vcpkg_extra_ports" / portname / portversion, vcpkgDir / "ports" / portname, fs::copy_options::recursive);
                }
            }

            if (removeUnusedPorts)
            {
                for (auto dir = fs::directory_iterator(vcpkgDir / "ports"); dir != fs::directory_iterator(); ++dir)
                {
                    if (ports.find(dir->path().filename().u8string()) == ports.end())
                    {
                        fs::remove_all(dir->path());
                    }
                }
            }

            if (noPkgConfig)
            {
                cout << "Performing no-op substitution of vcpkg_fixup_pkgconfig and PKGCONFIG to skip pkgconfig integration/checks\n";
                ofstream vcpkg_fixup_pkgconfig(vcpkgDir / "scripts" / "cmake" / "vcpkg_fixup_pkgconfig.cmake", std::ios::trunc);
                if (!vcpkg_fixup_pkgconfig)
                {
                    cout << "Could not open vcpkg script file to suppress pkgconfig\n";
                    return 1;
                }

                vcpkg_fixup_pkgconfig <<
                "function(vcpkg_fixup_pkgconfig)\n"
                "endfunction()\n"
                "set(PKGCONFIG \":\")\n"; // i.e., use no-op : operator
            }

        }
        else if (build)
        {

            if (!fs::is_directory("vcpkg"))
            {
                cout << "This command should be run from just outside 'vcpkg' folder - maybe it is not set up?" << endl;
                return 1;
            }
            else
            {
                fs::current_path("vcpkg");
            }

            for (auto portPair : ports)
            {
                #ifdef WIN32
                    execute("vcpkg install --triplet " + triplet + " " + portPair.first);
                #else
                    execute("./vcpkg install --triplet " + triplet + " " + portPair.first);
                #endif
            }
        }
    }

    return 0;
}
catch (exception& e)
{
    cout << "exception: " << e.what() << endl;
    return 1;
}

string platformToString(Platform p)
{
    switch (p) {
        case Platform::platform_windows:
        return "windows";
        case Platform::platform_osx:
        return "osx";
        case Platform::platform_linux:
        return "linux";
        default:
        throw std::logic_error("Unhandled platform enumerator");
    }
}

void execute(string command)
{
    cout << "Executing: " << command << endl;
    int result = system(command.c_str());
    if (result != 0)
    {
        cout << "Command failed with result code " << result << ". Command was: " << command <<endl;
        exit(1);
    }
}

bool showSyntax()
{
    cout << "build3rdParty --setup [--removeunusedports] [--nopkgconfig] --ports <ports override file> --triplet <triplet> --sdkroot <path>" << endl;
    cout << "build3rdParty --build --ports <ports override file> --triplet <triplet>" << endl;
    return false;
}

bool readCommandLine(int argc, char* argv[])
{
    if (argc <= 1) return showSyntax();

    std::vector<char*> myargv1(argv + 1, argv + argc);
    std::vector<char*> myargv2;

    for (auto it = myargv1.begin(); it != myargv1.end(); ++it)
    {
        if (std::string(*it) == "--ports")
        {
            if (++it == myargv1.end()) return showSyntax();
            portsFile = *it;
        }
        else if (std::string(*it) == "--triplet")
        {
            if (++it == myargv1.end()) return showSyntax();
            triplet = *it;
        }
        else if (std::string(*it) == "--sdkroot")
        {
            if (++it == myargv1.end()) return showSyntax();
            sdkRootPath = *it;
        }
        else if (std::string(*it) == "--setup")
        {
            setup = true;
        }
        else if (std::string(*it) == "--removeunusedports" && setup)
        {
            removeUnusedPorts = true;
        }
        else if (std::string(*it) == "--nopkgconfig" && setup)
        {
            noPkgConfig = true;
        }
        else if (std::string(*it) == "--build")
        {
            build = true;
        }
        else
        {
            myargv2.push_back(*it);
        }
    }

    if (!myargv2.empty())
    {
        cout << "unknown parameter: " << myargv2[0] << endl;
        return false;
    }

    if (!(setup || build) || portsFile.empty() || triplet.empty())
    {
        return showSyntax();
    }

    if (setup && sdkRootPath.empty())
    {
        return showSyntax();
    }

    patchPath = sdkRootPath / "contrib" / "cmake" / "vcpkg_patches";

    ifstream portsIn(portsFile.string().c_str());
    while (portsIn)
    {
        string s;
        getline(portsIn, s);

        // remove comments
        auto hashpos = s.find("#");
        if (hashpos != string::npos) s.erase(hashpos);

        // remove whitespace
        while (!s.empty() && (s.front() == ' ' || s.front() == '\t')) s.erase(0, 1);
        while (!s.empty() && (s.back() == ' ' || s.back() == '\t')) s.pop_back();
        if (s.empty()) continue;

        // check if port should be skipped for this platform
        if (s.find(" ") != string::npos)
        {
            string platformTest = s.substr(s.find_last_of(' ') + 1);
            s.erase(s.find_first_of(' '));
            if (!platformTest.empty() && platformTest[0] == '!')
            {
                if (platformTest.substr(1) == platformToString(buildPlatform))
                {
                    cout << "Skipping " << s << " because " << platformTest <<"\n";
                    continue;
                }
            }
            else
            {
                if (platformTest != platformToString(buildPlatform))
                {
                    cout << "Skipping " << s << " because " << platformTest << "\n";
                    continue;
                }
            }
        }

        // if not, extract the exclude expressions so we don't have to worry about them
        s = s.substr(0, s.find("!"));

        // extract port/version map
        auto slashpos = s.find("/");
        if (slashpos == string::npos)
        {
            cout << "bad port: " << s << endl;
            return 1;
        }
        string portname = s.substr(0, slashpos);

        auto colonpos = s.find(':');
        string portversion = s.substr(slashpos + 1, colonpos - (slashpos + 1));

        auto existing = ports.find(portname);
        if (existing != ports.end() && existing->second != portversion)
        {
            cout << "conflicting port versions: " << portname << " " << existing->second << " " << portversion << endl;
            return 1;
        }
        ports[portname] = portversion;

        if (build) continue;

        if (colonpos != string::npos)
        {
            fs::path patch = s.substr(colonpos + 1);
            auto existingPatch = patches.find(portname);
            if (existingPatch != patches.end() && existingPatch->second != patch)
            {
                cout << "Conflicting patch files: " << patch << " and " << existingPatch->second << " for " << portname << "\n";
                return 1;
            }
            if (!fs::exists(patchPath / patch))
            {
                cout << "Nonexistent patch " << patch << " for " << portname << ", patches must be in " << patchPath.u8string() << "\n";
            }
            cout << "Got patch " << patch << " for " << portname << "\n";
            patches[portname] = patchPath / patch;
        }
    }

    return true;
}
<|endoftext|>


<commit_before>/*
 * LanguageModel.cpp
 *
 *  Created on: 29 Oct 2015
 *      Author: hieu
 */
#include <vector>
#include "LanguageModel.h"
#include "System.h"
#include "Manager.h"
#include "Hypothesis.h"
#include "moses/Util.h"
#include "moses/InputFileStream.h"
#include "moses/LM/PointerState.h"
#include "moses/Bitmap.h"

using namespace std;

struct LMState : public Moses::PointerState
{
  LMState(MemPool &pool, const Moses::Factor *eos)
  :PointerState(NULL)
  {
	  numWords = 1;
	  lastWords = (const Moses::Factor**) pool.Allocate(sizeof(const Moses::Factor*));
	  lastWords[0] = eos;
  }

  LMState(MemPool &pool, void *lms, const std::vector<const Moses::Factor*> &context)
  :PointerState(lms)
  {
	  numWords = context.size();
	  lastWords = (const Moses::Factor**) pool.Allocate(sizeof(const Moses::Factor*) * numWords);
	  for (size_t i = 0; i < numWords; ++i) {
		  lastWords[i] = context[i];
	  }
  }

  size_t numWords;
  const Moses::Factor** lastWords;
};

////////////////////////////////////////////////////////////////////////////////////////
LanguageModel::LanguageModel(size_t startInd, const std::string &line)
:StatefulFeatureFunction(startInd, line)
,m_oov(-100)
{
	ReadParameters();
}

LanguageModel::~LanguageModel() {
	// TODO Auto-generated destructor stub
}

void LanguageModel::Load(System &system)
{
  Moses::FactorCollection &fc = system.GetVocab();

  m_sos = fc.AddFactor("<s>", false);
  m_eos = fc.AddFactor("</s>", false);

  Moses::InputFileStream infile(m_path);
  size_t lineNum = 0;
  string line;
  while (getline(infile, line)) {
	  if (++lineNum % 100000 == 0) {
		  cerr << lineNum << " ";
	  }

	  vector<string> substrings;
	  Moses::Tokenize(substrings, line, "\t");

	  if (substrings.size() < 2)
		   continue;

	  assert(substrings.size() == 2 || substrings.size() == 3);

	  SCORE prob = Moses::TransformLMScore(Moses::Scan<SCORE>(substrings[0]));
	  if (substrings[1] == "<unk>") {
		  m_oov = prob;
		  continue;
	  }

	  SCORE backoff = 0.f;
	  if (substrings.size() == 3) {
		backoff = Moses::TransformLMScore(Moses::Scan<SCORE>(substrings[2]));
	  }

	  // ngram
	  vector<string> key;
	  Moses::Tokenize(key, substrings[1], " ");

	  vector<const Moses::Factor*> factorKey(key.size());
	  for (size_t i = 0; i < key.size(); ++i) {
		  factorKey[factorKey.size() - i - 1] = fc.AddFactor(key[i], false);
	  }

	  m_root.insert(factorKey, LMScores(prob, backoff));
  }

}

void LanguageModel::SetParameter(const std::string& key, const std::string& value)
{
  if (key == "path") {
	  m_path = value;
  }
  else if (key == "factor") {
	  m_factorType = Moses::Scan<Moses::FactorType>(value);
  }
  else if (key == "order") {
	  m_order = Moses::Scan<size_t>(value);
  }
  else {
	  StatefulFeatureFunction::SetParameter(key, value);
  }
}

const Moses::FFState* LanguageModel::EmptyHypothesisState(const Manager &mgr, const Phrase &input) const
{
	MemPool &pool = mgr.GetPool();
	return new (pool.Allocate<LMState>()) LMState(pool, m_sos);
}

void
LanguageModel::EvaluateInIsolation(const System &system,
		  const PhraseBase &source, const TargetPhrase &targetPhrase,
        Scores &scores,
        Scores *estimatedFutureScores) const
{
	SCORE score = 0;
	SCORE nonFullScore = 0;
	vector<const Moses::Factor*> context;
	context.reserve(m_order);
	for (size_t i = 0; i < targetPhrase.GetSize(); ++i) {
		const Word &word = targetPhrase[i];
		const Moses::Factor *factor = word[m_factorType];
		ShiftOrPush(context, factor);

		if (context.size() == m_order) {
			std::pair<SCORE, void*> fromScoring = Score(context);
			//score += fromScoring.first;
			estimatedFutureScores += fromScoring.first;
		}
		else if (estimatedFutureScores) {
			std::pair<SCORE, void*> fromScoring = Score(context);
			nonFullScore += fromScoring.first;
		}
	}

	//scores.PlusEquals(system, *this, score);
	if (estimatedFutureScores) {
		estimatedFutureScores->PlusEquals(system, *this, nonFullScore);
	}
}

Moses::FFState* LanguageModel::EvaluateWhenApplied(const Manager &mgr,
  const Hypothesis &hypo,
  const Moses::FFState &prevState,
  Scores &scores) const
{
	const LMState &prevLMState = static_cast<const LMState &>(prevState);
	size_t numWords = prevLMState.numWords;

	// context is held backwards
	vector<const Moses::Factor*> context(numWords);
	for (size_t i = 0; i < numWords; ++i) {
		context[i] = prevLMState.lastWords[i];
	}
	//DebugContext(context);

	SCORE score = 0;
	std::pair<SCORE, void*> fromScoring;
	const Phrase &tp = hypo.GetTargetPhrase();
	for (size_t i = 0; i < tp.GetSize(); ++i) {
		const Word &word = tp[i];
		const Moses::Factor *factor = word[m_factorType];
		ShiftOrPush(context, factor);
		fromScoring = Score(context);
		score += fromScoring.first;
	}

	const Moses::Bitmap &bm = hypo.GetBitmap();
	if (bm.IsComplete()) {
		// everything translated
		ShiftOrPush(context, m_eos);
		fromScoring = Score(context);
		score += fromScoring.first;
		fromScoring.second = NULL;
		context.clear();
	}
	else {
		assert(context.size());
		if (context.size() == m_order) {
			context.resize(context.size() - 1);
		}
	}

	scores.PlusEquals(mgr.GetSystem(), *this, score);

	// return state
	//DebugContext(context);

	MemPool &pool = mgr.GetPool();
	return new (pool.Allocate<LMState>()) LMState(pool, fromScoring.second, context);
}

void LanguageModel::ShiftOrPush(std::vector<const Moses::Factor*> &context, const Moses::Factor *factor) const
{
	if (context.size() < m_order) {
		context.resize(context.size() + 1);
	}
	assert(context.size());

	for (size_t i = context.size() - 1; i > 0; --i) {
		context[i] = context[i - 1];
	}

	context[0] = factor;
}

std::pair<SCORE, void*> LanguageModel::Score(const std::vector<const Moses::Factor*> &context) const
{
	//cerr << "context=";
	//DebugContext(context);

	std::pair<SCORE, void*> ret;

	typedef Node<const Moses::Factor*, LMScores> LMNode;
	const LMNode *node = m_root.getNode(context);
	if (node) {
		ret.first = node->getValue().prob;
		ret.second = (void*) node;
	}
	else {
	  SCORE backoff = 0;
	  std::vector<const Moses::Factor*> backOffContext(context.begin() + 1, context.end());
	  node = m_root.getNode(backOffContext);
	  if (node) {
		  backoff = node->getValue().backoff;
	  }

	  std::vector<const Moses::Factor*> newContext(context.begin(), context.end() - 1);
	  std::pair<SCORE, void*> newRet = Score(newContext);

	  ret.first = backoff + newRet.first;
	  ret.second = newRet.second;
	}

	//cerr << "score=" << ret.first << endl;
	return ret;
}

SCORE LanguageModel::BackoffScore(const std::vector<const Moses::Factor*> &context) const
{
	//cerr << "backoff=";
	//DebugContext(context);

	SCORE ret;
	size_t stoppedAtInd;
	const Node<const Moses::Factor*, LMScores> &node = m_root.getNode(context, stoppedAtInd);

	if (stoppedAtInd == context.size()) {
		// found entire ngram
		ret =  node.getValue().backoff;
	}
	else {
		if (stoppedAtInd == 0) {
			ret = m_oov;
			stoppedAtInd = 1;
		}
		else {
			ret = node.getValue().backoff;
		}

		// recursive
		std::vector<const Moses::Factor*> backoff(context.begin() + stoppedAtInd, context.end());
		ret += BackoffScore(backoff);
	}

}

void LanguageModel::DebugContext(const std::vector<const Moses::Factor*> &context) const
{
	for (size_t i = 0; i < context.size(); ++i) {
		cerr << context[i]->ToString() << " ";
	}
	cerr << endl;
}
<commit_msg>future score<commit_after>/*
 * LanguageModel.cpp
 *
 *  Created on: 29 Oct 2015
 *      Author: hieu
 */
#include <vector>
#include "LanguageModel.h"
#include "System.h"
#include "Manager.h"
#include "Hypothesis.h"
#include "moses/Util.h"
#include "moses/InputFileStream.h"
#include "moses/LM/PointerState.h"
#include "moses/Bitmap.h"

using namespace std;

struct LMState : public Moses::PointerState
{
  LMState(MemPool &pool, const Moses::Factor *eos)
  :PointerState(NULL)
  {
	  numWords = 1;
	  lastWords = (const Moses::Factor**) pool.Allocate(sizeof(const Moses::Factor*));
	  lastWords[0] = eos;
  }

  LMState(MemPool &pool, void *lms, const std::vector<const Moses::Factor*> &context)
  :PointerState(lms)
  {
	  numWords = context.size();
	  lastWords = (const Moses::Factor**) pool.Allocate(sizeof(const Moses::Factor*) * numWords);
	  for (size_t i = 0; i < numWords; ++i) {
		  lastWords[i] = context[i];
	  }
  }

  size_t numWords;
  const Moses::Factor** lastWords;
};

////////////////////////////////////////////////////////////////////////////////////////
LanguageModel::LanguageModel(size_t startInd, const std::string &line)
:StatefulFeatureFunction(startInd, line)
,m_oov(-100)
{
	ReadParameters();
}

LanguageModel::~LanguageModel() {
	// TODO Auto-generated destructor stub
}

void LanguageModel::Load(System &system)
{
  Moses::FactorCollection &fc = system.GetVocab();

  m_sos = fc.AddFactor("<s>", false);
  m_eos = fc.AddFactor("</s>", false);

  Moses::InputFileStream infile(m_path);
  size_t lineNum = 0;
  string line;
  while (getline(infile, line)) {
	  if (++lineNum % 100000 == 0) {
		  cerr << lineNum << " ";
	  }

	  vector<string> substrings;
	  Moses::Tokenize(substrings, line, "\t");

	  if (substrings.size() < 2)
		   continue;

	  assert(substrings.size() == 2 || substrings.size() == 3);

	  SCORE prob = Moses::TransformLMScore(Moses::Scan<SCORE>(substrings[0]));
	  if (substrings[1] == "<unk>") {
		  m_oov = prob;
		  continue;
	  }

	  SCORE backoff = 0.f;
	  if (substrings.size() == 3) {
		backoff = Moses::TransformLMScore(Moses::Scan<SCORE>(substrings[2]));
	  }

	  // ngram
	  vector<string> key;
	  Moses::Tokenize(key, substrings[1], " ");

	  vector<const Moses::Factor*> factorKey(key.size());
	  for (size_t i = 0; i < key.size(); ++i) {
		  factorKey[factorKey.size() - i - 1] = fc.AddFactor(key[i], false);
	  }

	  m_root.insert(factorKey, LMScores(prob, backoff));
  }

}

void LanguageModel::SetParameter(const std::string& key, const std::string& value)
{
  if (key == "path") {
	  m_path = value;
  }
  else if (key == "factor") {
	  m_factorType = Moses::Scan<Moses::FactorType>(value);
  }
  else if (key == "order") {
	  m_order = Moses::Scan<size_t>(value);
  }
  else {
	  StatefulFeatureFunction::SetParameter(key, value);
  }
}

const Moses::FFState* LanguageModel::EmptyHypothesisState(const Manager &mgr, const Phrase &input) const
{
	MemPool &pool = mgr.GetPool();
	return new (pool.Allocate<LMState>()) LMState(pool, m_sos);
}

void
LanguageModel::EvaluateInIsolation(const System &system,
		  const PhraseBase &source, const TargetPhrase &targetPhrase,
        Scores &scores,
        Scores *estimatedFutureScores) const
{
	SCORE score = 0;
	SCORE nonFullScore = 0;
	vector<const Moses::Factor*> context;
	context.reserve(m_order);
	for (size_t i = 0; i < targetPhrase.GetSize(); ++i) {
		const Word &word = targetPhrase[i];
		const Moses::Factor *factor = word[m_factorType];
		ShiftOrPush(context, factor);

		if (context.size() == m_order) {
			std::pair<SCORE, void*> fromScoring = Score(context);
			//score += fromScoring.first;
			nonFullScore += fromScoring.first;
		}
		else if (estimatedFutureScores) {
			std::pair<SCORE, void*> fromScoring = Score(context);
			nonFullScore += fromScoring.first;
		}
	}

	//scores.PlusEquals(system, *this, score);
	if (estimatedFutureScores) {
		estimatedFutureScores->PlusEquals(system, *this, nonFullScore);
	}
}

Moses::FFState* LanguageModel::EvaluateWhenApplied(const Manager &mgr,
  const Hypothesis &hypo,
  const Moses::FFState &prevState,
  Scores &scores) const
{
	const LMState &prevLMState = static_cast<const LMState &>(prevState);
	size_t numWords = prevLMState.numWords;

	// context is held backwards
	vector<const Moses::Factor*> context(numWords);
	for (size_t i = 0; i < numWords; ++i) {
		context[i] = prevLMState.lastWords[i];
	}
	//DebugContext(context);

	SCORE score = 0;
	std::pair<SCORE, void*> fromScoring;
	const Phrase &tp = hypo.GetTargetPhrase();
	for (size_t i = 0; i < tp.GetSize(); ++i) {
		const Word &word = tp[i];
		const Moses::Factor *factor = word[m_factorType];
		ShiftOrPush(context, factor);
		fromScoring = Score(context);
		score += fromScoring.first;
	}

	const Moses::Bitmap &bm = hypo.GetBitmap();
	if (bm.IsComplete()) {
		// everything translated
		ShiftOrPush(context, m_eos);
		fromScoring = Score(context);
		score += fromScoring.first;
		fromScoring.second = NULL;
		context.clear();
	}
	else {
		assert(context.size());
		if (context.size() == m_order) {
			context.resize(context.size() - 1);
		}
	}

	scores.PlusEquals(mgr.GetSystem(), *this, score);

	// return state
	//DebugContext(context);

	MemPool &pool = mgr.GetPool();
	return new (pool.Allocate<LMState>()) LMState(pool, fromScoring.second, context);
}

void LanguageModel::ShiftOrPush(std::vector<const Moses::Factor*> &context, const Moses::Factor *factor) const
{
	if (context.size() < m_order) {
		context.resize(context.size() + 1);
	}
	assert(context.size());

	for (size_t i = context.size() - 1; i > 0; --i) {
		context[i] = context[i - 1];
	}

	context[0] = factor;
}

std::pair<SCORE, void*> LanguageModel::Score(const std::vector<const Moses::Factor*> &context) const
{
	//cerr << "context=";
	//DebugContext(context);

	std::pair<SCORE, void*> ret;

	typedef Node<const Moses::Factor*, LMScores> LMNode;
	const LMNode *node = m_root.getNode(context);
	if (node) {
		ret.first = node->getValue().prob;
		ret.second = (void*) node;
	}
	else {
	  SCORE backoff = 0;
	  std::vector<const Moses::Factor*> backOffContext(context.begin() + 1, context.end());
	  node = m_root.getNode(backOffContext);
	  if (node) {
		  backoff = node->getValue().backoff;
	  }

	  std::vector<const Moses::Factor*> newContext(context.begin(), context.end() - 1);
	  std::pair<SCORE, void*> newRet = Score(newContext);

	  ret.first = backoff + newRet.first;
	  ret.second = newRet.second;
	}

	//cerr << "score=" << ret.first << endl;
	return ret;
}

SCORE LanguageModel::BackoffScore(const std::vector<const Moses::Factor*> &context) const
{
	//cerr << "backoff=";
	//DebugContext(context);

	SCORE ret;
	size_t stoppedAtInd;
	const Node<const Moses::Factor*, LMScores> &node = m_root.getNode(context, stoppedAtInd);

	if (stoppedAtInd == context.size()) {
		// found entire ngram
		ret =  node.getValue().backoff;
	}
	else {
		if (stoppedAtInd == 0) {
			ret = m_oov;
			stoppedAtInd = 1;
		}
		else {
			ret = node.getValue().backoff;
		}

		// recursive
		std::vector<const Moses::Factor*> backoff(context.begin() + stoppedAtInd, context.end());
		ret += BackoffScore(backoff);
	}

}

void LanguageModel::DebugContext(const std::vector<const Moses::Factor*> &context) const
{
	for (size_t i = 0; i < context.size(); ++i) {
		cerr << context[i]->ToString() << " ";
	}
	cerr << endl;
}
<|endoftext|>


<commit_before>/*
 * Licensed under the MIT License (MIT)
 *
 * Copyright (c) 2013 AudioScience Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 * the Software, and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

/**
 * notification_imp.cpp
 *
 * Notification implementation
 */

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>

#include <sys/socket.h>
#include <sys/ioctl.h>
#include <linux/if_packet.h>
#include <linux/if_ether.h>
#include <linux/if_arp.h>
#include <linux/filter.h>
#include <linux/if.h>
#include <arpa/inet.h>

#include "enumeration.h"
#include "notification_imp.h"

namespace avdecc_lib
{
    notification_imp *notification_imp_ref = new notification_imp();

    notification_imp::notification_imp()
    {
        notification_thread_init(); // Start notification thread
    }

    notification_imp::~notification_imp()
    {
        post_notification_event();
    }

    int notification_imp::notification_thread_init()
    {
        int rc;

        sem_init(&notify_waiting, 0, 0);

        rc = pthread_create(&h_thread, NULL, &notification_imp::dispatch_thread, (void *)this);
        if (rc)
        {
            printf("ERROR; return code from pthread_create() is %d\n", rc);
            exit(-1);
        }

        return 0;
    }

    void * notification_imp::dispatch_thread(void * param)
    {
        return ((notification_imp *)param)->dispatch_callbacks();

    }

    void * notification_imp::dispatch_callbacks(void)
    {
        while (true)
        {
            sem_wait(&notify_waiting);

            if((write_index - read_index) > 0)
            {
                notification_callback(user_obj,
                                      notification_buf[read_index % NOTIFICATION_BUF_COUNT].notification_type,
                                      notification_buf[read_index % NOTIFICATION_BUF_COUNT].guid,
                                      notification_buf[read_index % NOTIFICATION_BUF_COUNT].cmd_type,
                                      notification_buf[read_index % NOTIFICATION_BUF_COUNT].desc_type,
                                      notification_buf[read_index % NOTIFICATION_BUF_COUNT].desc_index,
                                      notification_buf[read_index % NOTIFICATION_BUF_COUNT].notification_id
                                     );
                read_index++;
            }
            else
            {
                break;
            }
        }

        return 0;
    }

    void notification_imp::post_notification_event()
    {
        sem_post(&notify_waiting);
    }
}
<commit_msg>linux: fix build<commit_after>/*
 * Licensed under the MIT License (MIT)
 *
 * Copyright (c) 2013 AudioScience Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 * the Software, and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

/**
 * notification_imp.cpp
 *
 * Notification implementation
 */

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>

#include <sys/socket.h>
#include <sys/ioctl.h>
#include <linux/if_packet.h>
#include <linux/if_ether.h>
#include <linux/if_arp.h>
#include <linux/filter.h>
#include <linux/if.h>
#include <arpa/inet.h>

#include "enumeration.h"
#include "notification_imp.h"

namespace avdecc_lib
{
    notification_imp *notification_imp_ref = new notification_imp();

    notification_imp::notification_imp()
    {
        notification_thread_init(); // Start notification thread
    }

    notification_imp::~notification_imp()
    {
        post_notification_event();
    }

    int notification_imp::notification_thread_init()
    {
        int rc;

        sem_init(&notify_waiting, 0, 0);

        rc = pthread_create(&h_thread, NULL, &notification_imp::dispatch_thread, (void *)this);
        if (rc)
        {
            printf("ERROR; return code from pthread_create() is %d\n", rc);
            exit(-1);
        }

        return 0;
    }

    void * notification_imp::dispatch_thread(void * param)
    {
        return ((notification_imp *)param)->dispatch_callbacks();

    }

    void * notification_imp::dispatch_callbacks(void)
    {
        while (true)
        {
            sem_wait(&notify_waiting);

            if((write_index - read_index) > 0)
            {
                notification_callback(user_obj,
                                      notification_buf[read_index % NOTIFICATION_BUF_COUNT].notification_type,
                                      notification_buf[read_index % NOTIFICATION_BUF_COUNT].guid,
                                      notification_buf[read_index % NOTIFICATION_BUF_COUNT].cmd_type,
                                      notification_buf[read_index % NOTIFICATION_BUF_COUNT].desc_type,
                                      notification_buf[read_index % NOTIFICATION_BUF_COUNT].desc_index,
                                      notification_buf[read_index % NOTIFICATION_BUF_COUNT].cmd_status,
                                      notification_buf[read_index % NOTIFICATION_BUF_COUNT].notification_id
                                     );
                read_index++;
            }
            else
            {
                break;
            }
        }

        return 0;
    }

    void notification_imp::post_notification_event()
    {
        sem_post(&notify_waiting);
    }
}
<|endoftext|>


<commit_before>#define DEBUG 1

/**
 * File    : F3.cpp
 * Author  : Kazune Takahashi
 * Created : 2019-5-26 14:03:38
 * Powered by Visual Studio Code
 */

#include <iostream>
#include <iomanip>   // << fixed << setprecision(xxx)
#include <algorithm> // do { } while ( next_permutation(A, A+xxx) ) ;
#include <vector>
#include <string> // to_string(nnn) // substr(m, n) // stoi(nnn)
#include <complex>
#include <tuple>
#include <queue>
#include <stack>
#include <map> // if (M.find(key) != M.end()) { }
#include <set>
#include <functional>
#include <random> // auto rd = bind(uniform_int_distribution<int>(0, 9), mt19937(10101010));
#include <chrono> // std::chrono::system_clock::time_point start_time, end_time;
// start = std::chrono::system_clock::now();
// double elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(end_time-start_time).count();
#include <cctype>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
using namespace std;

typedef long long ll;

// const int dx[4] = {1, 0, -1, 0};
// const int dy[4] = {0, 1, 0, -1};

// const int C = 1e6+10;
// const ll M = 1000000007;

template <class T>
class SegTree
{ // 0-indexed, [0, N).
private:
  int N;
  T *dat;
  T UNIT; // モノイドの単位元

  static T func(T x, T y)
  { // ここで演算を定義する。圏、特にモノイドであればなんでも良い。
    // 実装はモノイドであるとする。
    // return min(x, y);
    return x + y;
  }

public:
  SegTree() {}

  SegTree(int n, T unit)
  { // ここで unit を定義するのも変な実装だけどめんどいからこれでいい。
    // min の場合は INFTY = (1LL << 60)
    // + の場合は 0 とする。
    UNIT = unit;
    N = 1;
    while (N < n)
    {
      N *= 2;
    }
    dat = new T[2 * N - 1];
    for (auto i = 0; i < 2 * N - 1; ++i)
    {
      dat[i] = UNIT;
    }
  }

  void update(int k, T a)
  {
    k += N - 1;
    dat[k] = a;
    while (k > 0)
    {
      k = (k - 1) / 2;
      dat[k] = func(dat[k * 2 + 1], dat[k * 2 + 2]);
    }
  }

private:
  T find(int a, int b, int k, int l, int r)
  {
    if (r <= a || b <= l)
      return UNIT;
    if (a <= l && r <= b)
      return dat[k];
    T vl = find(a, b, k * 2 + 1, l, (l + r) / 2);
    T vr = find(a, b, k * 2 + 2, (l + r) / 2, r);
    return func(vl, vr);
  }

public:
  T find(int a, int b)
  { // [a, b) の find をする。
    return find(a, b, 0, 0, N);
  }
};

typedef tuple<bool, ll, ll> query;

int Q;
query X[200010];
set<ll> S;
map<ll, int> M;
SegTree<ll> tree;

priority_queue<ll> L;
priority_queue<ll, vector<ll>, greater<ll>> R;
ll B = 0;

void merge(ll a, ll b)
{
  B += b;
  L.push(a);
  R.push(a);
  if (L.top() <= R.top())
  {
    // nothing
  }
  else
  {
    ll l = L.top();
    ll r = R.top();
    L.pop();
    R.pop();
    L.push(r);
    R.push(l);
  }
  tree.update(M[a], a);
}

void flush()
{
  ll p = L.top();
  int ind = M[p];
  ll v = -tree.find(0, ind) + tree.find(ind + 1, S.size());
  cout << p << " " << v << endl;
}

int main()
{
  cin >> Q;
  for (auto i = 0; i < Q; i++)
  {
    char x;
    cin >> x;
    if (x == '1')
    {
      ll a, b;
      cin >> a >> b;
      X[i] = query(true, a, b);
    }
    else
    {
      X[i] = query(false, 0, 0);
    }
  }
  for (auto i = 0; i < Q; i++)
  {
    if (get<0>(X[i]))
    {
      S.insert(get<1>(X[i]));
    }
  }
  int ind = 0;
  for (auto x : S)
  {
    M[x] = ind++;
  }
  tree = SegTree<ll>(S.size(), 0);
}<commit_msg>tried F3.cpp to 'F'<commit_after>#define DEBUG 1

/**
 * File    : F3.cpp
 * Author  : Kazune Takahashi
 * Created : 2019-5-26 14:03:38
 * Powered by Visual Studio Code
 */

#include <iostream>
#include <iomanip>   // << fixed << setprecision(xxx)
#include <algorithm> // do { } while ( next_permutation(A, A+xxx) ) ;
#include <vector>
#include <string> // to_string(nnn) // substr(m, n) // stoi(nnn)
#include <complex>
#include <tuple>
#include <queue>
#include <stack>
#include <map> // if (M.find(key) != M.end()) { }
#include <set>
#include <functional>
#include <random> // auto rd = bind(uniform_int_distribution<int>(0, 9), mt19937(10101010));
#include <chrono> // std::chrono::system_clock::time_point start_time, end_time;
// start = std::chrono::system_clock::now();
// double elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(end_time-start_time).count();
#include <cctype>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
using namespace std;

typedef long long ll;

// const int dx[4] = {1, 0, -1, 0};
// const int dy[4] = {0, 1, 0, -1};

// const int C = 1e6+10;
// const ll M = 1000000007;

template <class T>
class SegTree
{ // 0-indexed, [0, N).
private:
  int N;
  T *dat;
  T UNIT; // モノイドの単位元

  static T func(T x, T y)
  { // ここで演算を定義する。圏、特にモノイドであればなんでも良い。
    // 実装はモノイドであるとする。
    // return min(x, y);
    return x + y;
  }

public:
  SegTree() {}

  SegTree(int n, T unit)
  { // ここで unit を定義するのも変な実装だけどめんどいからこれでいい。
    // min の場合は INFTY = (1LL << 60)
    // + の場合は 0 とする。
    UNIT = unit;
    N = 1;
    while (N < n)
    {
      N *= 2;
    }
    dat = new T[2 * N - 1];
    for (auto i = 0; i < 2 * N - 1; ++i)
    {
      dat[i] = UNIT;
    }
  }

  void update(int k, T a)
  {
    k += N - 1;
    dat[k] = a;
    while (k > 0)
    {
      k = (k - 1) / 2;
      dat[k] = func(dat[k * 2 + 1], dat[k * 2 + 2]);
    }
  }

private:
  T find(int a, int b, int k, int l, int r)
  {
    if (r <= a || b <= l)
      return UNIT;
    if (a <= l && r <= b)
      return dat[k];
    T vl = find(a, b, k * 2 + 1, l, (l + r) / 2);
    T vr = find(a, b, k * 2 + 2, (l + r) / 2, r);
    return func(vl, vr);
  }

public:
  T find(int a, int b)
  { // [a, b) の find をする。
    return find(a, b, 0, 0, N);
  }
};

typedef tuple<bool, ll, ll> query;

int Q;
query X[200010];
set<ll> S;
map<ll, int> M;
SegTree<ll> tree;

priority_queue<ll> L;
priority_queue<ll, vector<ll>, greater<ll>> R;
ll B = 0;

void merge(ll a, ll b)
{
  B += b;
  L.push(a);
  R.push(a);
  if (L.top() <= R.top())
  {
    // nothing
  }
  else
  {
    ll l = L.top();
    ll r = R.top();
    L.pop();
    R.pop();
    L.push(r);
    R.push(l);
  }
  tree.update(M[a], a);
}

void flush()
{
  ll p = L.top();
  int ind = M[p];
  ll v = -tree.find(0, ind) + tree.find(ind + 1, S.size());
  cout << p << " " << v << endl;
}

int main()
{
  cin >> Q;
  for (auto i = 0; i < Q; i++)
  {
    char x;
    cin >> x;
    if (x == '1')
    {
      ll a, b;
      cin >> a >> b;
      X[i] = query(true, a, b);
    }
    else
    {
      X[i] = query(false, 0, 0);
    }
  }
  for (auto i = 0; i < Q; i++)
  {
    if (get<0>(X[i]))
    {
      S.insert(get<1>(X[i]));
    }
  }
  int ind = 0;
  for (auto x : S)
  {
    M[x] = ind++;
  }
  tree = SegTree<ll>(S.size(), 0);
  for (auto i = 0; i < Q; i++)
  {
    if (get<0>(X[i]))
    {
      merge(get<1>(X[i]), get<2>(X[i]));
    }
    else
    {
      flush();
    }
  }
}<|endoftext|>


<commit_before>#define DEBUG 1
/**
 * File    : B2.cpp
 * Author  : Kazune Takahashi
 * Created : 7/15/2019, 2:30:15 AM
 * Powered by Visual Studio Code
 */
#include <iostream>
#include <iomanip>
#include <algorithm>
#include <vector>
#include <string>
#include <complex>
#include <tuple>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <bitset>
#include <functional>
#include <random>
#include <chrono>
#include <cctype>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
using namespace std;
#define maxs(x, y) (x = max(x, y))
#define mins(x, y) (x = min(x, y))
using ll = long long;
class mint
{
public:
  static ll MOD;
  ll x;
  mint() : x(0) {}
  mint(ll x) : x(x % MOD) {}
  mint operator-() const { return x ? MOD - x : 0; }
  mint &operator+=(const mint &a)
  {
    if ((x += a.x) >= MOD)
    {
      x -= MOD;
    }
    return *this;
  }
  mint &operator-=(const mint &a) { return *this += -a; }
  mint &operator*=(const mint &a)
  {
    (x *= a.x) %= MOD;
    return *this;
  }
  mint &operator/=(const mint &a) { return (*this *= power(MOD - 2)); }
  mint operator+(const mint &a) const { return mint(*this) += a; }
  mint operator-(const mint &a) const { return mint(*this) -= a; }
  mint operator*(const mint &a) const { return mint(*this) *= a; }
  mint operator/(const mint &a) const { return mint(*this) /= a; }
  bool operator<(const mint &a) const { return x < a.x; }
  bool operator==(const mint &a) const { return x == a.x; }
  const mint power(ll N)
  {
    if (N == 0)
    {
      return 1;
    }
    else if (N % 2 == 1)
    {
      return *this * power(N - 1);
    }
    else
    {
      mint half = power(N / 2);
      return half * half;
    }
  }
};
ll mint::MOD = 1e9 + 7;
istream &operator>>(istream &stream, mint &a) { return stream >> a.x; }
ostream &operator<<(ostream &stream, const mint &a) { return stream << a.x; }
class combination
{
public:
  vector<mint> inv, fact, factinv;
  static int MAX_SIZE;
  combination() : inv(MAX_SIZE), fact(MAX_SIZE), factinv(MAX_SIZE)
  {
    inv[1] = 1;
    for (auto i = 2; i < MAX_SIZE; i++)
    {
      inv[i] = (-inv[mint::MOD % i]) * (mint::MOD / i);
    }
    fact[0] = factinv[0] = 1;
    for (auto i = 1; i < MAX_SIZE; i++)
    {
      fact[i] = mint(i) * fact[i - 1];
      factinv[i] = inv[i] * factinv[i - 1];
    }
  }
  mint operator()(int n, int k)
  {
    if (n >= 0 && k >= 0 && n - k >= 0)
    {
      return fact[n] * factinv[k] * factinv[n - k];
    }
    return 0;
  }
};
int combination::MAX_SIZE = 1e6 + 10;
ll gcd(ll x, ll y) { return y ? gcd(y, x % y) : x; }
// const double epsilon = 1e-10;
// const ll infty = 1000000000000000LL;
// const int dx[4] = {1, 0, -1, 0};
// const int dy[4] = {0, 1, 0, -1};

class UnionFind
{
  vector<long long> par;

public:
  UnionFind() {}
  UnionFind(int n) : par(n, -1) {}

  bool is_same(int x, int y)
  {
    return root(x) == root(y);
  }

  bool merge(int x, int y)
  {
    x = root(x);
    y = root(y);
    if (x == y)
    {
      return false;
    }
    if (par[x] > par[y])
    {
      swap(x, y);
    }
    par[x] += par[y];
    par[y] = x;
    return true;
  }

  long long size(int x)
  {
    return -par[root(x)];
  }

private:
  int root(int x)
  {
    if (par[x] < 0)
    {
      return x;
    }
    return par[x] = root(par[x]);
  }
};

using edge = tuple<int, int>;

int N, M;
vector<edge> E;
vector<edge> ans;
int cnt[100010];
vector<int> V[100010];

void Yes()
{
  for (auto x : ans)
  {
    cout << get<0>(x) + 1 << " " << get<1>(x) + 1 << endl;
  }
  exit(0);
}

void No()
{
  cout << "-1" << endl;
  exit(0);
}

void make_V()
{
  UnionFind uf{N};
  for (auto e : E)
  {
    int a, b;
    tie(a, b) = e;
    if (!uf.is_same(a, b))
    {
      uf.merge(a, b);
      V[a].push_back(b);
      V[b].push_back(a);
    }
    else
    {
      ans.push_back(e);
      cnt[a]++;
    }
  }
}

void dfs(int v, int p = -1)
{
  for (auto w : V[v])
  {
    if (p != w)
    {
      dfs(w, v);
    }
  }
  if (p == -1)
  {
    return;
  }
  if (cnt[v] % 2 == 1)
  {
    ans.push_back(edge(v, p));
  }
  else
  {
    ans.push_back(edge(p, v));
  }
}

void solve()
{
  make_V();
  dfs(0);
}

int main()
{
  cin >> N >> M;
  for (auto i = 0; i < M; i++)
  {
    int a, b;
    cin >> a >> b;
    --a;
    --b;
    E.push_back(edge(a, b));
  }
  if (M % 2 == 1)
  {
    No();
  }
  solve();
  Yes();
}<commit_msg>tried B2.cpp to 'B'<commit_after>#define DEBUG 1
/**
 * File    : B2.cpp
 * Author  : Kazune Takahashi
 * Created : 7/15/2019, 2:30:15 AM
 * Powered by Visual Studio Code
 */
#include <iostream>
#include <iomanip>
#include <algorithm>
#include <vector>
#include <string>
#include <complex>
#include <tuple>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <bitset>
#include <functional>
#include <random>
#include <chrono>
#include <cctype>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
using namespace std;
#define maxs(x, y) (x = max(x, y))
#define mins(x, y) (x = min(x, y))
using ll = long long;
class mint
{
public:
  static ll MOD;
  ll x;
  mint() : x(0) {}
  mint(ll x) : x(x % MOD) {}
  mint operator-() const { return x ? MOD - x : 0; }
  mint &operator+=(const mint &a)
  {
    if ((x += a.x) >= MOD)
    {
      x -= MOD;
    }
    return *this;
  }
  mint &operator-=(const mint &a) { return *this += -a; }
  mint &operator*=(const mint &a)
  {
    (x *= a.x) %= MOD;
    return *this;
  }
  mint &operator/=(const mint &a) { return (*this *= power(MOD - 2)); }
  mint operator+(const mint &a) const { return mint(*this) += a; }
  mint operator-(const mint &a) const { return mint(*this) -= a; }
  mint operator*(const mint &a) const { return mint(*this) *= a; }
  mint operator/(const mint &a) const { return mint(*this) /= a; }
  bool operator<(const mint &a) const { return x < a.x; }
  bool operator==(const mint &a) const { return x == a.x; }
  const mint power(ll N)
  {
    if (N == 0)
    {
      return 1;
    }
    else if (N % 2 == 1)
    {
      return *this * power(N - 1);
    }
    else
    {
      mint half = power(N / 2);
      return half * half;
    }
  }
};
ll mint::MOD = 1e9 + 7;
istream &operator>>(istream &stream, mint &a) { return stream >> a.x; }
ostream &operator<<(ostream &stream, const mint &a) { return stream << a.x; }
class combination
{
public:
  vector<mint> inv, fact, factinv;
  static int MAX_SIZE;
  combination() : inv(MAX_SIZE), fact(MAX_SIZE), factinv(MAX_SIZE)
  {
    inv[1] = 1;
    for (auto i = 2; i < MAX_SIZE; i++)
    {
      inv[i] = (-inv[mint::MOD % i]) * (mint::MOD / i);
    }
    fact[0] = factinv[0] = 1;
    for (auto i = 1; i < MAX_SIZE; i++)
    {
      fact[i] = mint(i) * fact[i - 1];
      factinv[i] = inv[i] * factinv[i - 1];
    }
  }
  mint operator()(int n, int k)
  {
    if (n >= 0 && k >= 0 && n - k >= 0)
    {
      return fact[n] * factinv[k] * factinv[n - k];
    }
    return 0;
  }
};
int combination::MAX_SIZE = 1e6 + 10;
ll gcd(ll x, ll y) { return y ? gcd(y, x % y) : x; }
// const double epsilon = 1e-10;
// const ll infty = 1000000000000000LL;
// const int dx[4] = {1, 0, -1, 0};
// const int dy[4] = {0, 1, 0, -1};

class UnionFind
{
  vector<long long> par;

public:
  UnionFind() {}
  UnionFind(int n) : par(n, -1) {}

  bool is_same(int x, int y)
  {
    return root(x) == root(y);
  }

  bool merge(int x, int y)
  {
    x = root(x);
    y = root(y);
    if (x == y)
    {
      return false;
    }
    if (par[x] > par[y])
    {
      swap(x, y);
    }
    par[x] += par[y];
    par[y] = x;
    return true;
  }

  long long size(int x)
  {
    return -par[root(x)];
  }

private:
  int root(int x)
  {
    if (par[x] < 0)
    {
      return x;
    }
    return par[x] = root(par[x]);
  }
};

using edge = tuple<int, int>;

int N, M;
vector<edge> E;
vector<edge> ans;
int cnt[100010];
vector<int> V[100010];

void Yes()
{
  for (auto x : ans)
  {
    cout << get<0>(x) + 1 << " " << get<1>(x) + 1 << endl;
  }
  exit(0);
}

void No()
{
  cout << "-1" << endl;
  exit(0);
}

void make_V()
{
  UnionFind uf{N};
  for (auto e : E)
  {
    int a, b;
    tie(a, b) = e;
    if (!uf.is_same(a, b))
    {
      uf.merge(a, b);
      V[a].push_back(b);
      V[b].push_back(a);
    }
    else
    {
      ans.push_back(e);
      cnt[a]++;
    }
  }
}

void dfs(int v, int p = -1)
{
  for (auto w : V[v])
  {
    if (p != w)
    {
      dfs(w, v);
    }
  }
  if (p == -1)
  {
    return;
  }
  if (cnt[v] % 2 == 1)
  {
    ans.push_back(edge(v, p));
    cnt[v]++;
  }
  else
  {
    ans.push_back(edge(p, v));
    cnt[p]++;
  }
}

void solve()
{
  make_V();
  dfs(0);
}

int main()
{
  cin >> N >> M;
  for (auto i = 0; i < M; i++)
  {
    int a, b;
    cin >> a >> b;
    --a;
    --b;
    E.push_back(edge(a, b));
  }
  if (M % 2 == 1)
  {
    No();
  }
  solve();
  Yes();
}<|endoftext|>