<commit_before>
#include "CMainMenuState.h"

#include "CMainState.h"
#include "ColorMappers.h"
#include "CGUILoadingWidget.h"
#include "CDataLoadingThread.h"
#include "SciDataManager.h"
#include "CGlyphSceneObject.h"

CMainMenuState::CMainMenuState()
{}

void CMainMenuState::Begin()
{
	Context->GUIContext->SetupMenuState();
	std::cout << "Menu State begin." << std::endl;
}

void CMainMenuState::End()
{
	Context->GUIContext->Clear();
	std::cout << "Menu State end." << std::endl;
}

void CMainMenuState::Update(f32 const Elapsed)
{
	printOpenGLErrors();
	// Let loading thread run
	//sf::sleep(sf::seconds(0.05f));
	std::chrono::milliseconds Milliseconds(50);
	std::this_thread::sleep_for(Milliseconds);

	Thread.Sync();

	Context->GUIContext->Draw(Elapsed, true);
	CApplication::Get().GetWindow().SwapBuffers();

	static int counter = 0;

	if (! counter--)
	{
		//createDataSet();
		loadData(//"DenmarkMission1.dat");
			"HopavagenBay1.dat");
	}

	//loaded = true;
}

void CMainMenuState::OnEvent(SWindowResizedEvent & Event)
{
	Context->GUIContext->GetCanvas()->SetSize(Event.Size.X, Event.Size.Y);
	Context->GUIContext->GetCanvas()->Invalidate();
	Context->GUIContext->GetCanvas()->InvalidateChildren(true);
}

void CMainMenuState::loadData(std::string const & FileName)
{
	DataSetName = FileName;

	std::stringstream s;
	s << "Datasets/";
	s << FileName;

	Thread.Context = Context;
	Context->GUIContext->AddWidget(Thread.LoadingWidget = new CGUILoadingWidget("Loading data and initializing scene elements"));
	Thread.Run(s.str());
}

void CMainMenuState::createDataSet()
{
	if (false)
	{
		SciDataParserSimpleTXT * Parser = new SciDataParserSimpleTXT();
		Parser->Manager = Context->DataManager;
		Parser->load("ForZoe.txt");

		//DataParser->RawValues.setDataScale(Vector3(3, 2, 3));

		CSpectrumColorMapper sf("d1");
		COxygenColorMapper o("d1");
		sf.AcceptedRange = Range(-9999999.0, 9999999.0);

		//Context->DataManager->createPointCloudObjects(true, Context->Scene.PointCloudObject, SVector3f(-3.f, 0.8f, 3.f), & o);
		//DataParser[0]->createGridDataFromRawValues(FullRange, 5.0, "d1");
		//DataParser[0]->createPointCloudObjects(false, SoupObject, SVector3f(3.f), & sf);
		//DataParser[0]->createVolumeFromGridValues(& sf);
	}

	if (false)
	{
		SciDataParserCTD * Parser = new SciDataParserCTD();
		Parser->Manager = Context->DataManager;
		Parser->examine("oxygenDataSet1.mat");

		//DataParser->RawValues.setDataScale(Vector3(3, 2, 3));

		CSpectrumColorMapper sf("salinity");
		sf.AcceptedRange = Range(-99999.0, 99999.0);

		//DataParser[1]->createPointCloudObjects(true, VoxelObject, SVector3f(3.f), & sf);
		Parser->Manager->createGridDataFromRawValues(sf.AcceptedRange, 5.0, "salinity");
		//DataParser->createPointCloudObjects(false, SoupObject, SVector3f(3.f), & sf);
		//DataParser->createVolumeFromGridValues(& sf);
	}

	if (true)
	{
		SciDataParserGrid1 * Parser = new SciDataParserGrid1();
		Parser->Manager = Context->DataManager;
		Parser->load("oxyMaps.mat");

		//DataParser->GridValues.setDataScale(Vector3(3, 2, 3));

		CRGBIntensityColorMapper r("o1", "o2", "o3");
		CSingleFieldColorMapper sf("o1");
		COxygenColorMapper o;
		//COxygenLocalizedColorMapper l;

		Context->DataManager->createVolumeFromGridValues(& o);
		/*Context->DataManager->createPointCloudObjects(false, Context->Scene.GridObject, SVector3f(3.f), & o);
		Context->Scene.VolumeSceneObject->VolumeHandle = Context->DataManager->VolumeHandle;*/
	}

	if (true)
	{
		SciDataParserCSV * Parser1 = new SciDataParserCSV();
		Parser1->Manager = Context->DataManager;
		Parser1->mergedLoad("OxyData.csv", "LogData.csv", "Time");
		/*
		COxygenColorMapper o("AirSaturation(%)");

		Context->DataManager->createPointCloudObjects(true, Context->Scene.PointCloudObject, SVector3f(1.f/*-3.f, 0.8f, 3.f*), & o);*/
	}

	Context->DataManager->writeToFile("Datasets/HopavagenBayNew1.dat");
}
<commit_msg>+ Simplified hopavagen data set creation<commit_after>
#include "CMainMenuState.h"

#include "CMainState.h"
#include "ColorMappers.h"
#include "CGUILoadingWidget.h"
#include "CDataLoadingThread.h"
#include "SciDataManager.h"
#include "CGlyphSceneObject.h"

CMainMenuState::CMainMenuState()
{}

void CMainMenuState::Begin()
{
	Context->GUIContext->SetupMenuState();
	std::cout << "Menu State begin." << std::endl;
}

void CMainMenuState::End()
{
	Context->GUIContext->Clear();
	std::cout << "Menu State end." << std::endl;
}

void CMainMenuState::Update(f32 const Elapsed)
{
	printOpenGLErrors();
	// Let loading thread run
	//sf::sleep(sf::seconds(0.05f));
	std::chrono::milliseconds Milliseconds(50);
	std::this_thread::sleep_for(Milliseconds);

	Thread.Sync();

	Context->GUIContext->Draw(Elapsed, true);
	CApplication::Get().GetWindow().SwapBuffers();

	static int counter = 0;

	if (! counter--)
	{
		createDataSet();
		loadData(//"DenmarkMission1.dat");
			"HopavagenBayNew1.dat");
	}

	//loaded = true;
}

void CMainMenuState::OnEvent(SWindowResizedEvent & Event)
{
	Context->GUIContext->GetCanvas()->SetSize(Event.Size.X, Event.Size.Y);
	Context->GUIContext->GetCanvas()->Invalidate();
	Context->GUIContext->GetCanvas()->InvalidateChildren(true);
}

void CMainMenuState::loadData(std::string const & FileName)
{
	DataSetName = FileName;

	std::stringstream s;
	s << "Datasets/";
	s << FileName;

	Thread.Context = Context;
	Context->GUIContext->AddWidget(Thread.LoadingWidget = new CGUILoadingWidget("Loading data and initializing scene elements"));
	Thread.Run(s.str());
}

void CMainMenuState::createDataSet()
{
	SciDataParserSimpleTXT * Parser1 = new SciDataParserSimpleTXT();
	Parser1->Manager = Context->DataManager;
	Parser1->load("ForZoe.txt");

	SciDataParserGrid1 * Parser2 = new SciDataParserGrid1();
	Parser2->Manager = Context->DataManager;
	Parser2->load("oxyMaps.mat");

	COxygenColorMapper o;
	Context->DataManager->createVolumeFromGridValues(& o);
	Context->DataManager->writeToFile("Datasets/HopavagenBay1.dat");
}
<|endoftext|>


<commit_before>//===- SyntaxColoring.cpp - Routines for syntax coloring ------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//

#include "swift/IDE/SyntaxColoring.h"
#include "swift/AST/ASTContext.h"
#include "swift/AST/ASTWalker.h"
#include "swift/AST/Decl.h"
#include "swift/AST/Module.h"
#include "swift/AST/TypeRepr.h"
#include "swift/Basic/SourceManager.h"
#include "swift/Parse/Lexer.h"
#include "swift/Parse/Token.h"
#include "swift/Subsystems.h"
#include "llvm/Support/MemoryBuffer.h"
#include <vector>

using namespace swift;
using namespace ide;

void SyntaxColorWalker::anchor() {}

struct SyntaxColoringContext::Implementation {
  std::vector<SyntaxNode> TokenNodes;
};

SyntaxColoringContext::SyntaxColoringContext(SourceManager &SM,
                                             unsigned BufferID,
                                             TranslationUnit &TU)
  : Impl(*new Implementation()),
    TU(TU) {
  std::vector<Token> Tokens = swift::tokenize(SM, BufferID, /*Offset=*/0,
                                              /*EndOffset=*/0,
                                              /*KeepComments=*/true,
                                           /*TokenizeInterpolatedString=*/true);
  std::vector<SyntaxNode> Nodes;
  for (auto &Tok : Tokens) {
    SyntaxNodeKind Kind;
    switch(Tok.getKind()) {
#define KEYWORD(X) case tok::kw_##X: Kind = SyntaxNodeKind::Keyword; break;
#include "swift/Parse/Tokens.def"
#undef KEYWORD

    case tok::dollarident: Kind = SyntaxNodeKind::DollarIdent; break;
    case tok::integer_literal: Kind = SyntaxNodeKind::Integer; break;
    case tok::floating_literal: Kind = SyntaxNodeKind::Floating; break;
    case tok::string_literal: Kind = SyntaxNodeKind::String; break;
    case tok::character_literal: Kind = SyntaxNodeKind::Character; break;
    case tok::comment:
      if (Tok.getText().startswith("//"))
        Kind = SyntaxNodeKind::CommentLine;
      else
        Kind = SyntaxNodeKind::CommentBlock;
      break;

    default:
      continue;
    }

    assert(Tok.getLoc().isValid());
    assert(Nodes.empty() || SM.isBeforeInBuffer(Nodes.back().Range.getStart(),
                                                Tok.getLoc()));
    Nodes.emplace_back(Kind, CharSourceRange(Tok.getLoc(), Tok.getLength()));
  }

  Impl.TokenNodes = std::move(Nodes);
}

SyntaxColoringContext::~SyntaxColoringContext() {
  delete &Impl;
}

namespace {

class ColorASTWalker : public ASTWalker {
  const SourceManager &SM;

public:
  SyntaxColorWalker &SCWalker;
  ArrayRef<SyntaxNode> TokenNodes;

  ColorASTWalker(const SourceManager &SM, SyntaxColorWalker &SCWalker)
      : SM(SM), SCWalker(SCWalker) { }

  void visitTranslationUnit(TranslationUnit &TU, ArrayRef<SyntaxNode> Tokens);

  virtual bool walkToTypeReprPre(TypeRepr *T);

private:
  bool passTokenNodesUntil(SourceLoc Loc, bool Inclusive);
  bool passNonTokenNode(const SyntaxNode &Node);
  bool passNode(const SyntaxNode &Node);
};

} // anonymous namespace

bool SyntaxColoringContext::walk(SyntaxColorWalker &Walker) {
  ColorASTWalker ASTWalk(TU.Ctx.SourceMgr, Walker);
  ASTWalk.visitTranslationUnit(TU, Impl.TokenNodes);
  return true;
}

void ColorASTWalker::visitTranslationUnit(TranslationUnit &TU,
                                          ArrayRef<SyntaxNode> Tokens) {
  TokenNodes = Tokens;
  for (Decl *D : TU.Decls)
    D->walk(*this);

  // Pass the rest of the token nodes.
  for (auto &TokNode : TokenNodes)
    passNode(TokNode);
}

bool ColorASTWalker::walkToTypeReprPre(TypeRepr *T) {
  if (IdentTypeRepr *IdT = dyn_cast<IdentTypeRepr>(T)) {
    for (auto &comp : IdT->Components) {
      if (!passNonTokenNode({ SyntaxNodeKind::TypeId,
                              CharSourceRange(comp.getIdLoc(),
                                              comp.getIdentifier().getLength())
                            }))
        return false;
    }
  }
  return true;
}

bool ColorASTWalker::passTokenNodesUntil(SourceLoc Loc, bool Inclusive) {
  assert(Loc.isValid());
  unsigned I = 0;
  for (unsigned E = TokenNodes.size(); I != E; ++I) {
    SourceLoc TokLoc = TokenNodes[I].Range.getStart();
    if (SM.isBeforeInBuffer(Loc, TokLoc) || (!Inclusive && TokLoc == Loc)) {
      break;
    }
    if (!passNode(TokenNodes[I]))
      return false;
  }

  TokenNodes = TokenNodes.slice(I);
  return true;
}

bool ColorASTWalker::passNonTokenNode(const SyntaxNode &Node) {
  if (!passTokenNodesUntil(Node.Range.getStart(), /*Inclusive=*/false))
    return false;
  if (!passNode(Node))
    return false;
  return true;
}

bool ColorASTWalker::passNode(const SyntaxNode &Node) {
  SCWalker.walkToNodePre(Node);
  if (!SCWalker.walkToNodePost(Node))
    return false;
  return true;
}
<commit_msg>Add support for skipping / displacing SyntaxNode tokens, so that we can effectively replace Identifier nodes with TypeId nodes. Reenable SyntaxNodeKind::Identifier.<commit_after>//===- SyntaxColoring.cpp - Routines for syntax coloring ------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//

#include "swift/IDE/SyntaxColoring.h"
#include "swift/AST/ASTContext.h"
#include "swift/AST/ASTWalker.h"
#include "swift/AST/Decl.h"
#include "swift/AST/Module.h"
#include "swift/AST/TypeRepr.h"
#include "swift/Basic/SourceManager.h"
#include "swift/Parse/Lexer.h"
#include "swift/Parse/Token.h"
#include "swift/Subsystems.h"
#include "llvm/Support/MemoryBuffer.h"
#include <vector>

using namespace swift;
using namespace ide;

void SyntaxColorWalker::anchor() {}

struct SyntaxColoringContext::Implementation {
  std::vector<SyntaxNode> TokenNodes;
};

SyntaxColoringContext::SyntaxColoringContext(SourceManager &SM,
                                             unsigned BufferID,
                                             TranslationUnit &TU)
  : Impl(*new Implementation()),
    TU(TU) {
  std::vector<Token> Tokens = swift::tokenize(SM, BufferID, /*Offset=*/0,
                                              /*EndOffset=*/0,
                                              /*KeepComments=*/true,
                                           /*TokenizeInterpolatedString=*/true);
  std::vector<SyntaxNode> Nodes;
  for (auto &Tok : Tokens) {
    SyntaxNodeKind Kind;
    switch(Tok.getKind()) {
#define KEYWORD(X) case tok::kw_##X: Kind = SyntaxNodeKind::Keyword; break;
#include "swift/Parse/Tokens.def"
#undef KEYWORD

    case tok::identifier: Kind = SyntaxNodeKind::Identifier; break;
    case tok::dollarident: Kind = SyntaxNodeKind::DollarIdent; break;
    case tok::integer_literal: Kind = SyntaxNodeKind::Integer; break;
    case tok::floating_literal: Kind = SyntaxNodeKind::Floating; break;
    case tok::string_literal: Kind = SyntaxNodeKind::String; break;
    case tok::character_literal: Kind = SyntaxNodeKind::Character; break;
    case tok::comment:
      if (Tok.getText().startswith("//"))
        Kind = SyntaxNodeKind::CommentLine;
      else
        Kind = SyntaxNodeKind::CommentBlock;
      break;

    default:
      continue;
    }

    assert(Tok.getLoc().isValid());
    assert(Nodes.empty() || SM.isBeforeInBuffer(Nodes.back().Range.getStart(),
                                                Tok.getLoc()));
    Nodes.emplace_back(Kind, CharSourceRange(Tok.getLoc(), Tok.getLength()));
  }

  Impl.TokenNodes = std::move(Nodes);
}

SyntaxColoringContext::~SyntaxColoringContext() {
  delete &Impl;
}

namespace {

class ColorASTWalker : public ASTWalker {
  const SourceManager &SM;

public:
  SyntaxColorWalker &SCWalker;
  ArrayRef<SyntaxNode> TokenNodes;

  ColorASTWalker(const SourceManager &SM, SyntaxColorWalker &SCWalker)
      : SM(SM), SCWalker(SCWalker) { }

  void visitTranslationUnit(TranslationUnit &TU, ArrayRef<SyntaxNode> Tokens);

  virtual bool walkToTypeReprPre(TypeRepr *T);

private:
  enum PassNodesBehavior {
    //Pass all nodes up to but not including the location
    ExcludeNodeAtLocation,
    //Pass all nodes up to and including the location
    IncludeNodeAtLocation,
    //Like ExcludeNodeAtLocation, and skip past any node at the location
    DisplaceNodeAtLocation
  };
  bool passTokenNodesUntil(SourceLoc Loc, PassNodesBehavior Behavior);
  bool passNonTokenNode(const SyntaxNode &Node);
  bool passNode(const SyntaxNode &Node);
};

} // anonymous namespace

bool SyntaxColoringContext::walk(SyntaxColorWalker &Walker) {
  ColorASTWalker ASTWalk(TU.Ctx.SourceMgr, Walker);
  ASTWalk.visitTranslationUnit(TU, Impl.TokenNodes);
  return true;
}

void ColorASTWalker::visitTranslationUnit(TranslationUnit &TU,
                                          ArrayRef<SyntaxNode> Tokens) {
  TokenNodes = Tokens;
  for (Decl *D : TU.Decls)
    D->walk(*this);

  // Pass the rest of the token nodes.
  for (auto &TokNode : TokenNodes)
    passNode(TokNode);
}

bool ColorASTWalker::walkToTypeReprPre(TypeRepr *T) {
  if (IdentTypeRepr *IdT = dyn_cast<IdentTypeRepr>(T)) {
    for (auto &comp : IdT->Components) {
      if (!passNonTokenNode({ SyntaxNodeKind::TypeId,
                              CharSourceRange(comp.getIdLoc(),
                                              comp.getIdentifier().getLength())
                            }))
        return false;
    }
  }
  return true;
}

bool ColorASTWalker::passTokenNodesUntil(SourceLoc Loc,
                                         PassNodesBehavior Behavior) {
  assert(Loc.isValid());
  unsigned I = 0;
  for (unsigned E = TokenNodes.size(); I != E; ++I) {
    SourceLoc TokLoc = TokenNodes[I].Range.getStart();
    if (SM.isBeforeInBuffer(Loc, TokLoc)) {
      break;
    }
    if (TokLoc == Loc && Behavior != IncludeNodeAtLocation) {
      if (Behavior == DisplaceNodeAtLocation) {
        //Skip past the node directly at the specified location, allowing the
        //caller to effectively replace it.
        ++I;
      }
      break;
    }
    if (!passNode(TokenNodes[I]))
      return false;
  }

  TokenNodes = TokenNodes.slice(I);
  return true;
}

bool ColorASTWalker::passNonTokenNode(const SyntaxNode &Node) {
  if (!passTokenNodesUntil(Node.Range.getStart(), DisplaceNodeAtLocation))
    return false;
  if (!passNode(Node))
    return false;
  return true;
}

bool ColorASTWalker::passNode(const SyntaxNode &Node) {
  SCWalker.walkToNodePre(Node);
  if (!SCWalker.walkToNodePost(Node))
    return false;
  return true;
}
<|endoftext|>


<commit_before>/********************************************************************
 * AUTHORS: Mate Soos
 *
 * BEGIN DATE: November, 2013
 *
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.
********************************************************************/

#include "stp/Sat/CryptoMinisat4.h"

#undef var_Undef
#undef l_True
#undef l_False
#undef l_Undef

#include "cryptominisat4/cryptominisat.h"
#include <vector>
using std::vector;

namespace stp
{

CryptoMinisat4::CryptoMinisat4()
{
  s = new CMSat::SATSolver;
  // s->log_to_file("stp.cnf");
  // s->set_num_threads(3);
  temp_cl = (void*)new std::vector<CMSat::Lit>;
}

CryptoMinisat4::~CryptoMinisat4()
{
  delete s;
  vector<CMSat::Lit>* real_temp_cl = (vector<CMSat::Lit>*)temp_cl;
  delete real_temp_cl;
}

void CryptoMinisat4::setMaxConflicts(int64_t max_confl)
{
  if (max_confl> 0)
    s->set_max_confl(max_confl);
}

bool
CryptoMinisat4::addClause(const vec_literals& ps) // Add a clause to the solver.
{
  // Cryptominisat uses a slightly different vec class.
  // Cryptominisat uses a slightly different Lit class too.

  vector<CMSat::Lit>& real_temp_cl = *(vector<CMSat::Lit>*)temp_cl;
  real_temp_cl.clear();
  for (int i = 0; i < ps.size(); i++)
  {
    real_temp_cl.push_back(CMSat::Lit(var(ps[i]), sign(ps[i])));
  }

  return s->add_clause(real_temp_cl);
}

bool
CryptoMinisat4::okay() const // FALSE means solver is in a conflicting state
{
  return s->okay();
}

bool CryptoMinisat4::solve(bool& timeout_expired) // Search without assumptions.
{
  CMSat::lbool ret = s->solve();
  if (ret == CMSat::l_Undef) {
    timeout_expired = true;
  }
  return ret == CMSat::l_True;
}

uint8_t CryptoMinisat4::modelValue(uint32_t x) const
{
  return (s->get_model().at(x) == CMSat::l_True);
}

uint32_t CryptoMinisat4::newVar()
{
  s->new_var();
  return s->nVars() - 1;
}

void CryptoMinisat4::setVerbosity(int v)
{
  // s->conf.verbosity = v;
}

unsigned long CryptoMinisat4::nVars() const
{
  return s->nVars();
}

void CryptoMinisat4::printStats() const
{
  // s->printStats();
}

} //end namespace stp
<commit_msg>No need for these UNDEF-s<commit_after>/********************************************************************
 * AUTHORS: Mate Soos
 *
 * BEGIN DATE: November, 2013
 *
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.
********************************************************************/

#include "stp/Sat/CryptoMinisat4.h"
#include "cryptominisat4/cryptominisat.h"
#include <vector>
using std::vector;

namespace stp
{

CryptoMinisat4::CryptoMinisat4()
{
  s = new CMSat::SATSolver;
  // s->log_to_file("stp.cnf");
  // s->set_num_threads(3);
  temp_cl = (void*)new std::vector<CMSat::Lit>;
}

CryptoMinisat4::~CryptoMinisat4()
{
  delete s;
  vector<CMSat::Lit>* real_temp_cl = (vector<CMSat::Lit>*)temp_cl;
  delete real_temp_cl;
}

void CryptoMinisat4::setMaxConflicts(int64_t max_confl)
{
  if (max_confl> 0)
    s->set_max_confl(max_confl);
}

bool
CryptoMinisat4::addClause(const vec_literals& ps) // Add a clause to the solver.
{
  // Cryptominisat uses a slightly different vec class.
  // Cryptominisat uses a slightly different Lit class too.

  vector<CMSat::Lit>& real_temp_cl = *(vector<CMSat::Lit>*)temp_cl;
  real_temp_cl.clear();
  for (int i = 0; i < ps.size(); i++)
  {
    real_temp_cl.push_back(CMSat::Lit(var(ps[i]), sign(ps[i])));
  }

  return s->add_clause(real_temp_cl);
}

bool
CryptoMinisat4::okay() const // FALSE means solver is in a conflicting state
{
  return s->okay();
}

bool CryptoMinisat4::solve(bool& timeout_expired) // Search without assumptions.
{
  CMSat::lbool ret = s->solve();
  if (ret == CMSat::l_Undef) {
    timeout_expired = true;
  }
  return ret == CMSat::l_True;
}

uint8_t CryptoMinisat4::modelValue(uint32_t x) const
{
  return (s->get_model().at(x) == CMSat::l_True);
}

uint32_t CryptoMinisat4::newVar()
{
  s->new_var();
  return s->nVars() - 1;
}

void CryptoMinisat4::setVerbosity(int v)
{
  // s->conf.verbosity = v;
}

unsigned long CryptoMinisat4::nVars() const
{
  return s->nVars();
}

void CryptoMinisat4::printStats() const
{
  // s->printStats();
}

} //end namespace stp
<|endoftext|>


<commit_before>//===--- CSDiagnostics.cpp - Constraint Diagnostics -----------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// This file implements diagnostics for constraint system.
//
//===----------------------------------------------------------------------===//

#include "ConstraintSystem.h"
#include "CSDiagnostics.h"
#include "MiscDiagnostics.h"
#include "swift/AST/Expr.h"
#include "swift/AST/Types.h"
#include "llvm/ADT/ArrayRef.h"

using namespace swift;
using namespace constraints;

FailureDiagnostic::~FailureDiagnostic() {}

std::pair<Expr *, bool> FailureDiagnostic::computeAnchor() const {
  auto &cs = getConstraintSystem();

  auto *locator = getLocator();
  // Resolve the locator to a specific expression.
  SourceRange range;
  bool isSubscriptMember =
      (!locator->getPath().empty() && locator->getPath().back().getKind() ==
                                          ConstraintLocator::SubscriptMember);

  ConstraintLocator *resolved = simplifyLocator(cs, locator, range);
  if (!resolved || !resolved->getAnchor())
    return {locator->getAnchor(), true};

  Expr *anchor = resolved->getAnchor();
  // FIXME: Work around an odd locator representation that doesn't separate the
  // base of a subscript member from the member access.
  if (isSubscriptMember) {
    if (auto subscript = dyn_cast<SubscriptExpr>(anchor))
      anchor = subscript->getBase();
  }

  return {anchor, !resolved->getPath().empty()};
}

Type FailureDiagnostic::getType(Expr *expr) const {
  auto &cs = getConstraintSystem();
  return solution.simplifyType(cs.getType(expr));
}

template <typename... ArgTypes>
InFlightDiagnostic
FailureDiagnostic::emitDiagnostic(ArgTypes &&... Args) const {
  auto &cs = getConstraintSystem();
  return cs.TC.diagnose(std::forward<ArgTypes>(Args)...);
}

Type RequirementFailure::getOwnerType() const {
  return getType(getAnchor())->getRValueInstanceType();
}

const Requirement &RequirementFailure::getRequirement() {
  auto *genericCtx = AffectedDecl->getAsGenericContext();
  return genericCtx->getGenericRequirements()[getRequirementIndex()];
}

ValueDecl *RequirementFailure::getDeclRef() const {
  auto &cs = getConstraintSystem();

  auto *anchor = getAnchor();
  auto *locator = cs.getConstraintLocator(anchor);
  if (auto *AE = dyn_cast<CallExpr>(anchor)) {
    assert(isa<TypeExpr>(AE->getFn()));
    ConstraintLocatorBuilder ctor(locator);
    locator = cs.getConstraintLocator(
        ctor.withPathElement(PathEltKind::ApplyFunction)
            .withPathElement(PathEltKind::ConstructorMember));
  } else if (auto *UDE = dyn_cast<UnresolvedDotExpr>(anchor)) {
    ConstraintLocatorBuilder member(locator);
    locator =
        cs.getConstraintLocator(member.withPathElement(PathEltKind::Member));
  }

  auto overload = getOverloadChoiceIfAvailable(locator);
  if (overload)
    return overload->choice.getDecl();

  auto ownerType = getOwnerType();
  if (auto *NA = dyn_cast<NameAliasType>(ownerType.getPointer()))
    return NA->getDecl();

  return ownerType->getAnyGeneric();
}

bool MissingConformanceFailure::diagnose() {
  auto *anchor = getAnchor();
  auto ownerType = getOwnerType();
  auto type = getNonConformingType();
  auto protocolType = getProtocolType();

  //  Find `ApplyExpr` based on a function expression attached to it.
  auto findApplyExpr = [](Expr *parent, Expr *fnExpr) -> ApplyExpr * {
    ApplyExpr *applyExpr = nullptr;
    parent->forEachChildExpr([&applyExpr, &fnExpr](Expr *subExpr) -> Expr * {
      auto *AE = dyn_cast<ApplyExpr>(subExpr);
      if (!AE || AE->getFn() != fnExpr)
        return subExpr;

      applyExpr = AE;
      return nullptr;
    });
    return applyExpr;
  };

  auto getArgumentAt = [](ApplyExpr *AE, unsigned index) -> Expr * {
    assert(AE);

    auto *arg = AE->getArg();
    if (auto *TE = dyn_cast<TupleExpr>(arg))
      return TE->getElement(index);

    assert(index == 0);
    if (auto *PE = dyn_cast<ParenExpr>(arg))
      return PE->getSubExpr();

    return arg;
  };

  auto *applyExpr = findApplyExpr(getParentExpr(), anchor);

  Optional<unsigned> atParameterPos;
  // Sometimes fix is recorded by type-checking sub-expression
  // during normal diagnostics, in such case call expression
  // is unavailable.
  if (applyExpr) {
    // If this is a static, initializer or operator call,
    // let's not try to diagnose it here, but refer to expression
    // diagnostics.
    if (isa<BinaryExpr>(applyExpr) || isa<TypeExpr>(anchor))
      return false;

    if (auto *fnType = ownerType->getAs<AnyFunctionType>()) {
      auto parameters = fnType->getParams();
      for (auto index : indices(parameters)) {
        if (parameters[index].getType()->isEqual(type)) {
          atParameterPos = index;
          break;
        }
      }
    }
  }

  if (type->isExistentialType()) {
    auto diagnostic = diag::protocol_does_not_conform_objc;
    if (type->isObjCExistentialType())
      diagnostic = diag::protocol_does_not_conform_static;

    emitDiagnostic(anchor->getLoc(), diagnostic, type, protocolType);
  } else if (atParameterPos) {
    // Requirement comes from one of the parameter types,
    // let's try to point diagnostic to the argument expression.
    auto *argExpr = getArgumentAt(applyExpr, *atParameterPos);
    emitDiagnostic(argExpr->getLoc(),
                   diag::cannot_convert_argument_value_protocol, type,
                   protocolType);
  } else {
    const auto &req = getRequirement();
    auto *genericCtx = AffectedDecl->getAsGenericContext();

    std::function<const DeclContext *(Type)> getAffectedCtx =
        [&](Type type) -> const DeclContext * {
      if (auto *DMT = type->getAs<DependentMemberType>())
        return getAffectedCtx(DMT->getBase());

      if (auto *GPT = type->getAs<GenericTypeParamType>())
        return GPT->getDecl()->getDeclContext();

      return genericCtx;
    };

    const auto *affected = getAffectedCtx(req.getFirstType());
    if (affected != genericCtx) {
      auto *NTD = affected->getAsNominalTypeOrNominalTypeExtensionContext();
      emitDiagnostic(anchor->getLoc(), diag::type_does_not_conform_in_decl_ref,
                     AffectedDecl->getDescriptiveKind(),
                     AffectedDecl->getFullName(), NTD->getDeclaredType(), type,
                     protocolType);
    } else {
      emitDiagnostic(anchor->getLoc(), diag::type_does_not_conform_decl_owner,
                     AffectedDecl->getDescriptiveKind(),
                     AffectedDecl->getFullName(), type, protocolType);
    }

    emitDiagnostic(affected->getAsDeclOrDeclExtensionContext(),
                   diag::where_type_does_not_conform_type, req.getFirstType(),
                   type);
  }
  return true;
}

bool LabelingFailure::diagnose() {
  auto &cs = getConstraintSystem();
  auto *call = cast<CallExpr>(getAnchor());
  return diagnoseArgumentLabelError(cs.getASTContext(), call->getArg(),
                                    CorrectLabels,
                                    isa<SubscriptExpr>(call->getFn()));
}

bool NoEscapeFuncToTypeConversionFailure::diagnose() {
  auto *anchor = getAnchor();

  if (ConvertTo) {
    emitDiagnostic(anchor->getLoc(), diag::converting_noescape_to_type,
                   ConvertTo);
    return true;
  }

  auto path = getLocator()->getPath();
  if (path.empty())
    return false;

  auto &last = path.back();
  if (last.getKind() != ConstraintLocator::Archetype)
    return false;

  auto *archetype = last.getArchetype();
  emitDiagnostic(anchor->getLoc(), diag::converting_noescape_to_type,
                 archetype);
  return true;
}

bool MissingForcedDowncastFailure::diagnose() {
  if (hasComplexLocator())
    return false;

  auto &TC = getTypeChecker();

  auto *coerceExpr = dyn_cast<CoerceExpr>(getAnchor());
  if (!coerceExpr)
    return false;

  auto *subExpr = coerceExpr->getSubExpr();
  auto fromType = getType(subExpr)->getRValueType();
  auto toType = resolveType(coerceExpr->getCastTypeLoc().getType());

  auto castKind =
      TC.typeCheckCheckedCast(fromType, toType, CheckedCastContextKind::None,
                              getDC(), coerceExpr->getLoc(), subExpr,
                              coerceExpr->getCastTypeLoc().getSourceRange());

  switch (castKind) {
  // Invalid cast.
  case CheckedCastKind::Unresolved:
    // Fix didn't work, let diagnoseFailureForExpr handle this.
    return false;
  case CheckedCastKind::Coercion:
  case CheckedCastKind::BridgingCoercion:
    llvm_unreachable("Coercions handled in other disjunction branch");

  // Valid casts.
  case CheckedCastKind::ArrayDowncast:
  case CheckedCastKind::DictionaryDowncast:
  case CheckedCastKind::SetDowncast:
  case CheckedCastKind::ValueCast:
    emitDiagnostic(coerceExpr->getLoc(), diag::missing_forced_downcast,
                   fromType, toType)
        .highlight(coerceExpr->getSourceRange())
        .fixItReplace(coerceExpr->getLoc(), "as!");
    return true;
  }
}

bool MissingAddressOfFailure::diagnose() {
  if (hasComplexLocator())
    return false;

  auto *anchor = getAnchor();
  auto type = getType(anchor)->getRValueType();
  emitDiagnostic(anchor->getLoc(), diag::missing_address_of, type)
      .fixItInsert(anchor->getStartLoc(), "&");
  return true;
}

bool MissingExplicitConversionFailure::diagnose() {
  if (hasComplexLocator())
    return false;

  auto *DC = getDC();
  auto &TC = getTypeChecker();

  auto *anchor = getAnchor();
  if (auto *paren = dyn_cast<ParenExpr>(anchor))
    anchor = paren->getSubExpr();

  auto fromType = getType(anchor)->getRValueType();
  Type toType = resolveType(ConvertingTo);
  bool useAs = TC.isExplicitlyConvertibleTo(fromType, toType, DC);
  bool useAsBang = !useAs && TC.checkedCastMaySucceed(fromType, toType, DC);
  if (!useAs && !useAsBang)
    return false;

  auto *expr = getParentExpr();
  // If we're performing pattern matching,
  // "as" means something completely different...
  if (auto binOpExpr = dyn_cast<BinaryExpr>(expr)) {
    auto overloadedFn = dyn_cast<OverloadedDeclRefExpr>(binOpExpr->getFn());
    if (overloadedFn && !overloadedFn->getDecls().empty()) {
      ValueDecl *decl0 = overloadedFn->getDecls()[0];
      if (decl0->getBaseName() == decl0->getASTContext().Id_MatchOperator)
        return false;
    }
  }

  bool needsParensInside = exprNeedsParensBeforeAddingAs(anchor);
  bool needsParensOutside = exprNeedsParensAfterAddingAs(anchor, expr);

  llvm::SmallString<2> insertBefore;
  llvm::SmallString<32> insertAfter;
  if (needsParensOutside) {
    insertBefore += "(";
  }
  if (needsParensInside) {
    insertBefore += "(";
    insertAfter += ")";
  }
  insertAfter += useAs ? " as " : " as! ";
  insertAfter += toType->getWithoutParens()->getString();
  if (needsParensOutside)
    insertAfter += ")";

  auto diagID =
      useAs ? diag::missing_explicit_conversion : diag::missing_forced_downcast;
  auto diag = emitDiagnostic(anchor->getLoc(), diagID, fromType, toType);
  if (!insertBefore.empty()) {
    diag.fixItInsert(anchor->getStartLoc(), insertBefore);
  }
  diag.fixItInsertAfter(anchor->getEndLoc(), insertAfter);
  return true;
}

bool MemberAccessOnOptionalBaseFailure::diagnose() {
  if (hasComplexLocator())
    return false;

  auto *anchor = getAnchor();
  auto type = getType(anchor)->getRValueType();
  bool resultIsOptional = ResultTypeIsOptional;

  // If we've resolved the member overload to one that returns an optional
  // type, then the result of the expression is optional (and we want to offer
  // only a '?' fixit) even though the constraint system didn't need to add any
  // additional optionality.
  auto overload = getResolvedOverload(getLocator());
  if (overload && overload->ImpliedType->getOptionalObjectType())
    resultIsOptional = true;

  return diagnoseBaseUnwrapForMemberAccess(anchor, type, Member,
                                           resultIsOptional, SourceRange());
}

bool MissingOptionalUnwrapFailure::diagnose() {
  if (hasComplexLocator())
    return false;

  auto *anchor = getAnchor();
  auto *unwrapped = anchor->getValueProvidingExpr();
  auto type = getType(anchor)->getRValueType();

  auto *tryExpr = dyn_cast<OptionalTryExpr>(unwrapped);
  if (!tryExpr)
    return diagnoseUnwrap(getTypeChecker(), getDC(), unwrapped, type);

  emitDiagnostic(tryExpr->getTryLoc(), diag::missing_unwrap_optional_try, type)
      .fixItReplace({tryExpr->getTryLoc(), tryExpr->getQuestionLoc()}, "try!");
  return true;
}
<commit_msg>Conflict resolution.<commit_after>//===--- CSDiagnostics.cpp - Constraint Diagnostics -----------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// This file implements diagnostics for constraint system.
//
//===----------------------------------------------------------------------===//

#include "ConstraintSystem.h"
#include "CSDiagnostics.h"
#include "MiscDiagnostics.h"
#include "swift/AST/Expr.h"
#include "swift/AST/Types.h"
#include "llvm/ADT/ArrayRef.h"

using namespace swift;
using namespace constraints;

FailureDiagnostic::~FailureDiagnostic() {}

std::pair<Expr *, bool> FailureDiagnostic::computeAnchor() const {
  auto &cs = getConstraintSystem();

  auto *locator = getLocator();
  // Resolve the locator to a specific expression.
  SourceRange range;
  bool isSubscriptMember =
      (!locator->getPath().empty() && locator->getPath().back().getKind() ==
                                          ConstraintLocator::SubscriptMember);

  ConstraintLocator *resolved = simplifyLocator(cs, locator, range);
  if (!resolved || !resolved->getAnchor())
    return {locator->getAnchor(), true};

  Expr *anchor = resolved->getAnchor();
  // FIXME: Work around an odd locator representation that doesn't separate the
  // base of a subscript member from the member access.
  if (isSubscriptMember) {
    if (auto subscript = dyn_cast<SubscriptExpr>(anchor))
      anchor = subscript->getBase();
  }

  return {anchor, !resolved->getPath().empty()};
}

Type FailureDiagnostic::getType(Expr *expr) const {
  auto &cs = getConstraintSystem();
  return solution.simplifyType(cs.getType(expr));
}

template <typename... ArgTypes>
InFlightDiagnostic
FailureDiagnostic::emitDiagnostic(ArgTypes &&... Args) const {
  auto &cs = getConstraintSystem();
  return cs.TC.diagnose(std::forward<ArgTypes>(Args)...);
}

Type RequirementFailure::getOwnerType() const {
  return getType(getAnchor())->getRValueInstanceType();
}

const Requirement &RequirementFailure::getRequirement() {
  auto *genericCtx = AffectedDecl->getAsGenericContext();
  return genericCtx->getGenericRequirements()[getRequirementIndex()];
}

ValueDecl *RequirementFailure::getDeclRef() const {
  auto &cs = getConstraintSystem();

  auto *anchor = getAnchor();
  auto *locator = cs.getConstraintLocator(anchor);
  if (auto *AE = dyn_cast<CallExpr>(anchor)) {
    assert(isa<TypeExpr>(AE->getFn()));
    ConstraintLocatorBuilder ctor(locator);
    locator = cs.getConstraintLocator(
        ctor.withPathElement(PathEltKind::ApplyFunction)
            .withPathElement(PathEltKind::ConstructorMember));
  } else if (auto *UDE = dyn_cast<UnresolvedDotExpr>(anchor)) {
    ConstraintLocatorBuilder member(locator);
    locator =
        cs.getConstraintLocator(member.withPathElement(PathEltKind::Member));
  }

  auto overload = getOverloadChoiceIfAvailable(locator);
  if (overload)
    return overload->choice.getDecl();

  auto ownerType = getOwnerType();
  if (auto *NA = dyn_cast<NameAliasType>(ownerType.getPointer()))
    return NA->getDecl();

  return ownerType->getAnyGeneric();
}

bool MissingConformanceFailure::diagnose() {
  auto *anchor = getAnchor();
  auto ownerType = getOwnerType();
  auto type = getNonConformingType();
  auto protocolType = getProtocolType();

  //  Find `ApplyExpr` based on a function expression attached to it.
  auto findApplyExpr = [](Expr *parent, Expr *fnExpr) -> ApplyExpr * {
    ApplyExpr *applyExpr = nullptr;
    parent->forEachChildExpr([&applyExpr, &fnExpr](Expr *subExpr) -> Expr * {
      auto *AE = dyn_cast<ApplyExpr>(subExpr);
      if (!AE || AE->getFn() != fnExpr)
        return subExpr;

      applyExpr = AE;
      return nullptr;
    });
    return applyExpr;
  };

  auto getArgumentAt = [](ApplyExpr *AE, unsigned index) -> Expr * {
    assert(AE);

    auto *arg = AE->getArg();
    if (auto *TE = dyn_cast<TupleExpr>(arg))
      return TE->getElement(index);

    assert(index == 0);
    if (auto *PE = dyn_cast<ParenExpr>(arg))
      return PE->getSubExpr();

    return arg;
  };

  auto *applyExpr = findApplyExpr(getParentExpr(), anchor);

  Optional<unsigned> atParameterPos;
  // Sometimes fix is recorded by type-checking sub-expression
  // during normal diagnostics, in such case call expression
  // is unavailable.
  if (applyExpr) {
    // If this is a static, initializer or operator call,
    // let's not try to diagnose it here, but refer to expression
    // diagnostics.
    if (isa<BinaryExpr>(applyExpr) || isa<TypeExpr>(anchor))
      return false;

    if (auto *fnType = ownerType->getAs<AnyFunctionType>()) {
      auto parameters = fnType->getParams();
      for (auto index : indices(parameters)) {
        if (parameters[index].getType()->isEqual(type)) {
          atParameterPos = index;
          break;
        }
      }
    }
  }

  if (type->isExistentialType()) {
    auto diagnostic = diag::protocol_does_not_conform_objc;
    if (type->isObjCExistentialType())
      diagnostic = diag::protocol_does_not_conform_static;

    emitDiagnostic(anchor->getLoc(), diagnostic, type, protocolType);
  } else if (atParameterPos) {
    // Requirement comes from one of the parameter types,
    // let's try to point diagnostic to the argument expression.
    auto *argExpr = getArgumentAt(applyExpr, *atParameterPos);
    emitDiagnostic(argExpr->getLoc(),
                   diag::cannot_convert_argument_value_protocol, type,
                   protocolType);
  } else {
    const auto &req = getRequirement();
    auto *genericCtx = AffectedDecl->getAsGenericContext();

    std::function<const DeclContext *(Type)> getAffectedCtx =
        [&](Type type) -> const DeclContext * {
      if (auto *DMT = type->getAs<DependentMemberType>())
        return getAffectedCtx(DMT->getBase());

      if (auto *GPT = type->getAs<GenericTypeParamType>())
        return GPT->getDecl()->getDeclContext();

      return genericCtx;
    };

    const auto *affected = getAffectedCtx(req.getFirstType());
    if (affected != genericCtx) {
      auto *NTD = affected->getAsNominalTypeOrNominalTypeExtensionContext();
      emitDiagnostic(anchor->getLoc(), diag::type_does_not_conform_in_decl_ref,
                     AffectedDecl->getDescriptiveKind(),
                     AffectedDecl->getFullName(), NTD->getDeclaredType(), type,
                     protocolType);
    } else {
      emitDiagnostic(anchor->getLoc(), diag::type_does_not_conform_decl_owner,
                     AffectedDecl->getDescriptiveKind(),
                     AffectedDecl->getFullName(), type, protocolType);
    }

    emitDiagnostic(affected->getAsDeclOrDeclExtensionContext(),
                   diag::where_type_does_not_conform_type, req.getFirstType(),
                   type);
  }
  return true;
}

bool LabelingFailure::diagnose() {
  auto &cs = getConstraintSystem();
  auto *call = cast<CallExpr>(getAnchor());
  return diagnoseArgumentLabelError(cs.getASTContext(), call->getArg(),
                                    CorrectLabels,
                                    isa<SubscriptExpr>(call->getFn()));
}

bool NoEscapeFuncToTypeConversionFailure::diagnose() {
  auto *anchor = getAnchor();

  if (ConvertTo) {
    emitDiagnostic(anchor->getLoc(), diag::converting_noescape_to_type,
                   ConvertTo);
    return true;
  }

  auto path = getLocator()->getPath();
  if (path.empty())
    return false;

  auto &last = path.back();
  if (last.getKind() != ConstraintLocator::Archetype)
    return false;

  auto *archetype = last.getArchetype();
  emitDiagnostic(anchor->getLoc(), diag::converting_noescape_to_type,
                 archetype);
  return true;
}

bool MissingForcedDowncastFailure::diagnose() {
  if (hasComplexLocator())
    return false;

  auto &TC = getTypeChecker();

  auto *coerceExpr = dyn_cast<CoerceExpr>(getAnchor());
  if (!coerceExpr)
    return false;

  auto *subExpr = coerceExpr->getSubExpr();
  auto fromType = getType(subExpr)->getRValueType();
  auto toType = resolveType(coerceExpr->getCastTypeLoc().getType());

  auto castKind =
      TC.typeCheckCheckedCast(fromType, toType, CheckedCastContextKind::None,
                              getDC(), coerceExpr->getLoc(), subExpr,
                              coerceExpr->getCastTypeLoc().getSourceRange());

  switch (castKind) {
  // Invalid cast.
  case CheckedCastKind::Unresolved:
    // Fix didn't work, let diagnoseFailureForExpr handle this.
    return false;
  case CheckedCastKind::Coercion:
  case CheckedCastKind::BridgingCoercion:
    llvm_unreachable("Coercions handled in other disjunction branch");

  // Valid casts.
  case CheckedCastKind::ArrayDowncast:
  case CheckedCastKind::DictionaryDowncast:
  case CheckedCastKind::SetDowncast:
  case CheckedCastKind::ValueCast:
    emitDiagnostic(coerceExpr->getLoc(), diag::missing_forced_downcast,
                   fromType, toType)
        .highlight(coerceExpr->getSourceRange())
        .fixItReplace(coerceExpr->getLoc(), "as!");
    return true;
  }
}

bool MissingAddressOfFailure::diagnose() {
  if (hasComplexLocator())
    return false;

  auto *anchor = getAnchor();
  auto type = getType(anchor)->getRValueType();
  emitDiagnostic(anchor->getLoc(), diag::missing_address_of, type)
      .fixItInsert(anchor->getStartLoc(), "&");
  return true;
}

bool MissingExplicitConversionFailure::diagnose() {
  if (hasComplexLocator())
    return false;

  auto *DC = getDC();
  auto &TC = getTypeChecker();

  auto *anchor = getAnchor();
  if (auto *paren = dyn_cast<ParenExpr>(anchor))
    anchor = paren->getSubExpr();

  auto fromType = getType(anchor)->getRValueType();
  Type toType = resolveType(ConvertingTo);
  bool useAs = TC.isExplicitlyConvertibleTo(fromType, toType, DC);
  bool useAsBang = !useAs && TC.checkedCastMaySucceed(fromType, toType, DC);
  if (!useAs && !useAsBang)
    return false;

  auto *expr = getParentExpr();
  // If we're performing pattern matching,
  // "as" means something completely different...
  if (auto binOpExpr = dyn_cast<BinaryExpr>(expr)) {
    auto overloadedFn = dyn_cast<OverloadedDeclRefExpr>(binOpExpr->getFn());
    if (overloadedFn && !overloadedFn->getDecls().empty()) {
      ValueDecl *decl0 = overloadedFn->getDecls()[0];
      if (decl0->getBaseName() == decl0->getASTContext().Id_MatchOperator)
        return false;
    }
  }

  bool needsParensInside = exprNeedsParensBeforeAddingAs(anchor);
  bool needsParensOutside = exprNeedsParensAfterAddingAs(anchor, expr);

  llvm::SmallString<2> insertBefore;
  llvm::SmallString<32> insertAfter;
  if (needsParensOutside) {
    insertBefore += "(";
  }
  if (needsParensInside) {
    insertBefore += "(";
    insertAfter += ")";
  }
  insertAfter += useAs ? " as " : " as! ";
  insertAfter += toType->getWithoutParens()->getString();
  if (needsParensOutside)
    insertAfter += ")";

  auto diagID =
      useAs ? diag::missing_explicit_conversion : diag::missing_forced_downcast;
  auto diag = emitDiagnostic(anchor->getLoc(), diagID, fromType, toType);
  if (!insertBefore.empty()) {
    diag.fixItInsert(anchor->getStartLoc(), insertBefore);
  }
  diag.fixItInsertAfter(anchor->getEndLoc(), insertAfter);
  return true;
}

bool MemberAccessOnOptionalBaseFailure::diagnose() {
  if (hasComplexLocator())
    return false;

  auto *anchor = getAnchor();
  auto type = getType(anchor)->getRValueType();
  bool resultIsOptional = ResultTypeIsOptional;

  // If we've resolved the member overload to one that returns an optional
  // type, then the result of the expression is optional (and we want to offer
  // only a '?' fixit) even though the constraint system didn't need to add any
  // additional optionality.
  auto overload = getResolvedOverload(getLocator());
  if (overload && overload->ImpliedType->getOptionalObjectType())
    resultIsOptional = true;

  return diagnoseBaseUnwrapForMemberAccess(anchor, type, Member,
                                           resultIsOptional, SourceRange());
}

bool MissingOptionalUnwrapFailure::diagnose() {
  if (hasComplexLocator())
    return false;

  auto *anchor = getAnchor();
  auto *unwrapped = anchor->getValueProvidingExpr();
  auto type = getType(anchor)->getRValueType();

  auto *tryExpr = dyn_cast<OptionalTryExpr>(unwrapped);
  if (!tryExpr)
    return diagnoseUnwrap(getConstraintSystem(), unwrapped, type);

  emitDiagnostic(tryExpr->getTryLoc(), diag::missing_unwrap_optional_try, type)
      .fixItReplace({tryExpr->getTryLoc(), tryExpr->getQuestionLoc()}, "try!");
  return true;
}
<|endoftext|>


<commit_before>// cfiles, an analysis frontend for the Chemfiles library
// Copyright (C) Guillaume Fraux and contributors -- BSD license

#include <docopt/docopt.h>
#include <sstream>
#include <fstream>
#include <unordered_map>
#include <unordered_set>

#include <fmt/format.h>
#include <fmt/ostream.h>

#include "HBonds.hpp"
#include "Autocorrelation.hpp"
#include "Histogram.hpp"
#include "Errors.hpp"
#include "utils.hpp"
#include "warnings.hpp"

using namespace chemfiles;
constexpr double PI = 3.141592653589793238463;

static const char OPTIONS[] =
R"(Compute list of hydrogen bonds along a trajectory. Selections for the acceptor
and donor atoms can be specified using the chemfiles selection language. It is
possible to provide an alternative unit cell or topology for the trajectory file
if they are not defined in the trajectory format. Hydrogen bonds are defined as
electrostatic attraction between two polar groups: the donor group is a hydrogen
atom covalently bound to an electronegative atom (usually O, N, F) while the
acceptor group is another highly electronegative atom. The criteria used depend
on a maximum donor-acceptor distance and a maximum acceptor-donor-H angle.
Hydrogen bonds criteria can be specified.

For more information about chemfiles selection language, please see
http://chemfiles.org/chemfiles/latest/selections.html

Usage:
  cfiles hbonds [options] <trajectory>
  cfiles hbonds (-h | --help)

Examples:
  cfiles hbonds water.xyz --cell 15:15:25 --guess-bonds
  cfiles hbonds in.pdb --donors=="bonds: type(#1) == O and type(#2) == H"
  cfiles hbonds protein.pdb --acceptors=="atoms: type N" --angle 20.0

Options:
  -h --help                     show this help
  -o <file>, --output=<file>    write result to <file>. This default to the
                                trajectory file name with the `.hbonds.dat`
                                extension.
  --format=<format>             force the input file format to be <format>
  -t <path>, --topology=<path>  alternative topology file for the input
  --topology-format=<format>    use <format> as format for the topology file
  --guess-bonds                 guess the bonds in the input
  -c <cell>, --cell=<cell>      alternative unit cell. <cell> format is one of
                                <a:b:c:α:β:γ> or <a:b:c> or <a>. 'a', 'b' and
                                'c' are in angstroms, 'α', 'β', and 'γ' are in
                                degrees.
  --steps=<steps>               steps to use from the input. <steps> format
                                is <start>:<end>[:<stride>] with <start>, <end>
                                and <stride> optional. The used steps goes from
                                <start> to <end> (excluded) by steps of
                                <stride>. The default values are 0 for <start>,
                                the number of steps for <end> and 1 for
                                <stride>.
  --donors=<sel>                selection to use for the donors. This must be a
                                selection of size 2, with the hydrogen atom as
                                second atom. [default: bonds: type(#2) == H]
  --acceptors=<sel>             selection to use for the acceptors. This must
                                be a selection of size 1.
                                [default: atoms: type O or type N or type F]
  --distance=<distance>         distance criterion to use for the hydrogen bond
                                detection. <distance> is the donor-acceptor
                                maximum distance in angstroms. [default: 3.5]
  --angle=<angle>               angle criterion to use for the hydrogen bond
                                detection. <angle> is the acceptor-donor-hydrogen
                                maximum angle in degrees. [default: 30.0]
  --histogram=<output>          accumulate the hydrogen bond histogram as a
                                function of (r, theta) and output it to the
                                given <ouput> file.
  -p <n>, --points=<n>          number of points in the histogram [default: 200]
  --autocorrelation=<output>    compute the hydrogen bond existence
                                autocorrelation and output it to the given
                                <ouput> file. This can be used to retrieve the
                                lifetime of hydrogen bonds.
)";

struct hbond {
    size_t donor;
    size_t hydrogen;
    size_t acceptor;
};

bool operator==(const hbond& lhs, const hbond& rhs) {
    return (lhs.donor == rhs.donor && lhs.hydrogen == rhs.hydrogen && lhs.acceptor == rhs.acceptor);
}

inline void hash_combine(size_t& hash, size_t value) {
    hash ^= std::hash<size_t>()(value) + 0x9e3779b9 + (hash << 6) + (hash >> 2);
}

namespace std {
    template <> struct hash<hbond> {
        size_t operator()(const hbond& bond) const {
            size_t hash = 0;
            hash_combine(hash, bond.donor);
            hash_combine(hash, bond.hydrogen);
            hash_combine(hash, bond.acceptor);
            return hash;
        }
    };
}

static HBonds::Options parse_options(int argc, const char* argv[]) {
    auto options_str = command_header("hbonds", HBonds().description()) + "\n";
    options_str += "Laura Scalfi <laura.scalfi@ens.fr>\n";
    options_str += OPTIONS;
    auto args = docopt::docopt(options_str, {argv, argv + argc}, true, "");

    HBonds::Options options;
    options.trajectory = args.at("<trajectory>").asString();
    options.guess_bonds = args.at("--guess-bonds").asBool();

    options.acceptor_selection = args.at("--acceptors").asString();
    options.donor_selection = args.at("--donors").asString();

    options.distance = string2double(args.at("--distance").asString());
    options.angle = string2double(args.at("--angle").asString()) * PI / 180;
    options.npoints = string2long(args["--points"].asString());

    if (args.at("--output")) {
        options.outfile = args.at("--output").asString();
    } else {
        options.outfile = options.trajectory + ".hbonds.dat";
    }

    if (args.at("--autocorrelation")) {
        options.autocorr_output = args.at("--autocorrelation").asString();
        options.autocorrelation = true;
    } else {
        options.autocorrelation = false;
    }

    if (args.at("--histogram")) {
        options.histogram_output = args.at("--histogram").asString();
        options.histogram = true;
    } else {
        options.histogram = false;
    }

    if (args.at("--steps")) {
        options.steps = steps_range::parse(args.at("--steps").asString());
    }

    if (args.at("--format")) {
        options.format = args.at("--format").asString();
    }

    if (args.at("--topology")) {
        if (options.guess_bonds) {
            throw CFilesError("Can not use both '--topology' and '--guess-bonds'");
        }
        options.topology = args.at("--topology").asString();
    }

    if (args.at("--topology-format")) {
        if (options.topology == "") {
            throw CFilesError("Can not use '--topology-format' without a '--topology'");
        }
        options.topology_format = args.at("--topology-format").asString();
    }

    if (args.at("--cell")) {
        options.custom_cell = true;
        options.cell = parse_cell(args.at("--cell").asString());
    }

    return options;
}

std::string HBonds::description() const {
    return "compute hydrogen bonds using distance/angle criteria";
}

int HBonds::run(int argc, const char* argv[]) {
    auto options = parse_options(argc, argv);

    auto donors = Selection(options.donor_selection);
    if (donors.size() != 2) {
        throw CFilesError("Can not use a selection for donors with size that is not 2.");
    }

    auto acceptors = Selection(options.acceptor_selection);
    if (acceptors.size() != 1) {
        throw CFilesError("Can not use a selection for acceptors with size larger than 1.");
    }

    std::ofstream outfile(options.outfile, std::ios::out);
    if (!outfile.is_open()) {
        throw CFilesError("Could not open the '" + options.outfile + "' file.");
    }
    fmt::print(outfile, "# Hydrogen bonds in {}\n", options.trajectory);
    fmt::print(outfile, "# Between '{}' and '{}'\n", options.acceptor_selection, options.donor_selection);

    auto infile = Trajectory(options.trajectory, 'r', options.format);
    if (options.custom_cell) {
        infile.set_cell(options.cell);
    }

    if (options.topology != "") {
        infile.set_topology(options.topology, options.topology_format);
    }

    auto histogram = Histogram(options.npoints, 0, options.distance, options.npoints, 0, options.angle * 180 / PI);
    auto existing_bonds = std::unordered_map<hbond, std::vector<float>>();
    size_t used_steps = 0;
    for (auto step: options.steps) {
        if (step >= infile.nsteps()) {
            break;
        }
        auto frame = infile.read_step(step);
        if (options.guess_bonds) {
            frame.guess_bonds();
        }

        auto bonds = std::unordered_set<hbond>();
        auto matched = donors.evaluate(frame);
        if (matched.empty()) {
            warn("no atom matching the donnor selection at step " + std::to_string(step));
        }

        for (auto match: matched) {
            assert(match.size() == 2);

            size_t donor = match[0];
            size_t hydrogen = match[1];

            if (frame[hydrogen].type() != "H") {
                warn_once(
                    "the second atom in the donors selection might not be an "
                    "hydrogen (expected type H, got type " + frame[hydrogen].type() + ")"
                );
            }

            auto acceptors_list = acceptors.list(frame);
            if (acceptors_list.empty()) {
                warn("no atom matching the acceptor selection at step " + std::to_string(step));
            }

            for (auto acceptor: acceptors_list) {
                if (acceptor != donor && frame.topology()[acceptor].type() != "H") {
                    auto distance = frame.distance(acceptor, donor);
                    auto theta = frame.angle(acceptor, donor, hydrogen);
                    if (distance < options.distance && theta < options.angle) {
                        bonds.emplace(hbond{donor, hydrogen, acceptor});
                        if (options.histogram) {
                            histogram.insert(distance, theta * 180 / PI);
                        }
                    }
                }
            }
        }

        fmt::print(outfile, "# step n_bonds\n");
        fmt::print(outfile, "{} {}\n", step, bonds.size());
        fmt::print(outfile, "# Donnor Hydrogen Acceptor\n", step);
        for (auto& bond: bonds) {
            fmt::print(outfile, "{} {} {}\n", bond.donor, bond.hydrogen, bond.acceptor);
        }

        if (options.histogram) {
            auto max = *std::max_element(histogram.begin(), histogram.end());
            histogram.normalize([max](size_t, double value) {
                return value / max;
            });

            std::ofstream outhist(options.histogram_output, std::ios::out);
            if (!outhist.is_open()) {
                throw CFilesError("Could not open the '" + options.histogram_output + "' file.");
            }

            fmt::print(outhist, "# Hydrogen bonds density histogram in {}\n", options.trajectory);
            fmt::print(outhist, "# Between '{}' and '{}'\n", options.acceptor_selection, options.donor_selection);
            fmt::print(outhist, "# r theta density\n", options.acceptor_selection, options.donor_selection);

            for (size_t i = 0; i < histogram.first().nbins; i++){
                for (size_t j = 0; j < histogram.second().nbins; j++){
                    fmt::print(
                        outhist,
                        "{} {} {}\n",
                        histogram.first().coord(i),
                        histogram.second().coord(j),
                        histogram(i, j)
                    );
                }
            }
        }

        if (options.autocorrelation) {
            for (auto& bond: bonds) {
                auto it = existing_bonds.find(bond);
                if (it == existing_bonds.end()) {
                    // New bond. Insert it and pad with zeros
                    auto pair = existing_bonds.emplace(bond, std::vector<float>(used_steps, 0.0));
                    pair.first->second.push_back(1.0);
                } else {
                    // Already seen this bond, add a single 1
                    it->second.push_back(1.0);
                }
            }
            // Add 0 to all bonds we did not see in this frame
            for (auto& it: existing_bonds) {
                if (it.second.size() != used_steps + 1) {
                    it.second.push_back(0.0);
                }
            }
        }
        used_steps += 1;
    }

    if (options.autocorrelation && used_steps != 0) {
        // Compute the autocorrelation for all bonds and average them
        auto correlator = Autocorrelation(used_steps);
        for (auto&& it: std::move(existing_bonds)) {
            correlator.add_timeserie(std::move(it.second));
        }
        correlator.normalize();
        auto& correlation = correlator.get_result();

        std::ofstream outcorr(options.autocorr_output, std::ios::out);
        if (!outcorr.is_open()) {
            throw CFilesError("Could not open the '" + options.autocorr_output + "' file.");
        }
        fmt::print(outcorr, "# Auto correlation between H-bonds existence\n");
        fmt::print(outcorr, "# step value\n");

        auto norm = correlation[0];
        for (size_t i=0; i<correlation.size() / 2; i++) {
            fmt::print(outcorr, "{} {}\n", i * options.steps.stride(), correlation[i] / norm);
        }
    }

    return 0;
}
<commit_msg>Fix a typo in examples<commit_after>// cfiles, an analysis frontend for the Chemfiles library
// Copyright (C) Guillaume Fraux and contributors -- BSD license

#include <docopt/docopt.h>
#include <sstream>
#include <fstream>
#include <unordered_map>
#include <unordered_set>

#include <fmt/format.h>
#include <fmt/ostream.h>

#include "HBonds.hpp"
#include "Autocorrelation.hpp"
#include "Histogram.hpp"
#include "Errors.hpp"
#include "utils.hpp"
#include "warnings.hpp"

using namespace chemfiles;
constexpr double PI = 3.141592653589793238463;

static const char OPTIONS[] =
R"(Compute list of hydrogen bonds along a trajectory. Selections for the acceptor
and donor atoms can be specified using the chemfiles selection language. It is
possible to provide an alternative unit cell or topology for the trajectory file
if they are not defined in the trajectory format. Hydrogen bonds are defined as
electrostatic attraction between two polar groups: the donor group is a hydrogen
atom covalently bound to an electronegative atom (usually O, N, F) while the
acceptor group is another highly electronegative atom. The criteria used depend
on a maximum donor-acceptor distance and a maximum acceptor-donor-H angle.
Hydrogen bonds criteria can be specified.

For more information about chemfiles selection language, please see
http://chemfiles.org/chemfiles/latest/selections.html

Usage:
  cfiles hbonds [options] <trajectory>
  cfiles hbonds (-h | --help)

Examples:
  cfiles hbonds water.xyz --cell 15:15:25 --guess-bonds
  cfiles hbonds in.pdb --donors="bonds: type(#1) == O and type(#2) == H"
  cfiles hbonds protein.pdb --acceptors="atoms: type N" --angle 20.0

Options:
  -h --help                     show this help
  -o <file>, --output=<file>    write result to <file>. This default to the
                                trajectory file name with the `.hbonds.dat`
                                extension.
  --format=<format>             force the input file format to be <format>
  -t <path>, --topology=<path>  alternative topology file for the input
  --topology-format=<format>    use <format> as format for the topology file
  --guess-bonds                 guess the bonds in the input
  -c <cell>, --cell=<cell>      alternative unit cell. <cell> format is one of
                                <a:b:c:α:β:γ> or <a:b:c> or <a>. 'a', 'b' and
                                'c' are in angstroms, 'α', 'β', and 'γ' are in
                                degrees.
  --steps=<steps>               steps to use from the input. <steps> format
                                is <start>:<end>[:<stride>] with <start>, <end>
                                and <stride> optional. The used steps goes from
                                <start> to <end> (excluded) by steps of
                                <stride>. The default values are 0 for <start>,
                                the number of steps for <end> and 1 for
                                <stride>.
  --donors=<sel>                selection to use for the donors. This must be a
                                selection of size 2, with the hydrogen atom as
                                second atom. [default: bonds: type(#2) == H]
  --acceptors=<sel>             selection to use for the acceptors. This must
                                be a selection of size 1.
                                [default: atoms: type O or type N or type F]
  --distance=<distance>         distance criterion to use for the hydrogen bond
                                detection. <distance> is the donor-acceptor
                                maximum distance in angstroms. [default: 3.5]
  --angle=<angle>               angle criterion to use for the hydrogen bond
                                detection. <angle> is the acceptor-donor-hydrogen
                                maximum angle in degrees. [default: 30.0]
  --histogram=<output>          accumulate the hydrogen bond histogram as a
                                function of (r, theta) and output it to the
                                given <ouput> file.
  -p <n>, --points=<n>          number of points in the histogram [default: 200]
  --autocorrelation=<output>    compute the hydrogen bond existence
                                autocorrelation and output it to the given
                                <ouput> file. This can be used to retrieve the
                                lifetime of hydrogen bonds.
)";

struct hbond {
    size_t donor;
    size_t hydrogen;
    size_t acceptor;
};

bool operator==(const hbond& lhs, const hbond& rhs) {
    return (lhs.donor == rhs.donor && lhs.hydrogen == rhs.hydrogen && lhs.acceptor == rhs.acceptor);
}

inline void hash_combine(size_t& hash, size_t value) {
    hash ^= std::hash<size_t>()(value) + 0x9e3779b9 + (hash << 6) + (hash >> 2);
}

namespace std {
    template <> struct hash<hbond> {
        size_t operator()(const hbond& bond) const {
            size_t hash = 0;
            hash_combine(hash, bond.donor);
            hash_combine(hash, bond.hydrogen);
            hash_combine(hash, bond.acceptor);
            return hash;
        }
    };
}

static HBonds::Options parse_options(int argc, const char* argv[]) {
    auto options_str = command_header("hbonds", HBonds().description()) + "\n";
    options_str += "Laura Scalfi <laura.scalfi@ens.fr>\n";
    options_str += OPTIONS;
    auto args = docopt::docopt(options_str, {argv, argv + argc}, true, "");

    HBonds::Options options;
    options.trajectory = args.at("<trajectory>").asString();
    options.guess_bonds = args.at("--guess-bonds").asBool();

    options.acceptor_selection = args.at("--acceptors").asString();
    options.donor_selection = args.at("--donors").asString();

    options.distance = string2double(args.at("--distance").asString());
    options.angle = string2double(args.at("--angle").asString()) * PI / 180;
    options.npoints = string2long(args["--points"].asString());

    if (args.at("--output")) {
        options.outfile = args.at("--output").asString();
    } else {
        options.outfile = options.trajectory + ".hbonds.dat";
    }

    if (args.at("--autocorrelation")) {
        options.autocorr_output = args.at("--autocorrelation").asString();
        options.autocorrelation = true;
    } else {
        options.autocorrelation = false;
    }

    if (args.at("--histogram")) {
        options.histogram_output = args.at("--histogram").asString();
        options.histogram = true;
    } else {
        options.histogram = false;
    }

    if (args.at("--steps")) {
        options.steps = steps_range::parse(args.at("--steps").asString());
    }

    if (args.at("--format")) {
        options.format = args.at("--format").asString();
    }

    if (args.at("--topology")) {
        if (options.guess_bonds) {
            throw CFilesError("Can not use both '--topology' and '--guess-bonds'");
        }
        options.topology = args.at("--topology").asString();
    }

    if (args.at("--topology-format")) {
        if (options.topology == "") {
            throw CFilesError("Can not use '--topology-format' without a '--topology'");
        }
        options.topology_format = args.at("--topology-format").asString();
    }

    if (args.at("--cell")) {
        options.custom_cell = true;
        options.cell = parse_cell(args.at("--cell").asString());
    }

    return options;
}

std::string HBonds::description() const {
    return "compute hydrogen bonds using distance/angle criteria";
}

int HBonds::run(int argc, const char* argv[]) {
    auto options = parse_options(argc, argv);

    auto donors = Selection(options.donor_selection);
    if (donors.size() != 2) {
        throw CFilesError("Can not use a selection for donors with size that is not 2.");
    }

    auto acceptors = Selection(options.acceptor_selection);
    if (acceptors.size() != 1) {
        throw CFilesError("Can not use a selection for acceptors with size larger than 1.");
    }

    std::ofstream outfile(options.outfile, std::ios::out);
    if (!outfile.is_open()) {
        throw CFilesError("Could not open the '" + options.outfile + "' file.");
    }
    fmt::print(outfile, "# Hydrogen bonds in {}\n", options.trajectory);
    fmt::print(outfile, "# Between '{}' and '{}'\n", options.acceptor_selection, options.donor_selection);

    auto infile = Trajectory(options.trajectory, 'r', options.format);
    if (options.custom_cell) {
        infile.set_cell(options.cell);
    }

    if (options.topology != "") {
        infile.set_topology(options.topology, options.topology_format);
    }

    auto histogram = Histogram(options.npoints, 0, options.distance, options.npoints, 0, options.angle * 180 / PI);
    auto existing_bonds = std::unordered_map<hbond, std::vector<float>>();
    size_t used_steps = 0;
    for (auto step: options.steps) {
        if (step >= infile.nsteps()) {
            break;
        }
        auto frame = infile.read_step(step);
        if (options.guess_bonds) {
            frame.guess_bonds();
        }

        auto bonds = std::unordered_set<hbond>();
        auto matched = donors.evaluate(frame);
        if (matched.empty()) {
            warn("no atom matching the donnor selection at step " + std::to_string(step));
        }

        for (auto match: matched) {
            assert(match.size() == 2);

            size_t donor = match[0];
            size_t hydrogen = match[1];

            if (frame[hydrogen].type() != "H") {
                warn_once(
                    "the second atom in the donors selection might not be an "
                    "hydrogen (expected type H, got type " + frame[hydrogen].type() + ")"
                );
            }

            auto acceptors_list = acceptors.list(frame);
            if (acceptors_list.empty()) {
                warn("no atom matching the acceptor selection at step " + std::to_string(step));
            }

            for (auto acceptor: acceptors_list) {
                if (acceptor != donor && frame.topology()[acceptor].type() != "H") {
                    auto distance = frame.distance(acceptor, donor);
                    auto theta = frame.angle(acceptor, donor, hydrogen);
                    if (distance < options.distance && theta < options.angle) {
                        bonds.emplace(hbond{donor, hydrogen, acceptor});
                        if (options.histogram) {
                            histogram.insert(distance, theta * 180 / PI);
                        }
                    }
                }
            }
        }

        fmt::print(outfile, "# step n_bonds\n");
        fmt::print(outfile, "{} {}\n", step, bonds.size());
        fmt::print(outfile, "# Donnor Hydrogen Acceptor\n", step);
        for (auto& bond: bonds) {
            fmt::print(outfile, "{} {} {}\n", bond.donor, bond.hydrogen, bond.acceptor);
        }

        if (options.histogram) {
            auto max = *std::max_element(histogram.begin(), histogram.end());
            histogram.normalize([max](size_t, double value) {
                return value / max;
            });

            std::ofstream outhist(options.histogram_output, std::ios::out);
            if (!outhist.is_open()) {
                throw CFilesError("Could not open the '" + options.histogram_output + "' file.");
            }

            fmt::print(outhist, "# Hydrogen bonds density histogram in {}\n", options.trajectory);
            fmt::print(outhist, "# Between '{}' and '{}'\n", options.acceptor_selection, options.donor_selection);
            fmt::print(outhist, "# r theta density\n", options.acceptor_selection, options.donor_selection);

            for (size_t i = 0; i < histogram.first().nbins; i++){
                for (size_t j = 0; j < histogram.second().nbins; j++){
                    fmt::print(
                        outhist,
                        "{} {} {}\n",
                        histogram.first().coord(i),
                        histogram.second().coord(j),
                        histogram(i, j)
                    );
                }
            }
        }

        if (options.autocorrelation) {
            for (auto& bond: bonds) {
                auto it = existing_bonds.find(bond);
                if (it == existing_bonds.end()) {
                    // New bond. Insert it and pad with zeros
                    auto pair = existing_bonds.emplace(bond, std::vector<float>(used_steps, 0.0));
                    pair.first->second.push_back(1.0);
                } else {
                    // Already seen this bond, add a single 1
                    it->second.push_back(1.0);
                }
            }
            // Add 0 to all bonds we did not see in this frame
            for (auto& it: existing_bonds) {
                if (it.second.size() != used_steps + 1) {
                    it.second.push_back(0.0);
                }
            }
        }
        used_steps += 1;
    }

    if (options.autocorrelation && used_steps != 0) {
        // Compute the autocorrelation for all bonds and average them
        auto correlator = Autocorrelation(used_steps);
        for (auto&& it: std::move(existing_bonds)) {
            correlator.add_timeserie(std::move(it.second));
        }
        correlator.normalize();
        auto& correlation = correlator.get_result();

        std::ofstream outcorr(options.autocorr_output, std::ios::out);
        if (!outcorr.is_open()) {
            throw CFilesError("Could not open the '" + options.autocorr_output + "' file.");
        }
        fmt::print(outcorr, "# Auto correlation between H-bonds existence\n");
        fmt::print(outcorr, "# step value\n");

        auto norm = correlation[0];
        for (size_t i=0; i<correlation.size() / 2; i++) {
            fmt::print(outcorr, "{} {}\n", i * options.steps.stride(), correlation[i] / norm);
        }
    }

    return 0;
}
<|endoftext|>


<commit_before>/* bzflag
 * Copyright (c) 1993 - 2005 Tim Riker
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named COPYING that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

/**
 * GameTime:
 *	Manages the network time.
 *      Time is stored as microseconds since the epoch.
 */

// the top dog
#include "common.h"

// interface header
#include "GameTime.h"

// system headers
#include <time.h>
#ifndef _WIN32
#  include <sys/time.h>
#endif
#include <list>

// common headers
#include "Pack.h"
#include "bzfio.h"

// type definitions
typedef uint16_t u16;
typedef uint32_t u32;
#ifndef WIN32
typedef int64_t s64;
#else
typedef __int64 s64;
#endif
typedef struct {
  s64 netTime;
  s64 localTime;
} TimeRecord;

// local constants
static const double filterTime = 10.0;
static const unsigned int maxRecords = 1024; // safety
static const unsigned int maxRecordAge = 120 * 1000000;
static const s64 maxTime = 2345678;
static const double minRate = 0.50;
static const double maxRate = 2.00;

// local variables
static std::list<TimeRecord> timeRecs;
static double stepSecs = 0.0;
static s64 stepTime = 0;
static double avgRate = 1.0;
static TimeRecord avgPoint = {0, 0};

/******************************************************************************/

static s64 getRawTime()
{
#ifndef _WIN32

  struct timeval tv;
  gettimeofday(&tv, NULL);
  return ((s64)tv.tv_sec * (s64)1000000) + (s64)tv.tv_usec;

#else //_WIN32

  // FIXME - use QPC if available? (10ms[pat] good enough?)
  //       - during rollovers, check time() against the
  //	 current value to see if a rollover was missed?

  static s64 offset = ((s64)time(NULL) * (s64)1000000) -
                      ((s64)timeGetTime() * (s64)1000);
  static u32 lasttime = (u32)timeGetTime();

  u32 nowtime = (u32)timeGetTime();

  // we've got 49.71 days to catch the rollovers
  if (nowtime < lasttime) {
    // add the rollover value
    offset += ((s64)(1 << 32));
  }
  lasttime = nowtime;
  return offset + ((s64)nowtime * (s64)1000);

#endif //_WIN32
}

/******************************************************************************/

static void calcAvgRate()
{
  // FIXME - this is weak
  const int count = timeRecs.size();
  if (count <= 0) {
    avgRate = 1.0;
    avgPoint.netTime = 0;
    avgPoint.localTime = 0;
    return;
  }
  else if (timeRecs.size() == 1) {
    const TimeRecord& tr = *timeRecs.begin();
    avgRate = 1.0;
    avgPoint = tr;
    return;
  }
  else {
    const TimeRecord& last = *timeRecs.begin();
    const TimeRecord& first = *timeRecs.rbegin();
    const s64 netDiff = last.netTime - first.netTime;
    const s64 locDiff = last.localTime - first.localTime;
    if (locDiff != 0.0) {
      avgRate = ((double)netDiff / (double)locDiff);
      avgPoint = last;
    } else {
      // don't update
    }
  }
  return;
}

/******************************************************************************/

void GameTime::reset()
{
  stepSecs = 0.0;
  stepTime = 0;
  avgRate = 1.0;
  avgPoint.netTime = 0;
  avgPoint.localTime = 0;
  timeRecs.clear();
  return;
}

static void resetToRecord(const TimeRecord& record)
{
  avgRate = 1.0;
  avgPoint = record;
  stepTime = record.netTime;
  TimeRecord copy = record;
  timeRecs.clear();
  timeRecs.push_front(copy);
  return;
}

void GameTime::update()
{
  std::list<TimeRecord>::iterator it;
  unsigned int count = timeRecs.size();
  if (count <= 0) {
    const TimeRecord tr = {0,0};
    resetToRecord(tr);
  }
  else if (count == 1) {
    const TimeRecord& tr = *timeRecs.begin();
    resetToRecord(tr);
  }
  else {
    calcAvgRate();
    const TimeRecord& tr = *timeRecs.begin();
    const s64 diffTime = stepTime - tr.netTime;
    if ((llabs(diffTime) > maxTime) ||
        (avgRate < minRate) || (avgRate > maxRate)) {
      DEBUG4("GameTime: discontinuity: usecs = %lli, rate = %f\n",
             diffTime, avgRate);
      resetToRecord(tr);
    }
  }

  DEBUG4("GameTime: count = %i, rate = %f\n", timeRecs.size(), avgRate);

  return;
}

/******************************************************************************/

void GameTime::setStepTime()
{
  static s64 lastStep = 0;
  const s64 thisStep = getRawTime();
  if (timeRecs.size() <= 0) {
    stepTime = thisStep;
  } else {
    // long term prediction
    const double diffLocal = thisStep - avgPoint.localTime;
    const double longPred = (double)avgPoint.netTime + (diffLocal * avgRate);
    // short term prediction
    const double skipTime = (double)(thisStep - lastStep);
    const double shortPred = (double)stepTime + (skipTime * avgRate);
    // filtering
    const double c = (skipTime * 1.0e-6) / filterTime;
    const double a = (c > 0.0) && (c < 1.0) ? c : 0.5;
    const double b = 1.0 - a;
    stepTime = (s64)((a * longPred) + (b * (double)shortPred));
  }
  stepSecs = (double)stepTime * 1.0e-6;
  lastStep = thisStep;

  return;
}

double GameTime::getStepTime()
{
  return stepSecs;
}

/******************************************************************************/

int GameTime::packSize()
{
  return (2 * sizeof(u32));
}

void* GameTime::pack(void *buf)
{
  const s64 nowTime = getRawTime();
//  const s64 nowTime = getRawTime() + (s64)((bzfrand() - 0.5) * 2.0e6);
  buf = nboPackUInt(buf, (u32)(nowTime >> 32));		// msb's
  buf = nboPackUInt(buf, (u32)(nowTime & 0xFFFFFFFF));	// lsb's
  return buf;
}

void* GameTime::unpack(void *buf)
{
  u32 msb, lsb;
  buf = nboUnpackUInt(buf, msb);
  buf = nboUnpackUInt(buf, lsb);
  const s64 netTime = ((s64)msb << 32) + (s64)lsb;

  // store the value
  const TimeRecord tr = { netTime, getRawTime() };
  timeRecs.push_front(tr);

  // clear oversize entries
  while (timeRecs.size() > maxRecords) {
    timeRecs.pop_back();
  }

  // clear the aged entries
  if (timeRecs.size() > 0) {
    s64 nowTime = getRawTime();
    while (timeRecs.size() > 0) {
      TimeRecord back = *timeRecs.rbegin();
      if ((nowTime - back.localTime) < maxRecordAge) {
        break;
      }
      timeRecs.pop_back();
    }
  }

  return buf;
}

/******************************************************************************/

// Local Variables: ***
// mode: C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8
<commit_msg>no more llabs()<commit_after>/* bzflag
 * Copyright (c) 1993 - 2005 Tim Riker
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named COPYING that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

/**
 * GameTime:
 *	Manages the network time.
 *      Time is stored as microseconds since the epoch.
 */

// the top dog
#include "common.h"

// interface header
#include "GameTime.h"

// system headers
#include <time.h>
#ifndef _WIN32
#  include <sys/time.h>
#endif
#include <list>

// common headers
#include "Pack.h"
#include "bzfio.h"

// type definitions
typedef uint16_t u16;
typedef uint32_t u32;
#ifndef WIN32
typedef int64_t s64;
#else
typedef __int64 s64;
#endif
typedef struct {
  s64 netTime;
  s64 localTime;
} TimeRecord;

// local constants
static const double filterTime = 10.0;
static const unsigned int maxRecords = 1024; // safety
static const unsigned int maxRecordAge = 120 * 1000000;
static const s64 maxTime = 2345678;
static const double minRate = 0.50;
static const double maxRate = 2.00;

// local variables
static std::list<TimeRecord> timeRecs;
static double stepSecs = 0.0;
static s64 stepTime = 0;
static double avgRate = 1.0;
static TimeRecord avgPoint = {0, 0};

/******************************************************************************/

static s64 getRawTime()
{
#ifndef _WIN32

  struct timeval tv;
  gettimeofday(&tv, NULL);
  return ((s64)tv.tv_sec * (s64)1000000) + (s64)tv.tv_usec;

#else //_WIN32

  // FIXME - use QPC if available? (10ms[pat] good enough?)
  //       - during rollovers, check time() against the
  //	 current value to see if a rollover was missed?

  static s64 offset = ((s64)time(NULL) * (s64)1000000) -
                      ((s64)timeGetTime() * (s64)1000);
  static u32 lasttime = (u32)timeGetTime();

  u32 nowtime = (u32)timeGetTime();

  // we've got 49.71 days to catch the rollovers
  if (nowtime < lasttime) {
    // add the rollover value
    offset += ((s64)(1 << 32));
  }
  lasttime = nowtime;
  return offset + ((s64)nowtime * (s64)1000);

#endif //_WIN32
}

/******************************************************************************/

static void calcAvgRate()
{
  // FIXME - this is weak
  const int count = timeRecs.size();
  if (count <= 0) {
    avgRate = 1.0;
    avgPoint.netTime = 0;
    avgPoint.localTime = 0;
    return;
  }
  else if (timeRecs.size() == 1) {
    const TimeRecord& tr = *timeRecs.begin();
    avgRate = 1.0;
    avgPoint = tr;
    return;
  }
  else {
    const TimeRecord& last = *timeRecs.begin();
    const TimeRecord& first = *timeRecs.rbegin();
    const s64 netDiff = last.netTime - first.netTime;
    const s64 locDiff = last.localTime - first.localTime;
    if (locDiff != 0.0) {
      avgRate = ((double)netDiff / (double)locDiff);
      avgPoint = last;
    } else {
      // don't update
    }
  }
  return;
}

/******************************************************************************/

void GameTime::reset()
{
  stepSecs = 0.0;
  stepTime = 0;
  avgRate = 1.0;
  avgPoint.netTime = 0;
  avgPoint.localTime = 0;
  timeRecs.clear();
  return;
}

static void resetToRecord(const TimeRecord& record)
{
  avgRate = 1.0;
  avgPoint = record;
  stepTime = record.netTime;
  TimeRecord copy = record;
  timeRecs.clear();
  timeRecs.push_front(copy);
  return;
}

void GameTime::update()
{
  std::list<TimeRecord>::iterator it;
  unsigned int count = timeRecs.size();
  if (count <= 0) {
    const TimeRecord tr = {0,0};
    resetToRecord(tr);
  }
  else if (count == 1) {
    const TimeRecord& tr = *timeRecs.begin();
    resetToRecord(tr);
  }
  else {
    calcAvgRate();
    const TimeRecord& tr = *timeRecs.begin();
    const s64 diffTime = stepTime - tr.netTime;
    if ((diffTime < -maxTime) || (diffTime > +maxTime) ||
        (avgRate < minRate) || (avgRate > maxRate)) {
      DEBUG4("GameTime: discontinuity: usecs = %lli, rate = %f\n",
             diffTime, avgRate);
      resetToRecord(tr);
    }
  }

  DEBUG4("GameTime: count = %i, rate = %f\n", timeRecs.size(), avgRate);

  return;
}

/******************************************************************************/

void GameTime::setStepTime()
{
  static s64 lastStep = 0;
  const s64 thisStep = getRawTime();
  if (timeRecs.size() <= 0) {
    stepTime = thisStep;
  } else {
    // long term prediction
    const double diffLocal = thisStep - avgPoint.localTime;
    const double longPred = (double)avgPoint.netTime + (diffLocal * avgRate);
    // short term prediction
    const double skipTime = (double)(thisStep - lastStep);
    const double shortPred = (double)stepTime + (skipTime * avgRate);
    // filtering
    const double c = (skipTime * 1.0e-6) / filterTime;
    const double a = (c > 0.0) && (c < 1.0) ? c : 0.5;
    const double b = 1.0 - a;
    stepTime = (s64)((a * longPred) + (b * (double)shortPred));
  }
  stepSecs = (double)stepTime * 1.0e-6;
  lastStep = thisStep;

  return;
}

double GameTime::getStepTime()
{
  return stepSecs;
}

/******************************************************************************/

int GameTime::packSize()
{
  return (2 * sizeof(u32));
}

void* GameTime::pack(void *buf)
{
  const s64 nowTime = getRawTime();
//  const s64 nowTime = getRawTime() + (s64)((bzfrand() - 0.5) * 2.0e6);
  buf = nboPackUInt(buf, (u32)(nowTime >> 32));		// msb's
  buf = nboPackUInt(buf, (u32)(nowTime & 0xFFFFFFFF));	// lsb's
  return buf;
}

void* GameTime::unpack(void *buf)
{
  u32 msb, lsb;
  buf = nboUnpackUInt(buf, msb);
  buf = nboUnpackUInt(buf, lsb);
  const s64 netTime = ((s64)msb << 32) + (s64)lsb;

  // store the value
  const TimeRecord tr = { netTime, getRawTime() };
  timeRecs.push_front(tr);

  // clear oversize entries
  while (timeRecs.size() > maxRecords) {
    timeRecs.pop_back();
  }

  // clear the aged entries
  if (timeRecs.size() > 0) {
    s64 nowTime = getRawTime();
    while (timeRecs.size() > 0) {
      TimeRecord back = *timeRecs.rbegin();
      if ((nowTime - back.localTime) < maxRecordAge) {
        break;
      }
      timeRecs.pop_back();
    }
  }

  return buf;
}

/******************************************************************************/

// Local Variables: ***
// mode: C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8
<|endoftext|>