<commit_before>//== IdenticalExprChecker.cpp - Identical expression checker----------------==//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
///
/// \file
/// \brief This defines IdenticalExprChecker, a check that warns about
/// unintended use of identical expressions.
///
/// It checks for use of identical expressions with comparison operators.
///
//===----------------------------------------------------------------------===//

#include "ClangSACheckers.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/AST/RecursiveASTVisitor.h"

using namespace clang;
using namespace ento;

static bool isIdenticalExpr(const ASTContext &Ctx, const Expr *Expr1,
                            const Expr *Expr2);
//===----------------------------------------------------------------------===//
// FindIdenticalExprVisitor - Identify nodes using identical expressions.
//===----------------------------------------------------------------------===//

class FindIdenticalExprVisitor
    : public RecursiveASTVisitor<FindIdenticalExprVisitor> {
public:
  explicit FindIdenticalExprVisitor(BugReporter &B, AnalysisDeclContext *A)
      : BR(B), AC(A) {}
  // FindIdenticalExprVisitor only visits nodes
  // that are binary operators.
  bool VisitBinaryOperator(const BinaryOperator *B);

private:
  BugReporter &BR;
  AnalysisDeclContext *AC;
};

bool FindIdenticalExprVisitor::VisitBinaryOperator(const BinaryOperator *B) {
  BinaryOperator::Opcode Op = B->getOpcode();
  if (!BinaryOperator::isComparisonOp(Op))
    return true;
  //
  // Special case for floating-point representation.
  //
  // If expressions on both sides of comparison operator are of type float,
  // then for some comparison operators no warning shall be
  // reported even if the expressions are identical from a symbolic point of
  // view. Comparison between expressions, declared variables and literals
  // are treated differently.
  //
  // != and == between float literals that have the same value should NOT warn.
  // < > between float literals that have the same value SHOULD warn.
  //
  // != and == between the same float declaration should NOT warn.
  // < > between the same float declaration SHOULD warn.
  //
  // != and == between eq. expressions that evaluates into float
  //           should NOT warn.
  // < >       between eq. expressions that evaluates into float
  //           should NOT warn.
  //
  const Expr *LHS = B->getLHS()->IgnoreParenImpCasts();
  const Expr *RHS = B->getRHS()->IgnoreParenImpCasts();

  const DeclRefExpr *DeclRef1 = dyn_cast<DeclRefExpr>(LHS);
  const DeclRefExpr *DeclRef2 = dyn_cast<DeclRefExpr>(RHS);
  const FloatingLiteral *FloatLit1 = dyn_cast<FloatingLiteral>(LHS);
  const FloatingLiteral *FloatLit2 = dyn_cast<FloatingLiteral>(RHS);
  if ((DeclRef1) && (DeclRef2)) {
    if ((DeclRef1->getType()->hasFloatingRepresentation()) &&
        (DeclRef2->getType()->hasFloatingRepresentation())) {
      if (DeclRef1->getDecl() == DeclRef2->getDecl()) {
        if ((Op == BO_EQ) || (Op == BO_NE)) {
          return true;
        }
      }
    }
  } else if ((FloatLit1) && (FloatLit2)) {
    if (FloatLit1->getValue().bitwiseIsEqual(FloatLit2->getValue())) {
      if ((Op == BO_EQ) || (Op == BO_NE)) {
        return true;
      }
    }
  } else if (LHS->getType()->hasFloatingRepresentation()) {
    // If any side of comparison operator still has floating-point
    // representation, then it's an expression. Don't warn.
    // Here only LHS is checked since RHS will be implicit casted to float.
    return true;
  } else {
    // No special case with floating-point representation, report as usual.
  }

  if (isIdenticalExpr(AC->getASTContext(), B->getLHS(), B->getRHS())) {
    PathDiagnosticLocation ELoc =
        PathDiagnosticLocation::createOperatorLoc(B, BR.getSourceManager());
    StringRef Message;
    if (((Op == BO_EQ) || (Op == BO_LE) || (Op == BO_GE)))
      Message = "comparison of identical expressions always evaluates to true";
    else
      Message = "comparison of identical expressions always evaluates to false";
    BR.EmitBasicReport(AC->getDecl(), "Compare of identical expressions",
                       categories::LogicError, Message, ELoc);
  }
  // We want to visit ALL nodes (subexpressions of binary comparison
  // expressions too) that contains comparison operators.
  // True is always returned to traverse ALL nodes.
  return true;
}
/// \brief Determines whether two expression trees are identical regarding
/// operators and symbols.
///
/// Exceptions: expressions containing macros or functions with possible side
/// effects are never considered identical.
/// Limitations: (t + u) and (u + t) are not considered identical.
/// t*(u + t) and t*u + t*t are not considered identical.
///
static bool isIdenticalExpr(const ASTContext &Ctx, const Expr *Expr1,
                            const Expr *Expr2) {
  // If Expr1 & Expr2 are of different class then they are not
  // identical expression.
  if (Expr1->getStmtClass() != Expr2->getStmtClass())
    return false;
  // If Expr1 has side effects then don't warn even if expressions
  // are identical.
  if (Expr1->HasSideEffects(Ctx))
    return false;
  // Is expression is based on macro then don't warn even if
  // the expressions are identical.
  if ((Expr1->getExprLoc().isMacroID()) || (Expr2->getExprLoc().isMacroID()))
    return false;
  // If all children of two expressions are identical, return true.
  Expr::const_child_iterator I1 = Expr1->child_begin();
  Expr::const_child_iterator I2 = Expr2->child_begin();
  while (I1 != Expr1->child_end() && I2 != Expr2->child_end()) {
    const Expr *Child1 = dyn_cast<Expr>(*I1);
    const Expr *Child2 = dyn_cast<Expr>(*I2);
    if (!Child1 || !Child2 || !isIdenticalExpr(Ctx, Child1, Child2))
      return false;
    ++I1;
    ++I2;
  }
  // If there are different number of children in the expressions, return false.
  // (TODO: check if this is a redundant condition.)
  if (I1 != Expr1->child_end())
    return false;
  if (I2 != Expr2->child_end())
    return false;

  switch (Expr1->getStmtClass()) {
  default:
    return false;
  case Stmt::ArraySubscriptExprClass:
  case Stmt::CStyleCastExprClass:
  case Stmt::ImplicitCastExprClass:
  case Stmt::ParenExprClass:
    return true;
  case Stmt::BinaryOperatorClass: {
    const BinaryOperator *BinOp1 = dyn_cast<BinaryOperator>(Expr1);
    const BinaryOperator *BinOp2 = dyn_cast<BinaryOperator>(Expr2);
    return BinOp1->getOpcode() == BinOp2->getOpcode();
  }
  case Stmt::CharacterLiteralClass: {
    const CharacterLiteral *CharLit1 = dyn_cast<CharacterLiteral>(Expr1);
    const CharacterLiteral *CharLit2 = dyn_cast<CharacterLiteral>(Expr2);
    return CharLit1->getValue() == CharLit2->getValue();
  }
  case Stmt::DeclRefExprClass: {
    const DeclRefExpr *DeclRef1 = dyn_cast<DeclRefExpr>(Expr1);
    const DeclRefExpr *DeclRef2 = dyn_cast<DeclRefExpr>(Expr2);
    return DeclRef1->getDecl() == DeclRef2->getDecl();
  }
  case Stmt::IntegerLiteralClass: {
    const IntegerLiteral *IntLit1 = dyn_cast<IntegerLiteral>(Expr1);
    const IntegerLiteral *IntLit2 = dyn_cast<IntegerLiteral>(Expr2);
    return IntLit1->getValue() == IntLit2->getValue();
  }
  case Stmt::FloatingLiteralClass: {
    const FloatingLiteral *FloatLit1 = dyn_cast<FloatingLiteral>(Expr1);
    const FloatingLiteral *FloatLit2 = dyn_cast<FloatingLiteral>(Expr2);
    return FloatLit1->getValue().bitwiseIsEqual(FloatLit2->getValue());
  }
  case Stmt::MemberExprClass: {
    const MemberExpr *MemberExpr1 = dyn_cast<MemberExpr>(Expr1);
    const MemberExpr *MemberExpr2 = dyn_cast<MemberExpr>(Expr2);
    return MemberExpr1->getMemberDecl() == MemberExpr2->getMemberDecl();
  }
  case Stmt::UnaryOperatorClass: {
    const UnaryOperator *UnaryOp1 = dyn_cast<UnaryOperator>(Expr1);
    const UnaryOperator *UnaryOp2 = dyn_cast<UnaryOperator>(Expr2);
    if (UnaryOp1->getOpcode() != UnaryOp2->getOpcode())
      return false;
    return !UnaryOp1->isIncrementDecrementOp();
  }
  }
}

//===----------------------------------------------------------------------===//
// FindIdenticalExprChecker
//===----------------------------------------------------------------------===//

class FindIdenticalExprChecker : public Checker<check::ASTCodeBody> {
public:
  void checkASTCodeBody(const Decl *D, AnalysisManager &Mgr,
                        BugReporter &BR) const {
    FindIdenticalExprVisitor Visitor(BR, Mgr.getAnalysisDeclContext(D));
    Visitor.TraverseDecl(const_cast<Decl *>(D));
  }
};

void ento::registerIdenticalExprChecker(CheckerManager &Mgr) {
  Mgr.registerChecker<FindIdenticalExprChecker>();
}
<commit_msg>Move classes into anonymous namespaces.<commit_after>//== IdenticalExprChecker.cpp - Identical expression checker----------------==//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
///
/// \file
/// \brief This defines IdenticalExprChecker, a check that warns about
/// unintended use of identical expressions.
///
/// It checks for use of identical expressions with comparison operators.
///
//===----------------------------------------------------------------------===//

#include "ClangSACheckers.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/AST/RecursiveASTVisitor.h"

using namespace clang;
using namespace ento;

static bool isIdenticalExpr(const ASTContext &Ctx, const Expr *Expr1,
                            const Expr *Expr2);
//===----------------------------------------------------------------------===//
// FindIdenticalExprVisitor - Identify nodes using identical expressions.
//===----------------------------------------------------------------------===//

namespace {
class FindIdenticalExprVisitor
    : public RecursiveASTVisitor<FindIdenticalExprVisitor> {
public:
  explicit FindIdenticalExprVisitor(BugReporter &B, AnalysisDeclContext *A)
      : BR(B), AC(A) {}
  // FindIdenticalExprVisitor only visits nodes
  // that are binary operators.
  bool VisitBinaryOperator(const BinaryOperator *B);

private:
  BugReporter &BR;
  AnalysisDeclContext *AC;
};
} // end anonymous namespace

bool FindIdenticalExprVisitor::VisitBinaryOperator(const BinaryOperator *B) {
  BinaryOperator::Opcode Op = B->getOpcode();
  if (!BinaryOperator::isComparisonOp(Op))
    return true;
  //
  // Special case for floating-point representation.
  //
  // If expressions on both sides of comparison operator are of type float,
  // then for some comparison operators no warning shall be
  // reported even if the expressions are identical from a symbolic point of
  // view. Comparison between expressions, declared variables and literals
  // are treated differently.
  //
  // != and == between float literals that have the same value should NOT warn.
  // < > between float literals that have the same value SHOULD warn.
  //
  // != and == between the same float declaration should NOT warn.
  // < > between the same float declaration SHOULD warn.
  //
  // != and == between eq. expressions that evaluates into float
  //           should NOT warn.
  // < >       between eq. expressions that evaluates into float
  //           should NOT warn.
  //
  const Expr *LHS = B->getLHS()->IgnoreParenImpCasts();
  const Expr *RHS = B->getRHS()->IgnoreParenImpCasts();

  const DeclRefExpr *DeclRef1 = dyn_cast<DeclRefExpr>(LHS);
  const DeclRefExpr *DeclRef2 = dyn_cast<DeclRefExpr>(RHS);
  const FloatingLiteral *FloatLit1 = dyn_cast<FloatingLiteral>(LHS);
  const FloatingLiteral *FloatLit2 = dyn_cast<FloatingLiteral>(RHS);
  if ((DeclRef1) && (DeclRef2)) {
    if ((DeclRef1->getType()->hasFloatingRepresentation()) &&
        (DeclRef2->getType()->hasFloatingRepresentation())) {
      if (DeclRef1->getDecl() == DeclRef2->getDecl()) {
        if ((Op == BO_EQ) || (Op == BO_NE)) {
          return true;
        }
      }
    }
  } else if ((FloatLit1) && (FloatLit2)) {
    if (FloatLit1->getValue().bitwiseIsEqual(FloatLit2->getValue())) {
      if ((Op == BO_EQ) || (Op == BO_NE)) {
        return true;
      }
    }
  } else if (LHS->getType()->hasFloatingRepresentation()) {
    // If any side of comparison operator still has floating-point
    // representation, then it's an expression. Don't warn.
    // Here only LHS is checked since RHS will be implicit casted to float.
    return true;
  } else {
    // No special case with floating-point representation, report as usual.
  }

  if (isIdenticalExpr(AC->getASTContext(), B->getLHS(), B->getRHS())) {
    PathDiagnosticLocation ELoc =
        PathDiagnosticLocation::createOperatorLoc(B, BR.getSourceManager());
    StringRef Message;
    if (((Op == BO_EQ) || (Op == BO_LE) || (Op == BO_GE)))
      Message = "comparison of identical expressions always evaluates to true";
    else
      Message = "comparison of identical expressions always evaluates to false";
    BR.EmitBasicReport(AC->getDecl(), "Compare of identical expressions",
                       categories::LogicError, Message, ELoc);
  }
  // We want to visit ALL nodes (subexpressions of binary comparison
  // expressions too) that contains comparison operators.
  // True is always returned to traverse ALL nodes.
  return true;
}
/// \brief Determines whether two expression trees are identical regarding
/// operators and symbols.
///
/// Exceptions: expressions containing macros or functions with possible side
/// effects are never considered identical.
/// Limitations: (t + u) and (u + t) are not considered identical.
/// t*(u + t) and t*u + t*t are not considered identical.
///
static bool isIdenticalExpr(const ASTContext &Ctx, const Expr *Expr1,
                            const Expr *Expr2) {
  // If Expr1 & Expr2 are of different class then they are not
  // identical expression.
  if (Expr1->getStmtClass() != Expr2->getStmtClass())
    return false;
  // If Expr1 has side effects then don't warn even if expressions
  // are identical.
  if (Expr1->HasSideEffects(Ctx))
    return false;
  // Is expression is based on macro then don't warn even if
  // the expressions are identical.
  if ((Expr1->getExprLoc().isMacroID()) || (Expr2->getExprLoc().isMacroID()))
    return false;
  // If all children of two expressions are identical, return true.
  Expr::const_child_iterator I1 = Expr1->child_begin();
  Expr::const_child_iterator I2 = Expr2->child_begin();
  while (I1 != Expr1->child_end() && I2 != Expr2->child_end()) {
    const Expr *Child1 = dyn_cast<Expr>(*I1);
    const Expr *Child2 = dyn_cast<Expr>(*I2);
    if (!Child1 || !Child2 || !isIdenticalExpr(Ctx, Child1, Child2))
      return false;
    ++I1;
    ++I2;
  }
  // If there are different number of children in the expressions, return false.
  // (TODO: check if this is a redundant condition.)
  if (I1 != Expr1->child_end())
    return false;
  if (I2 != Expr2->child_end())
    return false;

  switch (Expr1->getStmtClass()) {
  default:
    return false;
  case Stmt::ArraySubscriptExprClass:
  case Stmt::CStyleCastExprClass:
  case Stmt::ImplicitCastExprClass:
  case Stmt::ParenExprClass:
    return true;
  case Stmt::BinaryOperatorClass: {
    const BinaryOperator *BinOp1 = dyn_cast<BinaryOperator>(Expr1);
    const BinaryOperator *BinOp2 = dyn_cast<BinaryOperator>(Expr2);
    return BinOp1->getOpcode() == BinOp2->getOpcode();
  }
  case Stmt::CharacterLiteralClass: {
    const CharacterLiteral *CharLit1 = dyn_cast<CharacterLiteral>(Expr1);
    const CharacterLiteral *CharLit2 = dyn_cast<CharacterLiteral>(Expr2);
    return CharLit1->getValue() == CharLit2->getValue();
  }
  case Stmt::DeclRefExprClass: {
    const DeclRefExpr *DeclRef1 = dyn_cast<DeclRefExpr>(Expr1);
    const DeclRefExpr *DeclRef2 = dyn_cast<DeclRefExpr>(Expr2);
    return DeclRef1->getDecl() == DeclRef2->getDecl();
  }
  case Stmt::IntegerLiteralClass: {
    const IntegerLiteral *IntLit1 = dyn_cast<IntegerLiteral>(Expr1);
    const IntegerLiteral *IntLit2 = dyn_cast<IntegerLiteral>(Expr2);
    return IntLit1->getValue() == IntLit2->getValue();
  }
  case Stmt::FloatingLiteralClass: {
    const FloatingLiteral *FloatLit1 = dyn_cast<FloatingLiteral>(Expr1);
    const FloatingLiteral *FloatLit2 = dyn_cast<FloatingLiteral>(Expr2);
    return FloatLit1->getValue().bitwiseIsEqual(FloatLit2->getValue());
  }
  case Stmt::MemberExprClass: {
    const MemberExpr *MemberExpr1 = dyn_cast<MemberExpr>(Expr1);
    const MemberExpr *MemberExpr2 = dyn_cast<MemberExpr>(Expr2);
    return MemberExpr1->getMemberDecl() == MemberExpr2->getMemberDecl();
  }
  case Stmt::UnaryOperatorClass: {
    const UnaryOperator *UnaryOp1 = dyn_cast<UnaryOperator>(Expr1);
    const UnaryOperator *UnaryOp2 = dyn_cast<UnaryOperator>(Expr2);
    if (UnaryOp1->getOpcode() != UnaryOp2->getOpcode())
      return false;
    return !UnaryOp1->isIncrementDecrementOp();
  }
  }
}

//===----------------------------------------------------------------------===//
// FindIdenticalExprChecker
//===----------------------------------------------------------------------===//

namespace {
class FindIdenticalExprChecker : public Checker<check::ASTCodeBody> {
public:
  void checkASTCodeBody(const Decl *D, AnalysisManager &Mgr,
                        BugReporter &BR) const {
    FindIdenticalExprVisitor Visitor(BR, Mgr.getAnalysisDeclContext(D));
    Visitor.TraverseDecl(const_cast<Decl *>(D));
  }
};
} // end anonymous namespace

void ento::registerIdenticalExprChecker(CheckerManager &Mgr) {
  Mgr.registerChecker<FindIdenticalExprChecker>();
}
<|endoftext|>


<commit_before>/*------------------------------------------------------------------------------

    Copyright (c) 2004 Media Development Loan Fund

    This file is part of the Campcaster project.
    http://campcaster.campware.org/
    To report bugs, send an e-mail to bugs@campware.org

    Campcaster is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    Campcaster is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with Campcaster; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

    Author   : $Author$
    Version  : $Revision$
    Location : $URL$

------------------------------------------------------------------------------*/

/* ============================================================ include files */

#ifdef HAVE_CONFIG_H
#include "configure.h"
#endif

#include <iostream>

#include "LiveSupport/Widgets/WidgetFactory.h"
#include "LiveSupport/Widgets/Colors.h"
#include "LiveSupport/Widgets/Button.h"

#include "LiveSupport/Widgets/DialogWindow.h"

using namespace LiveSupport::Widgets;

/* ===================================================  local data structures */

/* ================================================  local constants & macros */

/* ===============================================  local function prototypes */

/* =============================================================  module code */

/*------------------------------------------------------------------------------
 *  Constructor.
 *----------------------------------------------------------------------------*/
DialogWindow :: DialogWindow (Ptr<Glib::ustring>::Ref   message,
                              int                       buttonTypes,
                              Ptr<ResourceBundle>::Ref  bundle)
                                                                    throw ()
          : WhiteWindow("",
                        Colors::White,
                        WidgetFactory::getInstance()->getWhiteWindowCorners(),
                        WhiteWindow::isModal),
            LocalizedObject(bundle)
{
    Ptr<WidgetFactory>::Ref  widgetFactory = WidgetFactory::getInstance();

    Gtk::Label *        messageLabel = Gtk::manage(new Gtk::Label(*message,
                                                          Gtk::ALIGN_CENTER,
                                                          Gtk::ALIGN_CENTER ));
    messageLabel->set_justify(Gtk::JUSTIFY_CENTER);

    Gtk::Box *          messageBox = Gtk::manage(new Gtk::HBox);
    messageBox->pack_start(*messageLabel, true, false, 10);

    Gtk::ButtonBox *    buttonBox = Gtk::manage(new Gtk::HButtonBox(
                                                        Gtk::BUTTONBOX_END, 5));

    int     buttonCount = 0;
    try {
        if (buttonTypes & cancelButton) {
            Button *    button = Gtk::manage(widgetFactory->createButton(
                                    *getResourceUstring("cancelButtonLabel") ));
            button->signal_clicked().connect(sigc::mem_fun(*this,
                                    &DialogWindow::onCancelButtonClicked));
            buttonBox->pack_start(*button);
            ++buttonCount;
        }

        if (buttonTypes & noButton) {
            Button *    button = Gtk::manage(widgetFactory->createButton(
                                    *getResourceUstring("noButtonLabel") ));
            button->signal_clicked().connect(sigc::mem_fun(*this,
                                    &DialogWindow::onNoButtonClicked));
            buttonBox->pack_start(*button);
            ++buttonCount;
        }

        if (buttonTypes & yesButton) {
            Button *    button = Gtk::manage(widgetFactory->createButton(
                                    *getResourceUstring("yesButtonLabel") ));
            button->signal_clicked().connect(sigc::mem_fun(*this,
                                    &DialogWindow::onYesButtonClicked));
            buttonBox->pack_start(*button);
            ++buttonCount;
        }

        if (buttonTypes & okButton) {
            Button *    button = Gtk::manage(widgetFactory->createButton(
                                    *getResourceUstring("okButtonLabel") ));
            button->signal_clicked().connect(sigc::mem_fun(*this,
                                    &DialogWindow::onOkButtonClicked));
            buttonBox->pack_start(*button);
            ++buttonCount;
        }
    } catch (std::invalid_argument &e) {
        std::cerr << e.what() << std::endl;
        std::exit(1);
    }

    Gtk::Box *  bottomBox = Gtk::manage(new Gtk::HBox);
    bottomBox->pack_start(*buttonBox, true, true, 10);

    Gtk::Box *  layout = Gtk::manage(new Gtk::VBox);
    layout->pack_start(*messageBox, true, false, 5);
    layout->pack_start(*bottomBox, false, false, 0);

    set_default_size(100*buttonCount + 50, 120);
    property_window_position().set_value(Gtk::WIN_POS_CENTER);
    set_skip_taskbar_hint(true);    // do not show in the task bar

    add(*layout);
}

/*------------------------------------------------------------------------------
 *  Destructor.
 *----------------------------------------------------------------------------*/
DialogWindow :: ~DialogWindow (void)                                throw ()
{
}

/*------------------------------------------------------------------------------
 *  Event handler for the Cancel button clicked
 *----------------------------------------------------------------------------*/
void
DialogWindow :: onCancelButtonClicked(void)                         throw ()
{
    buttonClicked = cancelButton;
    hide();
}

/*------------------------------------------------------------------------------
 *  Event handler for the No button clicked.
 *----------------------------------------------------------------------------*/
void
DialogWindow :: onNoButtonClicked(void)                             throw ()
{
    buttonClicked = noButton;
    hide();
}

/*------------------------------------------------------------------------------
 *  Event handler for the Yes button clicked.
 *----------------------------------------------------------------------------*/
void
DialogWindow :: onYesButtonClicked(void)                            throw ()
{
    buttonClicked = yesButton;
    hide();
}

/*------------------------------------------------------------------------------
 *  Event handler for the OK button clicked.
 *----------------------------------------------------------------------------*/
void
DialogWindow :: onOkButtonClicked(void)                             throw ()
{
    buttonClicked = okButton;
    hide();
}

/*------------------------------------------------------------------------------
 *  Show the window and return the button clicked.
 *----------------------------------------------------------------------------*/
DialogWindow::ButtonType
DialogWindow :: run(void)                                           throw ()
{
    show_all();
    Gtk::Main::run(*this);
    return buttonClicked;
}

<commit_msg>fixing #1866<commit_after>/*------------------------------------------------------------------------------

    Copyright (c) 2004 Media Development Loan Fund

    This file is part of the Campcaster project.
    http://campcaster.campware.org/
    To report bugs, send an e-mail to bugs@campware.org

    Campcaster is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    Campcaster is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with Campcaster; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

    Author   : $Author$
    Version  : $Revision$
    Location : $URL$

------------------------------------------------------------------------------*/

/* ============================================================ include files */

#ifdef HAVE_CONFIG_H
#include "configure.h"
#endif

#include <iostream>

#include "LiveSupport/Widgets/WidgetFactory.h"
#include "LiveSupport/Widgets/Colors.h"
#include "LiveSupport/Widgets/Button.h"

#include "LiveSupport/Widgets/DialogWindow.h"

using namespace LiveSupport::Widgets;

/* ===================================================  local data structures */

/* ================================================  local constants & macros */

/* ===============================================  local function prototypes */

/* =============================================================  module code */

/*------------------------------------------------------------------------------
 *  Constructor.
 *----------------------------------------------------------------------------*/
DialogWindow :: DialogWindow (Ptr<Glib::ustring>::Ref   message,
                              int                       buttonTypes,
                              Ptr<ResourceBundle>::Ref  bundle)
                                                                    throw ()
          : WhiteWindow("",
                        Colors::White,
                        WidgetFactory::getInstance()->getWhiteWindowCorners(),
                        WhiteWindow::isModal),
            LocalizedObject(bundle)
{
    Ptr<WidgetFactory>::Ref  widgetFactory = WidgetFactory::getInstance();

    Gtk::Label *        messageLabel = Gtk::manage(new Gtk::Label(*message,
                                                          Gtk::ALIGN_CENTER,
                                                          Gtk::ALIGN_CENTER ));
    messageLabel->set_justify(Gtk::JUSTIFY_CENTER);

    Gtk::Box *          messageBox = Gtk::manage(new Gtk::HBox);
    messageBox->pack_start(*messageLabel, true, false, 10);

    Gtk::ButtonBox *    buttonBox = Gtk::manage(new Gtk::HButtonBox(
                                                        Gtk::BUTTONBOX_END, 5));

    int     buttonCount = 0;
    try {
        if (buttonTypes & cancelButton) {
            Button *    button = Gtk::manage(widgetFactory->createButton(
                                    *getResourceUstring("cancelButtonLabel") ));
            button->signal_clicked().connect(sigc::mem_fun(*this,
                                    &DialogWindow::onCancelButtonClicked));
            buttonBox->pack_start(*button);
            ++buttonCount;
        }

        if (buttonTypes & noButton) {
            Button *    button = Gtk::manage(widgetFactory->createButton(
                                    *getResourceUstring("noButtonLabel") ));
            button->signal_clicked().connect(sigc::mem_fun(*this,
                                    &DialogWindow::onNoButtonClicked));
            buttonBox->pack_start(*button);
            ++buttonCount;
        }

        if (buttonTypes & yesButton) {
            Button *    button = Gtk::manage(widgetFactory->createButton(
                                    *getResourceUstring("yesButtonLabel") ));
            button->signal_clicked().connect(sigc::mem_fun(*this,
                                    &DialogWindow::onYesButtonClicked));
            buttonBox->pack_start(*button);
            ++buttonCount;
        }

        if (buttonTypes & okButton) {
            Button *    button = Gtk::manage(widgetFactory->createButton(
                                    *getResourceUstring("okButtonLabel") ));
            button->signal_clicked().connect(sigc::mem_fun(*this,
                                    &DialogWindow::onOkButtonClicked));
            buttonBox->pack_start(*button);
            ++buttonCount;
        }
    } catch (std::invalid_argument &e) {
        std::cerr << e.what() << std::endl;
        std::exit(1);
    }

    Gtk::Box *  bottomBox = Gtk::manage(new Gtk::HBox);
    bottomBox->pack_start(*buttonBox, true, true, 10);

    Gtk::Box *  layout = Gtk::manage(new Gtk::VBox);
    layout->pack_start(*messageBox, true, false, 5);
    layout->pack_start(*bottomBox, false, false, 0);

    set_default_size(100*buttonCount + 50, 120);
    property_window_position().set_value(Gtk::WIN_POS_CENTER);
    set_skip_taskbar_hint(true);    // do not show in the task bar
    set_type_hint(Gdk::WINDOW_TYPE_HINT_DIALOG);
    set_keep_above(true);

    add(*layout);
}

/*------------------------------------------------------------------------------
 *  Destructor.
 *----------------------------------------------------------------------------*/
DialogWindow :: ~DialogWindow (void)                                throw ()
{
}

/*------------------------------------------------------------------------------
 *  Event handler for the Cancel button clicked
 *----------------------------------------------------------------------------*/
void
DialogWindow :: onCancelButtonClicked(void)                         throw ()
{
    buttonClicked = cancelButton;
    hide();
}

/*------------------------------------------------------------------------------
 *  Event handler for the No button clicked.
 *----------------------------------------------------------------------------*/
void
DialogWindow :: onNoButtonClicked(void)                             throw ()
{
    buttonClicked = noButton;
    hide();
}

/*------------------------------------------------------------------------------
 *  Event handler for the Yes button clicked.
 *----------------------------------------------------------------------------*/
void
DialogWindow :: onYesButtonClicked(void)                            throw ()
{
    buttonClicked = yesButton;
    hide();
}

/*------------------------------------------------------------------------------
 *  Event handler for the OK button clicked.
 *----------------------------------------------------------------------------*/
void
DialogWindow :: onOkButtonClicked(void)                             throw ()
{
    buttonClicked = okButton;
    hide();
}

/*------------------------------------------------------------------------------
 *  Show the window and return the button clicked.
 *----------------------------------------------------------------------------*/
DialogWindow::ButtonType
DialogWindow :: run(void)                                           throw ()
{
    show_all();
    Gtk::Main::run(*this);
    return buttonClicked;
}

<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  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.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: IBM Corporation
 *
 *  Copyright: 2008 by IBM Corporation
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/
/*************************************************************************
 * @file
 *  For LWP filter architecture prototype
 ************************************************************************/
/*************************************************************************
 * Change History
 Jan 2005           Created
 ************************************************************************/

#include <memory>

#include "clone.hxx"
#include "lwpcharborderoverride.hxx"
#include "lwpborderstuff.hxx"
#include "lwpmargins.hxx"

LwpCharacterBorderOverride::LwpCharacterBorderOverride() :
m_pBorderStuff(new LwpBorderStuff), m_pMargins(new LwpMargins)
{
}

LwpCharacterBorderOverride::LwpCharacterBorderOverride(LwpCharacterBorderOverride const& rOther)
    : LwpOverride(rOther)
    , m_pBorderStuff(0)
    , m_pMargins(0)
    , m_nAboveWidth(rOther.m_nAboveWidth)
    , m_nBelowWidth(rOther.m_nBelowWidth)
{
    std::auto_ptr<LwpBorderStuff> pBorderStuff(::clone(rOther.m_pBorderStuff));
    std::auto_ptr<LwpMargins> pMargins(::clone(rOther.m_pMargins));
    m_pBorderStuff = pBorderStuff.release();
    m_pMargins = pMargins.release();
}

LwpCharacterBorderOverride::~LwpCharacterBorderOverride()
{
    if (m_pBorderStuff)
    {
        delete m_pBorderStuff;
    }
    if (m_pMargins)
    {
        delete m_pMargins;
    }
}

LwpCharacterBorderOverride* LwpCharacterBorderOverride::clone() const
{
    return new LwpCharacterBorderOverride(*this);
}

void LwpCharacterBorderOverride::Read(LwpObjectStream* pStrm)
{
    if (pStrm->QuickReadBool())
    {
        ReadCommon(pStrm);
        m_pBorderStuff->Read(pStrm);
        m_pMargins->Read(pStrm);
        m_nAboveWidth = pStrm->QuickReaduInt32();
        m_nBelowWidth = pStrm->QuickReaduInt32();
    }

    pStrm->SkipExtra();
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>coverity#738688 Uninitialized scalar field<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  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.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: IBM Corporation
 *
 *  Copyright: 2008 by IBM Corporation
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/
/*************************************************************************
 * @file
 *  For LWP filter architecture prototype
 ************************************************************************/
/*************************************************************************
 * Change History
 Jan 2005           Created
 ************************************************************************/

#include <memory>

#include "clone.hxx"
#include "lwpcharborderoverride.hxx"
#include "lwpborderstuff.hxx"
#include "lwpmargins.hxx"

LwpCharacterBorderOverride::LwpCharacterBorderOverride()
    : m_pBorderStuff(new LwpBorderStuff)
    , m_pMargins(new LwpMargins)
    , m_nAboveWidth(0)
    , m_nBelowWidth(0)
{
}

LwpCharacterBorderOverride::LwpCharacterBorderOverride(LwpCharacterBorderOverride const& rOther)
    : LwpOverride(rOther)
    , m_pBorderStuff(0)
    , m_pMargins(0)
    , m_nAboveWidth(rOther.m_nAboveWidth)
    , m_nBelowWidth(rOther.m_nBelowWidth)
{
    std::auto_ptr<LwpBorderStuff> pBorderStuff(::clone(rOther.m_pBorderStuff));
    std::auto_ptr<LwpMargins> pMargins(::clone(rOther.m_pMargins));
    m_pBorderStuff = pBorderStuff.release();
    m_pMargins = pMargins.release();
}

LwpCharacterBorderOverride::~LwpCharacterBorderOverride()
{
    if (m_pBorderStuff)
    {
        delete m_pBorderStuff;
    }
    if (m_pMargins)
    {
        delete m_pMargins;
    }
}

LwpCharacterBorderOverride* LwpCharacterBorderOverride::clone() const
{
    return new LwpCharacterBorderOverride(*this);
}

void LwpCharacterBorderOverride::Read(LwpObjectStream* pStrm)
{
    if (pStrm->QuickReadBool())
    {
        ReadCommon(pStrm);
        m_pBorderStuff->Read(pStrm);
        m_pMargins->Read(pStrm);
        m_nAboveWidth = pStrm->QuickReaduInt32();
        m_nBelowWidth = pStrm->QuickReaduInt32();
    }

    pStrm->SkipExtra();
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<|endoftext|>


<commit_before>#ifndef MJOLNIR_POTENTIAL_GLOBAL_EXCLUDED_VOLUME_POTENTIAL_HPP
#define MJOLNIR_POTENTIAL_GLOBAL_EXCLUDED_VOLUME_POTENTIAL_HPP
#include <mjolnir/core/ExclusionList.hpp>
#include <mjolnir/core/System.hpp>
#include <mjolnir/math/math.hpp>
#include <algorithm>
#include <numeric>
#include <memory>
#include <cmath>

namespace mjolnir
{

// excluded volume potential.
// This class contains radii of the particles and calculates energy and
// derivative of the potential function.
// This class is an implementation of the excluded volume term used in
// Clementi's off-lattice Go-like model (Clement et al., 2000) and AICG2+ model
// (Li et al., 2014)
template<typename realT>
class ExcludedVolumePotential
{
  public:

    using real_type            = realT;
    using parameter_type       = real_type;
    using container_type       = std::vector<parameter_type>;

    // `pair_parameter_type` is a parameter for a interacting pair.
    // Although it is the same type as `parameter_type` in this potential,
    // it can be different from normal parameter for each particle.
    // This enables NeighborList to cache a value to calculate forces between
    // the particles, e.g. by having (radius_i + radius_)/2 for a pair of {i, j}.
    using pair_parameter_type  = parameter_type;

    // topology stuff
    using topology_type        = Topology;
    using molecule_id_type     = typename topology_type::molecule_id_type;
    using group_id_type        = typename topology_type::group_id_type;
    using connection_kind_type = typename topology_type::connection_kind_type;
    using ignore_molecule_type = IgnoreMolecule<molecule_id_type>;
    using ignore_group_type    = IgnoreGroup   <group_id_type>;
    using exclusion_list_type  = ExclusionList;

    static constexpr real_type default_cutoff() noexcept
    {
        return real_type(2.0);
    }
    static constexpr parameter_type default_parameter() noexcept
    {
        return parameter_type{0.0};
    }

  public:

    ExcludedVolumePotential(const real_type eps,
        const std::vector<std::pair<std::size_t, parameter_type>>& parameters,
        const std::map<connection_kind_type, std::size_t>&         exclusions,
        ignore_molecule_type ignore_mol, ignore_group_type ignore_grp)
        : ExcludedVolumePotential(eps, default_cutoff(),
            parameters, exclusions, std::move(ignore_mol), std::move(ignore_grp))
    {}
    ExcludedVolumePotential(const real_type eps, const real_type cutoff_ratio,
        const std::vector<std::pair<std::size_t, parameter_type>>& parameters,
        const std::map<connection_kind_type, std::size_t>&         exclusions,
        ignore_molecule_type ignore_mol, ignore_group_type ignore_grp)
        : epsilon_(eps), cutoff_ratio_(cutoff_ratio),
          coef_at_cutoff_(std::pow(1.0 / cutoff_ratio, 12)),
          exclusion_list_(exclusions, std::move(ignore_mol), std::move(ignore_grp))
    {
        this->parameters_  .reserve(parameters.size());
        this->participants_.reserve(parameters.size());
        for(const auto& idxp : parameters)
        {
            const auto idx = idxp.first;
            this->participants_.push_back(idx);
            if(idx >= this->parameters_.size())
            {
                this->parameters_.resize(idx+1, default_parameter());
            }
            this->parameters_.at(idx) = idxp.second;
        }
    }
    ~ExcludedVolumePotential() = default;
    ExcludedVolumePotential(const ExcludedVolumePotential&) = default;
    ExcludedVolumePotential(ExcludedVolumePotential&&)      = default;
    ExcludedVolumePotential& operator=(const ExcludedVolumePotential&) = default;
    ExcludedVolumePotential& operator=(ExcludedVolumePotential&&)      = default;

    pair_parameter_type prepare_params(std::size_t i, std::size_t j) const noexcept
    {
        return this->parameters_[i] + this->parameters_[j];
    }

    // forwarding functions for clarity...
    real_type potential(const std::size_t i, const std::size_t j,
                        const real_type r) const noexcept
    {
        return this->potential(r, this->prepare_params(i, j));
    }
    real_type derivative(const std::size_t i, const std::size_t j,
                         const real_type r) const noexcept
    {
        return this->derivative(r, this->prepare_params(i, j));
    }

    real_type potential(const real_type r, const pair_parameter_type& d) const noexcept
    {
        if(d * this->cutoff_ratio_ < r){return 0.0;}

        const real_type d_r  = d / r;
        const real_type dr3  = d_r * d_r * d_r;
        const real_type dr6  = dr3 * dr3;
        const real_type dr12 = dr6 * dr6;
        return this->epsilon_ * (dr12 - this->coef_at_cutoff_);
    }
    real_type derivative(const real_type r, const pair_parameter_type& d) const noexcept
    {
        if(d * this->cutoff_ratio_ < r){return 0.0;}

        const real_type rinv = 1.0 / r;
        const real_type d_r  = d * rinv;
        const real_type dr3  = d_r * d_r * d_r;
        const real_type dr6  = dr3 * dr3;
        const real_type dr12 = dr6 * dr6;
        return -12.0 * this->epsilon_ * dr12 * rinv;
    }

    template<typename traitsT>
    void initialize(const System<traitsT>& sys) noexcept
    {
        MJOLNIR_GET_DEFAULT_LOGGER();
        MJOLNIR_LOG_FUNCTION();

        this->update(sys);
        return;
    }

    // nothing to be done if system parameter (e.g. temperature) changes
    template<typename traitsT>
    void update(const System<traitsT>& sys) noexcept
    {
        MJOLNIR_GET_DEFAULT_LOGGER();
        MJOLNIR_LOG_FUNCTION();

        // update exclusion list based on sys.topology()
        exclusion_list_.make(sys);
        return;
    }

    real_type cutoff_ratio()   const noexcept {return this->cutoff_ratio_;}
    real_type coef_at_cutoff() const noexcept {return this->coef_at_cutoff_;}

    real_type max_cutoff_length() const
    {
        const real_type max_sigma =
            *(std::max_element(parameters_.cbegin(), parameters_.cend()));
        return 2 * max_sigma * this->cutoff_ratio_;
    }

    bool has_interaction(const std::size_t i, const std::size_t j) const noexcept
    {
        // if not excluded, the pair has interaction.
        return !exclusion_list_.is_excluded(i, j);
    }
    // for testing
    exclusion_list_type const& exclusion_list() const noexcept
    {
        return exclusion_list_;
    }

    // ------------------------------------------------------------------------
    // used by Observer.

    static const char* name() noexcept {return "ExcludedVolume";}

    // ------------------------------------------------------------------------
    // the following accessers would be used in tests.

    real_type& epsilon()       noexcept {return this->epsilon_;}
    real_type  epsilon() const noexcept {return this->epsilon_;}
    std::vector<real_type>&       parameters()       noexcept {return this->parameters_;}
    std::vector<real_type> const& parameters() const noexcept {return this->parameters_;}

    std::vector<std::size_t> const& participants() const noexcept {return participants_;}

  private:

    real_type epsilon_;
    real_type cutoff_ratio_;
    real_type coef_at_cutoff_;
    std::vector<parameter_type> parameters_;
    std::vector<std::size_t> participants_;

    exclusion_list_type  exclusion_list_;
};

#ifdef MJOLNIR_SEPARATE_BUILD
extern template class ExcludedVolumePotential<double>;
extern template class ExcludedVolumePotential<float>;
#endif// MJOLNIR_SEPARATE_BUILD

} // mjolnir
#endif /* MJOLNIR_EXCLUDED_VOLUME_POTENTIAL */
<commit_msg>add comment about coef_at_cutoff<commit_after>#ifndef MJOLNIR_POTENTIAL_GLOBAL_EXCLUDED_VOLUME_POTENTIAL_HPP
#define MJOLNIR_POTENTIAL_GLOBAL_EXCLUDED_VOLUME_POTENTIAL_HPP
#include <mjolnir/core/ExclusionList.hpp>
#include <mjolnir/core/System.hpp>
#include <mjolnir/math/math.hpp>
#include <algorithm>
#include <numeric>
#include <memory>
#include <cmath>

namespace mjolnir
{

// excluded volume potential.
// This class contains radii of the particles and calculates energy and
// derivative of the potential function.
// This class is an implementation of the excluded volume term used in
// Clementi's off-lattice Go-like model (Clement et al., 2000) and AICG2+ model
// (Li et al., 2014)
template<typename realT>
class ExcludedVolumePotential
{
  public:

    using real_type            = realT;
    using parameter_type       = real_type;
    using container_type       = std::vector<parameter_type>;

    // `pair_parameter_type` is a parameter for a interacting pair.
    // Although it is the same type as `parameter_type` in this potential,
    // it can be different from normal parameter for each particle.
    // This enables NeighborList to cache a value to calculate forces between
    // the particles, e.g. by having (radius_i + radius_)/2 for a pair of {i, j}.
    using pair_parameter_type  = parameter_type;

    // topology stuff
    using topology_type        = Topology;
    using molecule_id_type     = typename topology_type::molecule_id_type;
    using group_id_type        = typename topology_type::group_id_type;
    using connection_kind_type = typename topology_type::connection_kind_type;
    using ignore_molecule_type = IgnoreMolecule<molecule_id_type>;
    using ignore_group_type    = IgnoreGroup   <group_id_type>;
    using exclusion_list_type  = ExclusionList;

    static constexpr real_type default_cutoff() noexcept
    {
        return real_type(2.0);
    }
    static constexpr parameter_type default_parameter() noexcept
    {
        return parameter_type{0.0};
    }

  public:

    ExcludedVolumePotential(const real_type eps,
        const std::vector<std::pair<std::size_t, parameter_type>>& parameters,
        const std::map<connection_kind_type, std::size_t>&         exclusions,
        ignore_molecule_type ignore_mol, ignore_group_type ignore_grp)
        : ExcludedVolumePotential(eps, default_cutoff(),
            parameters, exclusions, std::move(ignore_mol), std::move(ignore_grp))
    {}
    ExcludedVolumePotential(const real_type eps, const real_type cutoff_ratio,
        const std::vector<std::pair<std::size_t, parameter_type>>& parameters,
        const std::map<connection_kind_type, std::size_t>&         exclusions,
        ignore_molecule_type ignore_mol, ignore_group_type ignore_grp)
        : epsilon_(eps), cutoff_ratio_(cutoff_ratio),
          coef_at_cutoff_(std::pow(1.0 / cutoff_ratio, 12)),
          exclusion_list_(exclusions, std::move(ignore_mol), std::move(ignore_grp))
    {
        this->parameters_  .reserve(parameters.size());
        this->participants_.reserve(parameters.size());
        for(const auto& idxp : parameters)
        {
            const auto idx = idxp.first;
            this->participants_.push_back(idx);
            if(idx >= this->parameters_.size())
            {
                this->parameters_.resize(idx+1, default_parameter());
            }
            this->parameters_.at(idx) = idxp.second;
        }
    }
    ~ExcludedVolumePotential() = default;
    ExcludedVolumePotential(const ExcludedVolumePotential&) = default;
    ExcludedVolumePotential(ExcludedVolumePotential&&)      = default;
    ExcludedVolumePotential& operator=(const ExcludedVolumePotential&) = default;
    ExcludedVolumePotential& operator=(ExcludedVolumePotential&&)      = default;

    pair_parameter_type prepare_params(std::size_t i, std::size_t j) const noexcept
    {
        return this->parameters_[i] + this->parameters_[j];
    }

    // forwarding functions for clarity...
    real_type potential(const std::size_t i, const std::size_t j,
                        const real_type r) const noexcept
    {
        return this->potential(r, this->prepare_params(i, j));
    }
    real_type derivative(const std::size_t i, const std::size_t j,
                         const real_type r) const noexcept
    {
        return this->derivative(r, this->prepare_params(i, j));
    }

    real_type potential(const real_type r, const pair_parameter_type& d) const noexcept
    {
        if(d * this->cutoff_ratio_ < r){return 0.0;}

        const real_type d_r  = d / r;
        const real_type dr3  = d_r * d_r * d_r;
        const real_type dr6  = dr3 * dr3;
        const real_type dr12 = dr6 * dr6;
        // correction by coef_at_cuttoff make energy 0 about the particle pair
        // who's distance is over the cutoff range.
        return this->epsilon_ * (dr12 - this->coef_at_cutoff_);
    }
    real_type derivative(const real_type r, const pair_parameter_type& d) const noexcept
    {
        if(d * this->cutoff_ratio_ < r){return 0.0;}

        const real_type rinv = 1.0 / r;
        const real_type d_r  = d * rinv;
        const real_type dr3  = d_r * d_r * d_r;
        const real_type dr6  = dr3 * dr3;
        const real_type dr12 = dr6 * dr6;
        return -12.0 * this->epsilon_ * dr12 * rinv;
    }

    template<typename traitsT>
    void initialize(const System<traitsT>& sys) noexcept
    {
        MJOLNIR_GET_DEFAULT_LOGGER();
        MJOLNIR_LOG_FUNCTION();

        this->update(sys);
        return;
    }

    // nothing to be done if system parameter (e.g. temperature) changes
    template<typename traitsT>
    void update(const System<traitsT>& sys) noexcept
    {
        MJOLNIR_GET_DEFAULT_LOGGER();
        MJOLNIR_LOG_FUNCTION();

        // update exclusion list based on sys.topology()
        exclusion_list_.make(sys);
        return;
    }

    real_type cutoff_ratio()   const noexcept {return this->cutoff_ratio_;}
    real_type coef_at_cutoff() const noexcept {return this->coef_at_cutoff_;}

    real_type max_cutoff_length() const
    {
        const real_type max_sigma =
            *(std::max_element(parameters_.cbegin(), parameters_.cend()));
        return 2 * max_sigma * this->cutoff_ratio_;
    }

    bool has_interaction(const std::size_t i, const std::size_t j) const noexcept
    {
        // if not excluded, the pair has interaction.
        return !exclusion_list_.is_excluded(i, j);
    }
    // for testing
    exclusion_list_type const& exclusion_list() const noexcept
    {
        return exclusion_list_;
    }

    // ------------------------------------------------------------------------
    // used by Observer.

    static const char* name() noexcept {return "ExcludedVolume";}

    // ------------------------------------------------------------------------
    // the following accessers would be used in tests.

    real_type& epsilon()       noexcept {return this->epsilon_;}
    real_type  epsilon() const noexcept {return this->epsilon_;}
    std::vector<real_type>&       parameters()       noexcept {return this->parameters_;}
    std::vector<real_type> const& parameters() const noexcept {return this->parameters_;}

    std::vector<std::size_t> const& participants() const noexcept {return participants_;}

  private:

    real_type epsilon_;
    real_type cutoff_ratio_;
    real_type coef_at_cutoff_;
    std::vector<parameter_type> parameters_;
    std::vector<std::size_t> participants_;

    exclusion_list_type  exclusion_list_;
};

#ifdef MJOLNIR_SEPARATE_BUILD
extern template class ExcludedVolumePotential<double>;
extern template class ExcludedVolumePotential<float>;
#endif// MJOLNIR_SEPARATE_BUILD

} // mjolnir
#endif /* MJOLNIR_EXCLUDED_VOLUME_POTENTIAL */
<|endoftext|>


<commit_before>/*M///////////////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2015, Youssef Kashef
// Copyright (c) 2015, ELM Library Project
// 3-clause BSD License
//
//M*/
#include "elm/layers/gradassignment.h"

//#include <boost/graph/adjacency_list.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>

#include "elm/core/debug_utils.h"

#include "elm/core/signal.h"
#include "elm/core/layerconfig.h"
#include "elm/layers/graphcompatibility.h"
#include "elm/layers/layerfactory.h"
#include "elm/ts/layer_assertions.h"

using namespace std;
using namespace boost;
using namespace cv;
using namespace elm;
//namespace bg=boost::graph;

namespace {

ELM_INSTANTIATE_LAYER_TYPED_TEST_CASE_P(GradAssignment);

const float BETA            = 0.5f;
const float BETA_MAX        = 10.f;
const float BETA_RATE       = 1.075f;
const int MAX_ITER_PER_BETA = 4;
const int MAX_ITER_SINKHORN = 30;

const string NAME_GRAPH_AB          = "G_ab";
const string NAME_GRAPH_IJ          = "g_ij";
const string NAME_COMPATIBILITY_MAT = "c";
const string NAME_M                 = "m";

class GradAssignmentInitTest : public ::testing::Test
{
protected:
    virtual void SetUp()
    {
        LayerConfig cfg;

        PTree p;
        p.put(GradAssignment::PARAM_BETA, BETA);
        p.put(GradAssignment::PARAM_BETA_MAX, BETA_MAX);
        p.put(GradAssignment::PARAM_BETA_RATE, BETA_RATE);
        p.put(GradAssignment::PARAM_MAX_ITER_PER_BETA, MAX_ITER_PER_BETA);
        p.put(GradAssignment::PARAM_MAX_ITER_SINKHORN, MAX_ITER_SINKHORN);

        cfg.Params(p);

        LayerIONames io;
        io.Input(GradAssignment::KEY_INPUT_GRAPH_AB, NAME_GRAPH_AB);
        io.Input(GradAssignment::KEY_INPUT_GRAPH_IJ, NAME_GRAPH_IJ);
        io.Input(GradAssignment::KEY_INPUT_MAT_COMPATIBILITY, NAME_COMPATIBILITY_MAT);

        io.Output(GradAssignment::KEY_OUTPUT_RESPONSE, NAME_M);

        to_ = LayerFactory::CreateShared("GradAssignment", cfg, io);
    }

    // members
    LayerFactory::LayerShared to_; ///< ptr to test object
};

TEST_F(GradAssignmentInitTest, Constructor_overloaded)
{
    LayerConfig cfg;

    PTree p;
    p.put(GradAssignment::PARAM_BETA, BETA);
    p.put(GradAssignment::PARAM_BETA_MAX, BETA_MAX);
    p.put(GradAssignment::PARAM_BETA_RATE, BETA_RATE);
    p.put(GradAssignment::PARAM_MAX_ITER_PER_BETA, MAX_ITER_PER_BETA);
    p.put(GradAssignment::PARAM_MAX_ITER_SINKHORN, MAX_ITER_SINKHORN);

    cfg.Params(p);

    EXPECT_NO_THROW(to_.reset(new GradAssignment(cfg)));
}

TEST_F(GradAssignmentInitTest, Reconfigure_invalid_beta)
{
    LayerConfig cfg;

    PTree p;
    p.put(GradAssignment::PARAM_BETA_MAX, BETA_MAX);
    p.put(GradAssignment::PARAM_BETA_RATE, BETA_RATE);
    p.put(GradAssignment::PARAM_MAX_ITER_PER_BETA, MAX_ITER_PER_BETA);
    p.put(GradAssignment::PARAM_MAX_ITER_SINKHORN, MAX_ITER_SINKHORN);

    p.put(GradAssignment::PARAM_BETA, 0.f);
    cfg.Params(p);
    EXPECT_THROW(to_.reset(new GradAssignment(cfg)), ExceptionValueError);

    p.put(GradAssignment::PARAM_BETA, -0.5f);
    cfg.Params(p);
    EXPECT_THROW(to_.reset(new GradAssignment(cfg)), ExceptionValueError);
}

TEST_F(GradAssignmentInitTest, Reconfigure_invalid_beta_rate)
{
    LayerConfig cfg;

    PTree p;
    p.put(GradAssignment::PARAM_BETA_MAX, BETA_MAX);
    p.put(GradAssignment::PARAM_BETA_RATE, BETA_RATE);
    p.put(GradAssignment::PARAM_MAX_ITER_PER_BETA, MAX_ITER_PER_BETA);
    p.put(GradAssignment::PARAM_MAX_ITER_SINKHORN, MAX_ITER_SINKHORN);

    p.put(GradAssignment::PARAM_BETA, 1.f);
    cfg.Params(p);
    EXPECT_THROW(to_.reset(new GradAssignment(cfg)), ExceptionValueError);

    p.put(GradAssignment::PARAM_BETA, 0.8f);
    cfg.Params(p);
    EXPECT_THROW(to_.reset(new GradAssignment(cfg)), ExceptionValueError);

    p.put(GradAssignment::PARAM_BETA, 0.f);
    cfg.Params(p);
    EXPECT_THROW(to_.reset(new GradAssignment(cfg)), ExceptionValueError);

    p.put(GradAssignment::PARAM_BETA, -10.f);
    cfg.Params(p);
    EXPECT_THROW(to_.reset(new GradAssignment(cfg)), ExceptionValueError);
}

class GradAssignmentTest : public GradAssignmentInitTest
{
protected:
    virtual void SetUp()
    {
        GradAssignmentInitTest::SetUp();

        {
            LayerConfig cfg;
            LayerIONames io;
            io.Input(GraphCompatibility::KEY_INPUT_GRAPH_AB, NAME_GRAPH_AB);
            io.Input(GraphCompatibility::KEY_INPUT_GRAPH_IJ, NAME_GRAPH_IJ);
            io.Output(GraphCompatibility::KEY_OUTPUT_RESPONSE, NAME_COMPATIBILITY_MAT);

            graph_compatibility_= LayerFactory::CreateShared("GraphCompatibility", cfg, io);
        }

        // initialize test graphs
        const int A=4;  ///< no. of nodes in G
        const int I=A;  ///< no. of nodes in g

        // generate random adjacency matrices
        g_ab_ = Mat1f(A, A);
        Mat1i tmp(A, A);

        int s = 1000;
        randu(tmp, 0, s);
        g_ab_ = tmp/static_cast<float>(s);

        // distance from node to itself is 0
        for(int r=0; r<g_ab_.rows; r++) {

            g_ab_(r, r) = 0.f;
        }
        // make symmetrical
        for(int r=0; r<g_ab_.rows; r++) {

            for(int c=0; c<g_ab_.rows; c++) {

                g_ab_(r, c) = g_ab_(c, r);
            }
        }

        g_ij_ = Mat1f(I, I);
        g_ij_ = g_ab_.clone();    // make them equal
        Mat1f noise(g_ij_.size());
        randn(noise, 0.f, 0.015f);
        g_ij_ += noise;
        g_ij_.setTo(0.f, g_ij_ < 0.f);
        g_ij_.setTo(1.f, g_ij_ > 1.f);

        for(int r=0; r<g_ij_.rows; r++) {

            g_ij_(r, r) = 0.f;
            for(int c=0; c<g_ij_.cols; c++) {

                g_ij_(r, c) = g_ij_(c, r);
            }
        }

        // add test graphs to signal
        sig_.Append(NAME_GRAPH_AB, g_ab_);
        sig_.Append(NAME_GRAPH_IJ, g_ij_);

        graph_compatibility_->Activate(sig_);
        graph_compatibility_->Response(sig_);
    }

    virtual void TearDown()
    {
        sig_.Clear();
    }

    LayerFactory::LayerShared graph_compatibility_;

    Mat1f g_ab_;                 ///< adj. matrix for test graph
    Mat1f g_ij_;                 ///< adj. matrix for test graph

    Signal sig_;
};

TEST_F(GradAssignmentTest, ActivateAndResponse)
{
    to_->Activate(sig_);
    to_->Response(sig_);

    Mat1f m = sig_.MostRecentMat1f(NAME_M);

    EXPECT_MAT_DIMS_EQ(m, Size2i(g_ab_.rows, g_ij_.rows)) << "Match matrix should be of size (A, I)";

    // check we have a dominante diagonal
    for(int r=0; r<m.rows; r++) {

        for(int c=0; c<m.cols; c++) {

            if(r!=c) {

                EXPECT_LT(m(r, c), m(r, r)) << "Values > diagonal at r=" << r << ", c=" << c;
            }
        }
    }
}

TEST_F(GradAssignmentTest, ActivateAndResponse_large_graphs)
{
    // initialize test graphs
    const int A=30;  ///< no. of nodes in G
    const int I=A;  ///< no. of nodes in g

    // generate random adjacency matrices
    g_ab_ = Mat1f(A, A);
    Mat1i tmp(A, A);
    int s = 1000;
    randu(tmp, 0, s);
    g_ab_ = tmp/static_cast<float>(s);

    // distance from node to itself is 0
    for(int r=0; r<g_ab_.rows; r++) {

        g_ab_(r, r) = 0.f;
    }
    // make symmetrical
    for(int r=0; r<g_ab_.rows; r++) {

        for(int c=0; c<g_ab_.rows; c++) {

            g_ab_(r, c) = g_ab_(c, r);
        }
    }

    // remove edges, large graphs are not expected to be fully connected, leads to overflow anyway.
    const int NB_NULL = static_cast<int>(0.5*A*A);
    for(int i=0; i<NB_NULL; i++) {

        int r = abs(randu<int>()) % A;
        int c = abs(randu<int>()) % A;
        g_ab_(r, c) = g_ab_(c, r) = 0.f;
    }

    g_ij_ = Mat1f(I, I);
    g_ij_ = g_ab_.clone();    // make them equal
    Mat1f noise(g_ij_.size());
    randn(noise, 0.f, 0.01f);
    //g_ij_ += noise;
    g_ij_.setTo(0.f, g_ij_ < 0.f);
    g_ij_.setTo(1.f, g_ij_ > 1.f);

    for(int r=0; r<g_ij_.rows; r++) {

        g_ij_(r, r) = 0.f;
        for(int c=0; c<g_ij_.cols; c++) {

            g_ij_(r, c) = g_ij_(c, r);
        }
    }

    // add test graphs to signal
    sig_.Append(NAME_GRAPH_AB, g_ab_);
    sig_.Append(NAME_GRAPH_IJ, g_ij_);

    graph_compatibility_->Activate(sig_);
    graph_compatibility_->Response(sig_);

    to_->Activate(sig_);
    to_->Response(sig_);

    Mat1f m = sig_.MostRecentMat1f(NAME_M);

//    cout<<cv::format(m, cv::Formatter::FMT_NUMPY)<<std::endl;
//    cv::imshow("m/sum(m)", elm::ConvertTo8U(m/sum(m)[0]));
//    cv::waitKey();

    EXPECT_MAT_DIMS_EQ(m, Size2i(g_ab_.rows, g_ij_.rows)) << "Match matrix should be of size (A, I)";

    // check we have a dominante diagonal
    for(int r=0; r<m.rows; r++) {

        for(int c=0; c<m.cols; c++) {

            if(r!=c) {

                //EXPECT_LT(m(r, c), m(r, r)) << "Values > diagonal at r=" << r << ", c=" << c;
            }
        }
    }
}

TEST_F(GradAssignmentTest, Dims)
{
    for(int A=1; A<10; A++) {

        for(int I=1; I<10; I++) {

            // generate random adjacency matrices
            g_ab_ = Mat1f(A, A);
            Mat1i tmp(A, A);
            int stddev = 1000;
            randu(tmp, 0, stddev);
            g_ab_ = tmp/static_cast<float>(stddev);

            // distance from node to itself is 0
            for(int r=0; r<g_ab_.rows; r++) {

                g_ab_(r, r) = 0.f;
            }
            // make symmetrical
            for(int r=0; r<g_ab_.rows; r++) {

                for(int c=0; c<g_ab_.rows; c++) {

                    g_ab_(r, c) = g_ab_(c, r);
                }
            }

            g_ij_ = Mat1f(I, I);
            g_ij_ = g_ab_.clone();    // make them equal

            sig_.Clear();
            // add test graphs to signal
            sig_.Append(NAME_GRAPH_AB, g_ab_);
            sig_.Append(NAME_GRAPH_IJ, g_ij_);

            graph_compatibility_->Activate(sig_);
            graph_compatibility_->Response(sig_);

            to_->Activate(sig_);
            to_->Response(sig_);

            EXPECT_MAT_DIMS_EQ(sig_.MostRecentMat1f(NAME_M),
                               Size2i(g_ab_.rows, g_ij_.rows))
                    << "Match matrix should be of size (A, I)";
        }
    }
}

/**
 * @brief Test that incrasing noise leads to deteriorated matching matrix
 *
 * For multiple iterations:
 *
 *  Measure difference between diagonal and other match variables.
 *  Sum difference across rows
 *
 * Measure slope across iterations, and see diagonal dominance decreasing
 *
 */
TEST_F(GradAssignmentTest, MoreNoise)
{
    g_ij_ = g_ab_.clone();    // start with equal graphs

    const int N=5;
    std::vector<float> diag_sum_diff(N);

    for(int i=0; i<N; i++) {

        // add noisy test graphs to signal
        sig_.Append(NAME_GRAPH_IJ, g_ij_);

        graph_compatibility_->Activate(sig_);
        graph_compatibility_->Response(sig_);

        to_->Activate(sig_);
        to_->Response(sig_);

        Mat1f m = sig_.MostRecentMat1f(NAME_M);

        // get diagonal values
        Mat1f diag(m.rows, 1);
        for(int r=0; r<m.rows; r++) {

            diag(r) = m(r, r);
        }

        diag_sum_diff[i] = sum(repeat(diag, 1, m.cols)-m)[0];

        // add more noise to g_ij_ for next iteration
        Mat1f noise(g_ij_.size());
        randn(noise, 0.f, 0.05f);
        g_ij_ += noise;
        g_ij_.setTo(0.f, g_ij_ < 0.f);
        g_ij_.setTo(1.f, g_ij_ > 1.f);

        // keep symmetric
        for(int r=0; r<g_ij_.rows; r++) {

            g_ij_(r, r) = 0.f;
            for(int c=0; c<g_ij_.cols; c++) {

                g_ij_(r, c) = g_ij_(c, r);
            }
        }
    }

    Mat _mean, _stddev;

    // Calculate mean slope to dermine if diagonals dominate less with noise.
    Mat1f deriv1;
    Sobel(diag_sum_diff, deriv1, CV_32F, 1, 0, 3);
    meanStdDev(deriv1, _mean, _stddev);

    EXPECT_LT(_mean.at<double>(), 0.) << "Diagonal dominance not decreasing with added noise." << Mat1f(diag_sum_diff).t();
}

} // annonymous namespace for test cases and fixtures

<commit_msg>add test coverage around Gradassigment stimulus dimension validation<commit_after>/*M///////////////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2015, Youssef Kashef
// Copyright (c) 2015, ELM Library Project
// 3-clause BSD License
//
//M*/
#include "elm/layers/gradassignment.h"

//#include <boost/graph/adjacency_list.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>

#include "elm/core/debug_utils.h"

#include "elm/core/signal.h"
#include "elm/core/layerconfig.h"
#include "elm/layers/graphcompatibility.h"
#include "elm/layers/layerfactory.h"
#include "elm/ts/layer_assertions.h"

using namespace std;
using namespace boost;
using namespace cv;
using namespace elm;
//namespace bg=boost::graph;

namespace {

ELM_INSTANTIATE_LAYER_TYPED_TEST_CASE_P(GradAssignment);

const float BETA            = 0.5f;
const float BETA_MAX        = 10.f;
const float BETA_RATE       = 1.075f;
const int MAX_ITER_PER_BETA = 4;
const int MAX_ITER_SINKHORN = 30;

const string NAME_GRAPH_AB          = "G_ab";
const string NAME_GRAPH_IJ          = "g_ij";
const string NAME_COMPATIBILITY_MAT = "c";
const string NAME_M                 = "m";

class GradAssignmentInitTest : public ::testing::Test
{
protected:
    virtual void SetUp()
    {
        LayerConfig cfg;

        PTree p;
        p.put(GradAssignment::PARAM_BETA, BETA);
        p.put(GradAssignment::PARAM_BETA_MAX, BETA_MAX);
        p.put(GradAssignment::PARAM_BETA_RATE, BETA_RATE);
        p.put(GradAssignment::PARAM_MAX_ITER_PER_BETA, MAX_ITER_PER_BETA);
        p.put(GradAssignment::PARAM_MAX_ITER_SINKHORN, MAX_ITER_SINKHORN);

        cfg.Params(p);

        LayerIONames io;
        io.Input(GradAssignment::KEY_INPUT_GRAPH_AB, NAME_GRAPH_AB);
        io.Input(GradAssignment::KEY_INPUT_GRAPH_IJ, NAME_GRAPH_IJ);
        io.Input(GradAssignment::KEY_INPUT_MAT_COMPATIBILITY, NAME_COMPATIBILITY_MAT);

        io.Output(GradAssignment::KEY_OUTPUT_RESPONSE, NAME_M);

        to_ = LayerFactory::CreateShared("GradAssignment", cfg, io);
    }

    // members
    LayerFactory::LayerShared to_; ///< ptr to test object
};

TEST_F(GradAssignmentInitTest, Constructor_overloaded)
{
    LayerConfig cfg;

    PTree p;
    p.put(GradAssignment::PARAM_BETA, BETA);
    p.put(GradAssignment::PARAM_BETA_MAX, BETA_MAX);
    p.put(GradAssignment::PARAM_BETA_RATE, BETA_RATE);
    p.put(GradAssignment::PARAM_MAX_ITER_PER_BETA, MAX_ITER_PER_BETA);
    p.put(GradAssignment::PARAM_MAX_ITER_SINKHORN, MAX_ITER_SINKHORN);

    cfg.Params(p);

    EXPECT_NO_THROW(to_.reset(new GradAssignment(cfg)));
}

TEST_F(GradAssignmentInitTest, Reconfigure_invalid_beta)
{
    LayerConfig cfg;

    PTree p;
    p.put(GradAssignment::PARAM_BETA_MAX, BETA_MAX);
    p.put(GradAssignment::PARAM_BETA_RATE, BETA_RATE);
    p.put(GradAssignment::PARAM_MAX_ITER_PER_BETA, MAX_ITER_PER_BETA);
    p.put(GradAssignment::PARAM_MAX_ITER_SINKHORN, MAX_ITER_SINKHORN);

    p.put(GradAssignment::PARAM_BETA, 0.f);
    cfg.Params(p);
    EXPECT_THROW(to_.reset(new GradAssignment(cfg)), ExceptionValueError);

    p.put(GradAssignment::PARAM_BETA, -0.5f);
    cfg.Params(p);
    EXPECT_THROW(to_.reset(new GradAssignment(cfg)), ExceptionValueError);
}

TEST_F(GradAssignmentInitTest, Reconfigure_invalid_beta_rate)
{
    LayerConfig cfg;

    PTree p;
    p.put(GradAssignment::PARAM_BETA_MAX, BETA_MAX);
    p.put(GradAssignment::PARAM_BETA_RATE, BETA_RATE);
    p.put(GradAssignment::PARAM_MAX_ITER_PER_BETA, MAX_ITER_PER_BETA);
    p.put(GradAssignment::PARAM_MAX_ITER_SINKHORN, MAX_ITER_SINKHORN);

    p.put(GradAssignment::PARAM_BETA, 1.f);
    cfg.Params(p);
    EXPECT_THROW(to_.reset(new GradAssignment(cfg)), ExceptionValueError);

    p.put(GradAssignment::PARAM_BETA, 0.8f);
    cfg.Params(p);
    EXPECT_THROW(to_.reset(new GradAssignment(cfg)), ExceptionValueError);

    p.put(GradAssignment::PARAM_BETA, 0.f);
    cfg.Params(p);
    EXPECT_THROW(to_.reset(new GradAssignment(cfg)), ExceptionValueError);

    p.put(GradAssignment::PARAM_BETA, -10.f);
    cfg.Params(p);
    EXPECT_THROW(to_.reset(new GradAssignment(cfg)), ExceptionValueError);
}

class GradAssignmentTest : public GradAssignmentInitTest
{
protected:
    virtual void SetUp()
    {
        GradAssignmentInitTest::SetUp();

        {
            LayerConfig cfg;
            LayerIONames io;
            io.Input(GraphCompatibility::KEY_INPUT_GRAPH_AB, NAME_GRAPH_AB);
            io.Input(GraphCompatibility::KEY_INPUT_GRAPH_IJ, NAME_GRAPH_IJ);
            io.Output(GraphCompatibility::KEY_OUTPUT_RESPONSE, NAME_COMPATIBILITY_MAT);

            graph_compatibility_= LayerFactory::CreateShared("GraphCompatibility", cfg, io);
        }

        // initialize test graphs
        const int A=4;  ///< no. of nodes in G
        const int I=A;  ///< no. of nodes in g

        // generate random adjacency matrices
        g_ab_ = Mat1f(A, A);
        Mat1i tmp(A, A);

        int s = 1000;
        randu(tmp, 0, s);
        g_ab_ = tmp/static_cast<float>(s);

        // distance from node to itself is 0
        for(int r=0; r<g_ab_.rows; r++) {

            g_ab_(r, r) = 0.f;
        }
        // make symmetrical
        for(int r=0; r<g_ab_.rows; r++) {

            for(int c=0; c<g_ab_.rows; c++) {

                g_ab_(r, c) = g_ab_(c, r);
            }
        }

        g_ij_ = Mat1f(I, I);
        g_ij_ = g_ab_.clone();    // make them equal
        Mat1f noise(g_ij_.size());
        randn(noise, 0.f, 0.015f);
        g_ij_ += noise;
        g_ij_.setTo(0.f, g_ij_ < 0.f);
        g_ij_.setTo(1.f, g_ij_ > 1.f);

        for(int r=0; r<g_ij_.rows; r++) {

            g_ij_(r, r) = 0.f;
            for(int c=0; c<g_ij_.cols; c++) {

                g_ij_(r, c) = g_ij_(c, r);
            }
        }

        // add test graphs to signal
        sig_.Append(NAME_GRAPH_AB, g_ab_);
        sig_.Append(NAME_GRAPH_IJ, g_ij_);

        graph_compatibility_->Activate(sig_);
        graph_compatibility_->Response(sig_);
    }

    virtual void TearDown()
    {
        sig_.Clear();
    }

    LayerFactory::LayerShared graph_compatibility_;

    Mat1f g_ab_;                 ///< adj. matrix for test graph
    Mat1f g_ij_;                 ///< adj. matrix for test graph

    Signal sig_;
};

TEST_F(GradAssignmentTest, Activate_invalid_non_square_adj_mat)
{
    g_ab_ = Mat1f::ones(11, 7) - Mat1f::eye(11, 7);
    g_ij_ = g_ab_.clone();

    sig_.Append(NAME_GRAPH_AB, g_ab_);
    sig_.Append(NAME_GRAPH_IJ, g_ij_);

    EXPECT_THROW(to_->Activate(sig_), ExceptionBadDims);
}

TEST_F(GradAssignmentTest, ActivateAndResponse)
{
    to_->Activate(sig_);
    to_->Response(sig_);

    Mat1f m = sig_.MostRecentMat1f(NAME_M);

    EXPECT_MAT_DIMS_EQ(m, Size2i(g_ab_.rows, g_ij_.rows)) << "Match matrix should be of size (A, I)";

    // check we have a dominante diagonal
    for(int r=0; r<m.rows; r++) {

        for(int c=0; c<m.cols; c++) {

            if(r!=c) {

                EXPECT_LT(m(r, c), m(r, r)) << "Values > diagonal at r=" << r << ", c=" << c;
            }
        }
    }
}

TEST_F(GradAssignmentTest, ActivateAndResponse_large_graphs)
{
    // initialize test graphs
    const int A=30;  ///< no. of nodes in G
    const int I=A;  ///< no. of nodes in g

    // generate random adjacency matrices
    g_ab_ = Mat1f(A, A);
    Mat1i tmp(A, A);
    int s = 1000;
    randu(tmp, 0, s);
    g_ab_ = tmp/static_cast<float>(s);

    // distance from node to itself is 0
    for(int r=0; r<g_ab_.rows; r++) {

        g_ab_(r, r) = 0.f;
    }
    // make symmetrical
    for(int r=0; r<g_ab_.rows; r++) {

        for(int c=0; c<g_ab_.rows; c++) {

            g_ab_(r, c) = g_ab_(c, r);
        }
    }

    // remove edges, large graphs are not expected to be fully connected, leads to overflow anyway.
    const int NB_NULL = static_cast<int>(0.5*A*A);
    for(int i=0; i<NB_NULL; i++) {

        int r = abs(randu<int>()) % A;
        int c = abs(randu<int>()) % A;
        g_ab_(r, c) = g_ab_(c, r) = 0.f;
    }

    g_ij_ = Mat1f(I, I);
    g_ij_ = g_ab_.clone();    // make them equal
    Mat1f noise(g_ij_.size());
    randn(noise, 0.f, 0.01f);
    //g_ij_ += noise;
    g_ij_.setTo(0.f, g_ij_ < 0.f);
    g_ij_.setTo(1.f, g_ij_ > 1.f);

    for(int r=0; r<g_ij_.rows; r++) {

        g_ij_(r, r) = 0.f;
        for(int c=0; c<g_ij_.cols; c++) {

            g_ij_(r, c) = g_ij_(c, r);
        }
    }

    // add test graphs to signal
    sig_.Append(NAME_GRAPH_AB, g_ab_);
    sig_.Append(NAME_GRAPH_IJ, g_ij_);

    graph_compatibility_->Activate(sig_);
    graph_compatibility_->Response(sig_);

    to_->Activate(sig_);
    to_->Response(sig_);

    Mat1f m = sig_.MostRecentMat1f(NAME_M);

//    cout<<cv::format(m, cv::Formatter::FMT_NUMPY)<<std::endl;
//    cv::imshow("m/sum(m)", elm::ConvertTo8U(m/sum(m)[0]));
//    cv::waitKey();

    EXPECT_MAT_DIMS_EQ(m, Size2i(g_ab_.rows, g_ij_.rows)) << "Match matrix should be of size (A, I)";

    // check we have a dominante diagonal
    for(int r=0; r<m.rows; r++) {

        for(int c=0; c<m.cols; c++) {

            if(r!=c) {

                //EXPECT_LT(m(r, c), m(r, r)) << "Values > diagonal at r=" << r << ", c=" << c;
            }
        }
    }
}

TEST_F(GradAssignmentTest, Dims)
{
    for(int A=1; A<10; A++) {

        for(int I=1; I<10; I++) {

            // generate random adjacency matrices
            g_ab_ = Mat1f(A, A);
            Mat1i tmp(A, A);
            int stddev = 1000;
            randu(tmp, 0, stddev);
            g_ab_ = tmp/static_cast<float>(stddev);

            // distance from node to itself is 0
            for(int r=0; r<g_ab_.rows; r++) {

                g_ab_(r, r) = 0.f;
            }
            // make symmetrical
            for(int r=0; r<g_ab_.rows; r++) {

                for(int c=0; c<g_ab_.rows; c++) {

                    g_ab_(r, c) = g_ab_(c, r);
                }
            }

            g_ij_ = Mat1f(I, I);
            g_ij_ = g_ab_.clone();    // make them equal

            sig_.Clear();
            // add test graphs to signal
            sig_.Append(NAME_GRAPH_AB, g_ab_);
            sig_.Append(NAME_GRAPH_IJ, g_ij_);

            graph_compatibility_->Activate(sig_);
            graph_compatibility_->Response(sig_);

            to_->Activate(sig_);
            to_->Response(sig_);

            EXPECT_MAT_DIMS_EQ(sig_.MostRecentMat1f(NAME_M),
                               Size2i(g_ab_.rows, g_ij_.rows))
                    << "Match matrix should be of size (A, I)";
        }
    }
}

/**
 * @brief Test that incrasing noise leads to deteriorated matching matrix
 *
 * For multiple iterations:
 *
 *  Measure difference between diagonal and other match variables.
 *  Sum difference across rows
 *
 * Measure slope across iterations, and see diagonal dominance decreasing
 *
 */
TEST_F(GradAssignmentTest, MoreNoise)
{
    g_ij_ = g_ab_.clone();    // start with equal graphs

    const int N=5;
    std::vector<float> diag_sum_diff(N);

    for(int i=0; i<N; i++) {

        // add noisy test graphs to signal
        sig_.Append(NAME_GRAPH_IJ, g_ij_);

        graph_compatibility_->Activate(sig_);
        graph_compatibility_->Response(sig_);

        to_->Activate(sig_);
        to_->Response(sig_);

        Mat1f m = sig_.MostRecentMat1f(NAME_M);

        // get diagonal values
        Mat1f diag(m.rows, 1);
        for(int r=0; r<m.rows; r++) {

            diag(r) = m(r, r);
        }

        diag_sum_diff[i] = sum(repeat(diag, 1, m.cols)-m)[0];

        // add more noise to g_ij_ for next iteration
        Mat1f noise(g_ij_.size());
        randn(noise, 0.f, 0.05f);
        g_ij_ += noise;
        g_ij_.setTo(0.f, g_ij_ < 0.f);
        g_ij_.setTo(1.f, g_ij_ > 1.f);

        // keep symmetric
        for(int r=0; r<g_ij_.rows; r++) {

            g_ij_(r, r) = 0.f;
            for(int c=0; c<g_ij_.cols; c++) {

                g_ij_(r, c) = g_ij_(c, r);
            }
        }
    }

    Mat _mean, _stddev;

    // Calculate mean slope to dermine if diagonals dominate less with noise.
    Mat1f deriv1;
    Sobel(diag_sum_diff, deriv1, CV_32F, 1, 0, 3);
    meanStdDev(deriv1, _mean, _stddev);

    EXPECT_LT(_mean.at<double>(), 0.) << "Diagonal dominance not decreasing with added noise." << Mat1f(diag_sum_diff).t();
}

} // annonymous namespace for test cases and fixtures

<|endoftext|>


<commit_before>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "net/tools/quic/test_tools/http_message_test_utils.h"

#include <vector>

#include "base/basictypes.h"
#include "base/logging.h"
#include "base/strings/string_number_conversions.h"

using base::StringPiece;
using std::string;
using std::vector;

namespace net {
namespace test {

namespace {

//const char* kContentEncoding = "content-encoding";
const char* kContentLength = "content-length";
const char* kTransferCoding = "transfer-encoding";

// Both kHTTPVersionString and kMethodString arrays are constructed to match
// the enum values defined in Version and Method of HTTPMessage.
const char* kHTTPVersionString[] = {
  "",
  "HTTP/0.9",
  "HTTP/1.0",
  "HTTP/1.1"
};

const char* kMethodString[] = {
  "",
  "OPTIONS",
  "GET",
  "HEAD",
  "POST",
  "PUT",
  "DELETE",
  "TRACE",
  "CONNECT",
  "MKCOL",
  "UNLOCK",
};

// Returns true if the message represents a complete request or response.
// Messages are considered complete if:
// - Transfer-Encoding: chunked is present and message has a final chunk.
// - Content-Length header is present and matches the message body length.
// - Neither Transfer-Encoding nor Content-Length is present and message
//   is tagged as complete.
bool IsCompleteMessage(const HTTPMessage& message) {
  return true;
  const BalsaHeaders* headers = message.headers();
  StringPiece content_length = headers->GetHeader(kContentLength);
  if (!content_length.empty()) {
    int parsed_content_length;
    if (!base::StringToInt(content_length, &parsed_content_length)) {
      return false;
    }
    return (message.body().size() == (uint)parsed_content_length);
  } else {
    // Assume messages without transfer coding or content-length are
    // tagged correctly.
    return message.has_complete_message();
  }
}

}  // namespace

HTTPMessage::Method HTTPMessage::StringToMethod(StringPiece str) {
  // Skip the first element of the array since it is empty string.
  for (unsigned long i = 1; i < arraysize(kMethodString); ++i) {
    if (strncmp(str.data(), kMethodString[i], str.length()) == 0) {
      return static_cast<HTTPMessage::Method>(i);
    }
  }
  return HttpConstants::UNKNOWN_METHOD;
}

HTTPMessage::Version HTTPMessage::StringToVersion(StringPiece str) {
  // Skip the first element of the array since it is empty string.
  for (unsigned long i = 1; i < arraysize(kHTTPVersionString); ++i) {
    if (strncmp(str.data(), kHTTPVersionString[i], str.length()) == 0) {
      return static_cast<HTTPMessage::Version>(i);
    }
  }
  return HttpConstants::HTTP_UNKNOWN;
}

const char* HTTPMessage::MethodToString(Method method) {
  CHECK_LT(method, arraysize(kMethodString));
  return kMethodString[method];
}

const char* HTTPMessage::VersionToString(Version version) {
  CHECK_LT(version, arraysize(kHTTPVersionString));
  return kHTTPVersionString[version];
}

HTTPMessage::HTTPMessage()
    : is_request_(true) {
  InitializeFields();
}

HTTPMessage::HTTPMessage(Version ver, Method request, const string& path)
    : is_request_(true) {
  InitializeFields();
  if (ver != HttpConstants::HTTP_0_9) {
    headers()->SetRequestVersion(VersionToString(ver));
  }
  headers()->SetRequestMethod(MethodToString(request));
  headers()->SetRequestUri(path);
}

HTTPMessage::~HTTPMessage() {
}

void HTTPMessage::InitializeFields() {
  has_complete_message_ = true;
  skip_message_validation_ = false;
}

void HTTPMessage::AddHeader(const string& header, const string& value) {
  headers()->AppendHeader(header, value);
}

void HTTPMessage::RemoveHeader(const string& header) {
  headers()->RemoveAllOfHeader(header);
}

void HTTPMessage::ReplaceHeader(const string& header, const string& value) {
  headers()->ReplaceOrAppendHeader(header, value);
}

void HTTPMessage::AddBody(const string& body, bool add_content_length) {
  body_ = body;
  // Remove any transfer-encoding that was left by a previous body.
  RemoveHeader(kTransferCoding);
  if (add_content_length) {
    ReplaceHeader(kContentLength, base::IntToString(body.size()));
  } else {
    RemoveHeader(kContentLength);
  }
}

void HTTPMessage::ValidateMessage() const {
  if (skip_message_validation_) {
    return;
  }

  vector<StringPiece> transfer_encodings;
  headers()->GetAllOfHeader(kTransferCoding, &transfer_encodings);
  CHECK_GE(1ul, transfer_encodings.size());
  for (vector<StringPiece>::iterator it = transfer_encodings.begin();
       it != transfer_encodings.end();
       ++it) {
    CHECK(StringPieceUtils::EqualIgnoreCase("identity", *it) ||
          StringPieceUtils::EqualIgnoreCase("chunked", *it)) << *it;
  }

  vector<StringPiece> content_lengths;
  headers()->GetAllOfHeader(kContentLength, &content_lengths);
  CHECK_GE(1ul, content_lengths.size());

  CHECK_EQ(has_complete_message_, IsCompleteMessage(*this));
}

}  // namespace test
}  // namespace net
<commit_msg>Attempt to fix chromium.chrome linux compile.<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "net/tools/quic/test_tools/http_message_test_utils.h"

#include <vector>

#include "base/basictypes.h"
#include "base/logging.h"
#include "base/strings/string_number_conversions.h"

using base::StringPiece;
using std::string;
using std::vector;

namespace net {
namespace test {

namespace {

//const char* kContentEncoding = "content-encoding";
const char* kContentLength = "content-length";
const char* kTransferCoding = "transfer-encoding";

// Both kHTTPVersionString and kMethodString arrays are constructed to match
// the enum values defined in Version and Method of HTTPMessage.
const char* kHTTPVersionString[] = {
  "",
  "HTTP/0.9",
  "HTTP/1.0",
  "HTTP/1.1"
};

const char* kMethodString[] = {
  "",
  "OPTIONS",
  "GET",
  "HEAD",
  "POST",
  "PUT",
  "DELETE",
  "TRACE",
  "CONNECT",
  "MKCOL",
  "UNLOCK",
};

// Returns true if the message represents a complete request or response.
// Messages are considered complete if:
// - Transfer-Encoding: chunked is present and message has a final chunk.
// - Content-Length header is present and matches the message body length.
// - Neither Transfer-Encoding nor Content-Length is present and message
//   is tagged as complete.
bool IsCompleteMessage(const HTTPMessage& message) {
  return true;
  const BalsaHeaders* headers = message.headers();
  StringPiece content_length = headers->GetHeader(kContentLength);
  if (!content_length.empty()) {
    int parsed_content_length;
    if (!base::StringToInt(content_length, &parsed_content_length)) {
      return false;
    }
    return (message.body().size() == (uint)parsed_content_length);
  } else {
    // Assume messages without transfer coding or content-length are
    // tagged correctly.
    return message.has_complete_message();
  }
}

}  // namespace

HTTPMessage::Method HTTPMessage::StringToMethod(StringPiece str) {
  // Skip the first element of the array since it is empty string.
  for (unsigned long i = 1; i < arraysize(kMethodString); ++i) {
    if (strncmp(str.data(), kMethodString[i], str.length()) == 0) {
      return static_cast<HTTPMessage::Method>(i);
    }
  }
  return HttpConstants::UNKNOWN_METHOD;
}

HTTPMessage::Version HTTPMessage::StringToVersion(StringPiece str) {
  // Skip the first element of the array since it is empty string.
  for (unsigned long i = 1; i < arraysize(kHTTPVersionString); ++i) {
    if (strncmp(str.data(), kHTTPVersionString[i], str.length()) == 0) {
      return static_cast<HTTPMessage::Version>(i);
    }
  }
  return HttpConstants::HTTP_UNKNOWN;
}

const char* HTTPMessage::MethodToString(Method method) {
  CHECK_LT(static_cast<size_t>(method), arraysize(kMethodString));
  return kMethodString[method];
}

const char* HTTPMessage::VersionToString(Version version) {
  CHECK_LT(static_cast<size_t>(version), arraysize(kHTTPVersionString));
  return kHTTPVersionString[version];
}

HTTPMessage::HTTPMessage()
    : is_request_(true) {
  InitializeFields();
}

HTTPMessage::HTTPMessage(Version ver, Method request, const string& path)
    : is_request_(true) {
  InitializeFields();
  if (ver != HttpConstants::HTTP_0_9) {
    headers()->SetRequestVersion(VersionToString(ver));
  }
  headers()->SetRequestMethod(MethodToString(request));
  headers()->SetRequestUri(path);
}

HTTPMessage::~HTTPMessage() {
}

void HTTPMessage::InitializeFields() {
  has_complete_message_ = true;
  skip_message_validation_ = false;
}

void HTTPMessage::AddHeader(const string& header, const string& value) {
  headers()->AppendHeader(header, value);
}

void HTTPMessage::RemoveHeader(const string& header) {
  headers()->RemoveAllOfHeader(header);
}

void HTTPMessage::ReplaceHeader(const string& header, const string& value) {
  headers()->ReplaceOrAppendHeader(header, value);
}

void HTTPMessage::AddBody(const string& body, bool add_content_length) {
  body_ = body;
  // Remove any transfer-encoding that was left by a previous body.
  RemoveHeader(kTransferCoding);
  if (add_content_length) {
    ReplaceHeader(kContentLength, base::IntToString(body.size()));
  } else {
    RemoveHeader(kContentLength);
  }
}

void HTTPMessage::ValidateMessage() const {
  if (skip_message_validation_) {
    return;
  }

  vector<StringPiece> transfer_encodings;
  headers()->GetAllOfHeader(kTransferCoding, &transfer_encodings);
  CHECK_GE(1ul, transfer_encodings.size());
  for (vector<StringPiece>::iterator it = transfer_encodings.begin();
       it != transfer_encodings.end();
       ++it) {
    CHECK(StringPieceUtils::EqualIgnoreCase("identity", *it) ||
          StringPieceUtils::EqualIgnoreCase("chunked", *it)) << *it;
  }

  vector<StringPiece> content_lengths;
  headers()->GetAllOfHeader(kContentLength, &content_lengths);
  CHECK_GE(1ul, content_lengths.size());

  CHECK_EQ(has_complete_message_, IsCompleteMessage(*this));
}

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