<commit_before>//===--- SemaStmtAttr.cpp - Statement Attribute Handling ------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  This file implements stmt-related attribute processing.
//
//===----------------------------------------------------------------------===//

#include "clang/Sema/SemaInternal.h"
#include "clang/AST/ASTContext.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Sema/DelayedDiagnostic.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/LoopHint.h"
#include "clang/Sema/ScopeInfo.h"
#include "llvm/ADT/StringExtras.h"

using namespace clang;
using namespace sema;

static Attr *handleFallThroughAttr(Sema &S, Stmt *St, const AttributeList &A,
                                   SourceRange Range) {
  if (!isa<NullStmt>(St)) {
    S.Diag(A.getRange().getBegin(), diag::err_fallthrough_attr_wrong_target)
        << St->getLocStart();
    if (isa<SwitchCase>(St)) {
      SourceLocation L = S.getLocForEndOfToken(Range.getEnd());
      S.Diag(L, diag::note_fallthrough_insert_semi_fixit)
          << FixItHint::CreateInsertion(L, ";");
    }
    return nullptr;
  }
  if (S.getCurFunction()->SwitchStack.empty()) {
    S.Diag(A.getRange().getBegin(), diag::err_fallthrough_attr_outside_switch);
    return nullptr;
  }
  return ::new (S.Context) FallThroughAttr(A.getRange(), S.Context,
                                           A.getAttributeSpellingListIndex());
}

static Attr *handleLoopHintAttr(Sema &S, Stmt *St, const AttributeList &A,
                                SourceRange) {
  if (St->getStmtClass() != Stmt::DoStmtClass &&
      St->getStmtClass() != Stmt::ForStmtClass &&
      St->getStmtClass() != Stmt::CXXForRangeStmtClass &&
      St->getStmtClass() != Stmt::WhileStmtClass) {
    S.Diag(St->getLocStart(), diag::err_pragma_loop_precedes_nonloop);
    return nullptr;
  }

  IdentifierLoc *OptionLoc = A.getArgAsIdent(0);
  IdentifierInfo *OptionInfo = OptionLoc->Ident;
  IdentifierLoc *ValueLoc = A.getArgAsIdent(1);
  IdentifierInfo *ValueInfo = ValueLoc->Ident;
  Expr *ValueExpr = A.getArgAsExpr(2);

  assert(OptionInfo && "Attribute must have valid option info.");

  LoopHintAttr::OptionType Option =
      llvm::StringSwitch<LoopHintAttr::OptionType>(OptionInfo->getNameStart())
          .Case("vectorize", LoopHintAttr::Vectorize)
          .Case("vectorize_width", LoopHintAttr::VectorizeWidth)
          .Case("interleave", LoopHintAttr::Interleave)
          .Case("interleave_count", LoopHintAttr::InterleaveCount)
          .Default(LoopHintAttr::Vectorize);

  int ValueInt;
  if (Option == LoopHintAttr::Vectorize || Option == LoopHintAttr::Interleave) {
    if (!ValueInfo) {
      S.Diag(ValueLoc->Loc, diag::err_pragma_loop_invalid_keyword)
          << /*MissingKeyword=*/true << "";
      return nullptr;
    }

    if (ValueInfo->isStr("disable"))
      ValueInt = 0;
    else if (ValueInfo->isStr("enable"))
      ValueInt = 1;
    else {
      S.Diag(ValueLoc->Loc, diag::err_pragma_loop_invalid_keyword)
          << /*MissingKeyword=*/false << ValueInfo;
      return nullptr;
    }
  } else if (Option == LoopHintAttr::VectorizeWidth ||
             Option == LoopHintAttr::InterleaveCount) {
    // FIXME: We should support template parameters for the loop hint value.
    // See bug report #19610.
    llvm::APSInt ValueAPS;
    if (!ValueExpr || !ValueExpr->isIntegerConstantExpr(ValueAPS, S.Context)) {
      S.Diag(ValueLoc->Loc, diag::err_pragma_loop_invalid_value)
          << /*MissingValue=*/true << "";
      return nullptr;
    }

    if ((ValueInt = ValueAPS.getSExtValue()) < 1) {
      S.Diag(ValueLoc->Loc, diag::err_pragma_loop_invalid_value)
          << /*MissingValue=*/false << ValueInt;
      return nullptr;
    }
  }

  return LoopHintAttr::CreateImplicit(S.Context, Option, ValueInt,
                                      A.getRange());
}

static void
CheckForIncompatibleAttributes(Sema &S, SmallVectorImpl<const Attr *> &Attrs) {
  int PrevOptionValue[4] = {-1, -1, -1, -1};
  int OptionId[4] = {LoopHintAttr::Vectorize, LoopHintAttr::VectorizeWidth,
                     LoopHintAttr::Interleave, LoopHintAttr::InterleaveCount};

  for (const auto *I : Attrs) {
    const LoopHintAttr *LH = dyn_cast<LoopHintAttr>(I);

    // Skip non loop hint attributes
    if (!LH)
      continue;

    int State, Value;
    int Option = LH->getOption();
    int ValueInt = LH->getValue();

    switch (Option) {
    case LoopHintAttr::Vectorize:
    case LoopHintAttr::VectorizeWidth:
      State = 0;
      Value = 1;
      break;
    case LoopHintAttr::Interleave:
    case LoopHintAttr::InterleaveCount:
      State = 2;
      Value = 3;
      break;
    }

    SourceLocation ValueLoc = LH->getRange().getEnd();

    // Compatibility testing is split into two cases.
    // 1. if the current loop hint sets state (enable/disable) - check against
    // previous state and value.
    // 2. if the current loop hint sets a value - check against previous state
    // and value.

    if (Option == State) {
      if (PrevOptionValue[State] != -1) {
        // Cannot specify state twice.
        int PrevValue = PrevOptionValue[State];
        S.Diag(ValueLoc, diag::err_pragma_loop_compatibility)
            << /*Duplicate=*/true << LoopHintAttr::getOptionName(Option)
            << LoopHintAttr::getValueName(PrevValue)
            << LoopHintAttr::getOptionName(Option)
            << LoopHintAttr::getValueName(Value);
      }

      if (PrevOptionValue[Value] != -1) {
        // Compare state with previous width/count.
        int PrevOption = OptionId[Value];
        int PrevValueInt = PrevOptionValue[Value];
        if ((ValueInt == 0 && PrevValueInt > 1) ||
            (ValueInt == 1 && PrevValueInt <= 1))
          S.Diag(ValueLoc, diag::err_pragma_loop_compatibility)
              << /*Duplicate=*/false << LoopHintAttr::getOptionName(PrevOption)
              << PrevValueInt << LoopHintAttr::getOptionName(Option)
              << LoopHintAttr::getValueName(ValueInt);
      }
    } else {
      if (PrevOptionValue[State] != -1) {
        // Compare width/count value with previous state.
        int PrevOption = OptionId[State];
        int PrevValueInt = PrevOptionValue[State];
        if ((ValueInt > 1 && PrevValueInt == 0) ||
            (ValueInt <= 1 && PrevValueInt == 1))
          S.Diag(ValueLoc, diag::err_pragma_loop_compatibility)
              << /*Duplicate=*/false << LoopHintAttr::getOptionName(PrevOption)
              << LoopHintAttr::getValueName(PrevValueInt)
              << LoopHintAttr::getOptionName(Option) << ValueInt;
      }

      if (PrevOptionValue[Value] != -1) {
        // Cannot specify a width/count twice.
        int PrevValueInt = PrevOptionValue[Value];
        S.Diag(ValueLoc, diag::err_pragma_loop_compatibility)
            << /*Duplicate=*/true << LoopHintAttr::getOptionName(Option)
            << PrevValueInt << LoopHintAttr::getOptionName(Option) << ValueInt;
      }
    }

    PrevOptionValue[Option] = ValueInt;
  }
}

static Attr *ProcessStmtAttribute(Sema &S, Stmt *St, const AttributeList &A,
                                  SourceRange Range) {
  switch (A.getKind()) {
  case AttributeList::UnknownAttribute:
    S.Diag(A.getLoc(), A.isDeclspecAttribute() ?
           diag::warn_unhandled_ms_attribute_ignored :
           diag::warn_unknown_attribute_ignored) << A.getName();
    return nullptr;
  case AttributeList::AT_FallThrough:
    return handleFallThroughAttr(S, St, A, Range);
  case AttributeList::AT_LoopHint:
    return handleLoopHintAttr(S, St, A, Range);
  default:
    // if we're here, then we parsed a known attribute, but didn't recognize
    // it as a statement attribute => it is declaration attribute
    S.Diag(A.getRange().getBegin(), diag::err_attribute_invalid_on_stmt)
        << A.getName() << St->getLocStart();
    return nullptr;
  }
}

StmtResult Sema::ProcessStmtAttributes(Stmt *S, AttributeList *AttrList,
                                       SourceRange Range) {
  SmallVector<const Attr*, 8> Attrs;
  for (const AttributeList* l = AttrList; l; l = l->getNext()) {
    if (Attr *a = ProcessStmtAttribute(*this, S, *l, Range))
      Attrs.push_back(a);
  }

  CheckForIncompatibleAttributes(*this, Attrs);

  if (Attrs.empty())
    return S;

  return ActOnAttributedStmt(Range.getBegin(), Attrs, S);
}
<commit_msg>Quieting a false-positive which was causing the sanitizer bots to go red.<commit_after>//===--- SemaStmtAttr.cpp - Statement Attribute Handling ------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  This file implements stmt-related attribute processing.
//
//===----------------------------------------------------------------------===//

#include "clang/Sema/SemaInternal.h"
#include "clang/AST/ASTContext.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Sema/DelayedDiagnostic.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/LoopHint.h"
#include "clang/Sema/ScopeInfo.h"
#include "llvm/ADT/StringExtras.h"

using namespace clang;
using namespace sema;

static Attr *handleFallThroughAttr(Sema &S, Stmt *St, const AttributeList &A,
                                   SourceRange Range) {
  if (!isa<NullStmt>(St)) {
    S.Diag(A.getRange().getBegin(), diag::err_fallthrough_attr_wrong_target)
        << St->getLocStart();
    if (isa<SwitchCase>(St)) {
      SourceLocation L = S.getLocForEndOfToken(Range.getEnd());
      S.Diag(L, diag::note_fallthrough_insert_semi_fixit)
          << FixItHint::CreateInsertion(L, ";");
    }
    return nullptr;
  }
  if (S.getCurFunction()->SwitchStack.empty()) {
    S.Diag(A.getRange().getBegin(), diag::err_fallthrough_attr_outside_switch);
    return nullptr;
  }
  return ::new (S.Context) FallThroughAttr(A.getRange(), S.Context,
                                           A.getAttributeSpellingListIndex());
}

static Attr *handleLoopHintAttr(Sema &S, Stmt *St, const AttributeList &A,
                                SourceRange) {
  if (St->getStmtClass() != Stmt::DoStmtClass &&
      St->getStmtClass() != Stmt::ForStmtClass &&
      St->getStmtClass() != Stmt::CXXForRangeStmtClass &&
      St->getStmtClass() != Stmt::WhileStmtClass) {
    S.Diag(St->getLocStart(), diag::err_pragma_loop_precedes_nonloop);
    return nullptr;
  }

  IdentifierLoc *OptionLoc = A.getArgAsIdent(0);
  IdentifierInfo *OptionInfo = OptionLoc->Ident;
  IdentifierLoc *ValueLoc = A.getArgAsIdent(1);
  IdentifierInfo *ValueInfo = ValueLoc->Ident;
  Expr *ValueExpr = A.getArgAsExpr(2);

  assert(OptionInfo && "Attribute must have valid option info.");

  LoopHintAttr::OptionType Option =
      llvm::StringSwitch<LoopHintAttr::OptionType>(OptionInfo->getNameStart())
          .Case("vectorize", LoopHintAttr::Vectorize)
          .Case("vectorize_width", LoopHintAttr::VectorizeWidth)
          .Case("interleave", LoopHintAttr::Interleave)
          .Case("interleave_count", LoopHintAttr::InterleaveCount)
          .Default(LoopHintAttr::Vectorize);

  int ValueInt = 0;
  if (Option == LoopHintAttr::Vectorize || Option == LoopHintAttr::Interleave) {
    if (!ValueInfo) {
      S.Diag(ValueLoc->Loc, diag::err_pragma_loop_invalid_keyword)
          << /*MissingKeyword=*/true << "";
      return nullptr;
    }

    if (ValueInfo->isStr("disable"))
      ValueInt = 0;
    else if (ValueInfo->isStr("enable"))
      ValueInt = 1;
    else {
      S.Diag(ValueLoc->Loc, diag::err_pragma_loop_invalid_keyword)
          << /*MissingKeyword=*/false << ValueInfo;
      return nullptr;
    }
  } else if (Option == LoopHintAttr::VectorizeWidth ||
             Option == LoopHintAttr::InterleaveCount) {
    // FIXME: We should support template parameters for the loop hint value.
    // See bug report #19610.
    llvm::APSInt ValueAPS;
    if (!ValueExpr || !ValueExpr->isIntegerConstantExpr(ValueAPS, S.Context)) {
      S.Diag(ValueLoc->Loc, diag::err_pragma_loop_invalid_value)
          << /*MissingValue=*/true << "";
      return nullptr;
    }

    if ((ValueInt = ValueAPS.getSExtValue()) < 1) {
      S.Diag(ValueLoc->Loc, diag::err_pragma_loop_invalid_value)
          << /*MissingValue=*/false << ValueInt;
      return nullptr;
    }
  }

  return LoopHintAttr::CreateImplicit(S.Context, Option, ValueInt,
                                      A.getRange());
}

static void
CheckForIncompatibleAttributes(Sema &S, SmallVectorImpl<const Attr *> &Attrs) {
  int PrevOptionValue[4] = {-1, -1, -1, -1};
  int OptionId[4] = {LoopHintAttr::Vectorize, LoopHintAttr::VectorizeWidth,
                     LoopHintAttr::Interleave, LoopHintAttr::InterleaveCount};

  for (const auto *I : Attrs) {
    const LoopHintAttr *LH = dyn_cast<LoopHintAttr>(I);

    // Skip non loop hint attributes
    if (!LH)
      continue;

    int State, Value;
    int Option = LH->getOption();
    int ValueInt = LH->getValue();

    switch (Option) {
    case LoopHintAttr::Vectorize:
    case LoopHintAttr::VectorizeWidth:
      State = 0;
      Value = 1;
      break;
    case LoopHintAttr::Interleave:
    case LoopHintAttr::InterleaveCount:
      State = 2;
      Value = 3;
      break;
    }

    SourceLocation ValueLoc = LH->getRange().getEnd();

    // Compatibility testing is split into two cases.
    // 1. if the current loop hint sets state (enable/disable) - check against
    // previous state and value.
    // 2. if the current loop hint sets a value - check against previous state
    // and value.

    if (Option == State) {
      if (PrevOptionValue[State] != -1) {
        // Cannot specify state twice.
        int PrevValue = PrevOptionValue[State];
        S.Diag(ValueLoc, diag::err_pragma_loop_compatibility)
            << /*Duplicate=*/true << LoopHintAttr::getOptionName(Option)
            << LoopHintAttr::getValueName(PrevValue)
            << LoopHintAttr::getOptionName(Option)
            << LoopHintAttr::getValueName(Value);
      }

      if (PrevOptionValue[Value] != -1) {
        // Compare state with previous width/count.
        int PrevOption = OptionId[Value];
        int PrevValueInt = PrevOptionValue[Value];
        if ((ValueInt == 0 && PrevValueInt > 1) ||
            (ValueInt == 1 && PrevValueInt <= 1))
          S.Diag(ValueLoc, diag::err_pragma_loop_compatibility)
              << /*Duplicate=*/false << LoopHintAttr::getOptionName(PrevOption)
              << PrevValueInt << LoopHintAttr::getOptionName(Option)
              << LoopHintAttr::getValueName(ValueInt);
      }
    } else {
      if (PrevOptionValue[State] != -1) {
        // Compare width/count value with previous state.
        int PrevOption = OptionId[State];
        int PrevValueInt = PrevOptionValue[State];
        if ((ValueInt > 1 && PrevValueInt == 0) ||
            (ValueInt <= 1 && PrevValueInt == 1))
          S.Diag(ValueLoc, diag::err_pragma_loop_compatibility)
              << /*Duplicate=*/false << LoopHintAttr::getOptionName(PrevOption)
              << LoopHintAttr::getValueName(PrevValueInt)
              << LoopHintAttr::getOptionName(Option) << ValueInt;
      }

      if (PrevOptionValue[Value] != -1) {
        // Cannot specify a width/count twice.
        int PrevValueInt = PrevOptionValue[Value];
        S.Diag(ValueLoc, diag::err_pragma_loop_compatibility)
            << /*Duplicate=*/true << LoopHintAttr::getOptionName(Option)
            << PrevValueInt << LoopHintAttr::getOptionName(Option) << ValueInt;
      }
    }

    PrevOptionValue[Option] = ValueInt;
  }
}

static Attr *ProcessStmtAttribute(Sema &S, Stmt *St, const AttributeList &A,
                                  SourceRange Range) {
  switch (A.getKind()) {
  case AttributeList::UnknownAttribute:
    S.Diag(A.getLoc(), A.isDeclspecAttribute() ?
           diag::warn_unhandled_ms_attribute_ignored :
           diag::warn_unknown_attribute_ignored) << A.getName();
    return nullptr;
  case AttributeList::AT_FallThrough:
    return handleFallThroughAttr(S, St, A, Range);
  case AttributeList::AT_LoopHint:
    return handleLoopHintAttr(S, St, A, Range);
  default:
    // if we're here, then we parsed a known attribute, but didn't recognize
    // it as a statement attribute => it is declaration attribute
    S.Diag(A.getRange().getBegin(), diag::err_attribute_invalid_on_stmt)
        << A.getName() << St->getLocStart();
    return nullptr;
  }
}

StmtResult Sema::ProcessStmtAttributes(Stmt *S, AttributeList *AttrList,
                                       SourceRange Range) {
  SmallVector<const Attr*, 8> Attrs;
  for (const AttributeList* l = AttrList; l; l = l->getNext()) {
    if (Attr *a = ProcessStmtAttribute(*this, S, *l, Range))
      Attrs.push_back(a);
  }

  CheckForIncompatibleAttributes(*this, Attrs);

  if (Attrs.empty())
    return S;

  return ActOnAttributedStmt(Range.getBegin(), Attrs, S);
}
<|endoftext|>


<commit_before>#include "Motor.h"

Motor::Motor(uint8_t speedPin, uint8_t dirPin)
{
    this->speedPin = speedPin;
    this->dirPin = dirPin;
    this->speed = 0;
    this->minSpeed = 0;
    this->maxSpeed = 255;
}

void Motor::setup()
{
    pinMode(speedPin, OUTPUT);
    pinMode(dirPin, OUTPUT);
    analogWrite(speedPin, 0);
    forward();
}

uint8_t Motor::getSpeedPin()
{
    return speedPin;
}

uint8_t Motor::getDirPin()
{
    return dirPin;
}

uint8_t Motor::getSpeed()
{
    return speed;
}

uint8_t Motor::getMaxSpeed()
{
    return maxSpeed;
}

uint8_t Motor::getMinSpeed()
{
    return minSpeed;
}

void Motor::setMaxSpeed(uint8_t value)
{
    this->maxSpeed = value;
}

void Motor::setMinSpeed(uint8_t value)
{
    this->minSpeed = value;
}

void Motor::forward()
{
    digitalWrite(dirPin, LOW);
}

void Motor::backward()
{
    digitalWrite(dirPin, HIGH);
}

void Motor::stop()
{
    analogWrite(speedPin, 0);
}

void Motor::fullSpeed()
{
    setSpeed(maxSpeed);
}

void Motor::setSpeed(uint8_t value)
{
    if (value > maxSpeed) {
        value = maxSpeed;
    }

    if (value < minSpeed) {
        value = minSpeed;
    }

    this->speed = value;
    analogWrite(speedPin, speed);
}
<commit_msg>Fix style issue<commit_after>#include "Motor.h"

Motor::Motor(uint8_t speedPin, uint8_t dirPin)
{
    this->speedPin = speedPin;
    this->dirPin = dirPin;
    this->speed = 0;
    this->minSpeed = 0;
    this->maxSpeed = 255;
}

void Motor::setup()
{
    pinMode(speedPin, OUTPUT);
    pinMode(dirPin, OUTPUT);
    analogWrite(speedPin, 0);
    forward();
}

uint8_t Motor::getSpeedPin()
{
    return speedPin;
}

uint8_t Motor::getDirPin()
{
    return dirPin;
}

uint8_t Motor::getSpeed()
{
    return speed;
}

uint8_t Motor::getMaxSpeed()
{
    return maxSpeed;
}

uint8_t Motor::getMinSpeed()
{
    return minSpeed;
}

void Motor::setMaxSpeed(uint8_t value)
{
    this->maxSpeed = value;
}

void Motor::setMinSpeed(uint8_t value)
{
    this->minSpeed = value;
}

void Motor::forward()
{
    digitalWrite(dirPin, LOW);
}

void Motor::backward()
{
    digitalWrite(dirPin, HIGH);
}

void Motor::stop()
{
    analogWrite(speedPin, 0);
}

void Motor::fullSpeed()
{
    setSpeed(maxSpeed);
}

void Motor::setSpeed(uint8_t value)
{
    if (value > maxSpeed)
    {
        value = maxSpeed;
    }

    if (value < minSpeed)
    {
        value = minSpeed;
    }

    this->speed = value;
    analogWrite(speedPin, speed);
}
<|endoftext|>


<commit_before>//===-- Statistic.cpp - Easy way to expose stats information --------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the 'Statistic' class, which is designed to be an easy
// way to expose various success metrics from passes.  These statistics are
// printed at the end of a run, when the -stats command line option is enabled
// on the command line.
//
// This is useful for reporting information like the number of instructions
// simplified, optimized or removed by various transformations, like this:
//
// static Statistic NumInstEliminated("GCSE", "Number of instructions killed");
//
// Later, in the code: ++NumInstEliminated;
//
//===----------------------------------------------------------------------===//

#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/Mutex.h"
#include "llvm/Support/Timer.h"
#include "llvm/Support/YAMLTraits.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cstring>
using namespace llvm;

/// -stats - Command line option to cause transformations to emit stats about
/// what they did.
///
static cl::opt<bool> Stats(
    "stats",
    cl::desc("Enable statistics output from program (available with Asserts)"),
    cl::Hidden);

static cl::opt<bool> StatsAsJSON("stats-json",
                                 cl::desc("Display statistics as json data"),
                                 cl::Hidden);

static bool Enabled;
static bool PrintOnExit;

namespace {
/// This class is used in a ManagedStatic so that it is created on demand (when
/// the first statistic is bumped) and destroyed only when llvm_shutdown is
/// called. We print statistics from the destructor.
/// This class is also used to look up statistic values from applications that
/// use LLVM.
class StatisticInfo {
  std::vector<const Statistic*> Stats;

  friend void llvm::PrintStatistics();
  friend void llvm::PrintStatistics(raw_ostream &OS);
  friend void llvm::PrintStatisticsJSON(raw_ostream &OS);

  /// Sort statistics by debugtype,name,description.
  void sort();
public:
  using const_iterator = std::vector<const Statistic *>::const_iterator;

  StatisticInfo();
  ~StatisticInfo();

  void addStatistic(const Statistic *S) {
    Stats.push_back(S);
  }

  const_iterator begin() const { return Stats.begin(); }
  const_iterator end() const { return Stats.end(); }
  iterator_range<const_iterator> statistics() const {
    return {begin(), end()};
  }
};
} // end anonymous namespace

static ManagedStatic<StatisticInfo> StatInfo;
static ManagedStatic<sys::SmartMutex<true> > StatLock;

/// RegisterStatistic - The first time a statistic is bumped, this method is
/// called.
void Statistic::RegisterStatistic() {
  // If stats are enabled, inform StatInfo that this statistic should be
  // printed.
  sys::SmartScopedLock<true> Writer(*StatLock);
  if (!Initialized.load(std::memory_order_relaxed)) {
    if (Stats || Enabled)
      StatInfo->addStatistic(this);

    // Remember we have been registered.
    Initialized.store(true, std::memory_order_release);
  }
}

StatisticInfo::StatisticInfo() {
  // Ensure timergroup lists are created first so they are destructed after us.
  TimerGroup::ConstructTimerLists();
}

// Print information when destroyed, iff command line option is specified.
StatisticInfo::~StatisticInfo() {
  if (::Stats || PrintOnExit)
    llvm::PrintStatistics();
}

void llvm::EnableStatistics(bool PrintOnExit) {
  Enabled = true;
  ::PrintOnExit = PrintOnExit;
}

bool llvm::AreStatisticsEnabled() {
  return Enabled || Stats;
}

void StatisticInfo::sort() {
  std::stable_sort(Stats.begin(), Stats.end(),
                   [](const Statistic *LHS, const Statistic *RHS) {
    if (int Cmp = std::strcmp(LHS->getDebugType(), RHS->getDebugType()))
      return Cmp < 0;

    if (int Cmp = std::strcmp(LHS->getName(), RHS->getName()))
      return Cmp < 0;

    return std::strcmp(LHS->getDesc(), RHS->getDesc()) < 0;
  });
}

void llvm::PrintStatistics(raw_ostream &OS) {
  StatisticInfo &Stats = *StatInfo;

  // Figure out how long the biggest Value and Name fields are.
  unsigned MaxDebugTypeLen = 0, MaxValLen = 0;
  for (size_t i = 0, e = Stats.Stats.size(); i != e; ++i) {
    MaxValLen = std::max(MaxValLen,
                         (unsigned)utostr(Stats.Stats[i]->getValue()).size());
    MaxDebugTypeLen = std::max(MaxDebugTypeLen,
                         (unsigned)std::strlen(Stats.Stats[i]->getDebugType()));
  }

  Stats.sort();

  // Print out the statistics header...
  OS << "===" << std::string(73, '-') << "===\n"
     << "                          ... Statistics Collected ...\n"
     << "===" << std::string(73, '-') << "===\n\n";

  // Print all of the statistics.
  for (size_t i = 0, e = Stats.Stats.size(); i != e; ++i)
    OS << format("%*u %-*s - %s\n",
                 MaxValLen, Stats.Stats[i]->getValue(),
                 MaxDebugTypeLen, Stats.Stats[i]->getDebugType(),
                 Stats.Stats[i]->getDesc());

  OS << '\n';  // Flush the output stream.
  OS.flush();
}

void llvm::PrintStatisticsJSON(raw_ostream &OS) {
  StatisticInfo &Stats = *StatInfo;

  Stats.sort();

  // Print all of the statistics.
  OS << "{\n";
  const char *delim = "";
  for (const Statistic *Stat : Stats.Stats) {
    OS << delim;
    assert(yaml::needsQuotes(Stat->getDebugType()) == yaml::QuotingType::None &&
           "Statistic group/type name is simple.");
    assert(yaml::needsQuotes(Stat->getName()) == yaml::QuotingType::None &&
           "Statistic name is simple");
    OS << "\t\"" << Stat->getDebugType() << '.' << Stat->getName() << "\": "
       << Stat->getValue();
    delim = ",\n";
  }
  // Print timers.
  TimerGroup::printAllJSONValues(OS, delim);

  OS << "\n}\n";
  OS.flush();
}

void llvm::PrintStatistics() {
#if LLVM_ENABLE_STATS
  StatisticInfo &Stats = *StatInfo;

  // Statistics not enabled?
  if (Stats.Stats.empty()) return;

  // Get the stream to write to.
  std::unique_ptr<raw_ostream> OutStream = CreateInfoOutputFile();
  if (StatsAsJSON)
    PrintStatisticsJSON(*OutStream);
  else
    PrintStatistics(*OutStream);

#else
  // Check if the -stats option is set instead of checking
  // !Stats.Stats.empty().  In release builds, Statistics operators
  // do nothing, so stats are never Registered.
  if (Stats) {
    // Get the stream to write to.
    std::unique_ptr<raw_ostream> OutStream = CreateInfoOutputFile();
    (*OutStream) << "Statistics are disabled.  "
                 << "Build with asserts or with -DLLVM_ENABLE_STATS\n";
  }
#endif
}

const std::vector<std::pair<StringRef, unsigned>> llvm::GetStatistics() {
  sys::SmartScopedLock<true> Reader(*StatLock);
  std::vector<std::pair<StringRef, unsigned>> ReturnStats;

  for (const auto &Stat : StatInfo->statistics())
    ReturnStats.emplace_back(Stat->getName(), Stat->getValue());
  return ReturnStats;
}
<commit_msg>PrintStatistics() and PrintStatisticsJSON() should take StatLock<commit_after>//===-- Statistic.cpp - Easy way to expose stats information --------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the 'Statistic' class, which is designed to be an easy
// way to expose various success metrics from passes.  These statistics are
// printed at the end of a run, when the -stats command line option is enabled
// on the command line.
//
// This is useful for reporting information like the number of instructions
// simplified, optimized or removed by various transformations, like this:
//
// static Statistic NumInstEliminated("GCSE", "Number of instructions killed");
//
// Later, in the code: ++NumInstEliminated;
//
//===----------------------------------------------------------------------===//

#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/Mutex.h"
#include "llvm/Support/Timer.h"
#include "llvm/Support/YAMLTraits.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cstring>
using namespace llvm;

/// -stats - Command line option to cause transformations to emit stats about
/// what they did.
///
static cl::opt<bool> Stats(
    "stats",
    cl::desc("Enable statistics output from program (available with Asserts)"),
    cl::Hidden);

static cl::opt<bool> StatsAsJSON("stats-json",
                                 cl::desc("Display statistics as json data"),
                                 cl::Hidden);

static bool Enabled;
static bool PrintOnExit;

namespace {
/// This class is used in a ManagedStatic so that it is created on demand (when
/// the first statistic is bumped) and destroyed only when llvm_shutdown is
/// called. We print statistics from the destructor.
/// This class is also used to look up statistic values from applications that
/// use LLVM.
class StatisticInfo {
  std::vector<const Statistic*> Stats;

  friend void llvm::PrintStatistics();
  friend void llvm::PrintStatistics(raw_ostream &OS);
  friend void llvm::PrintStatisticsJSON(raw_ostream &OS);

  /// Sort statistics by debugtype,name,description.
  void sort();
public:
  using const_iterator = std::vector<const Statistic *>::const_iterator;

  StatisticInfo();
  ~StatisticInfo();

  void addStatistic(const Statistic *S) {
    Stats.push_back(S);
  }

  const_iterator begin() const { return Stats.begin(); }
  const_iterator end() const { return Stats.end(); }
  iterator_range<const_iterator> statistics() const {
    return {begin(), end()};
  }
};
} // end anonymous namespace

static ManagedStatic<StatisticInfo> StatInfo;
static ManagedStatic<sys::SmartMutex<true> > StatLock;

/// RegisterStatistic - The first time a statistic is bumped, this method is
/// called.
void Statistic::RegisterStatistic() {
  // If stats are enabled, inform StatInfo that this statistic should be
  // printed.
  sys::SmartScopedLock<true> Writer(*StatLock);
  if (!Initialized.load(std::memory_order_relaxed)) {
    if (Stats || Enabled)
      StatInfo->addStatistic(this);

    // Remember we have been registered.
    Initialized.store(true, std::memory_order_release);
  }
}

StatisticInfo::StatisticInfo() {
  // Ensure timergroup lists are created first so they are destructed after us.
  TimerGroup::ConstructTimerLists();
}

// Print information when destroyed, iff command line option is specified.
StatisticInfo::~StatisticInfo() {
  if (::Stats || PrintOnExit)
    llvm::PrintStatistics();
}

void llvm::EnableStatistics(bool PrintOnExit) {
  Enabled = true;
  ::PrintOnExit = PrintOnExit;
}

bool llvm::AreStatisticsEnabled() {
  return Enabled || Stats;
}

void StatisticInfo::sort() {
  std::stable_sort(Stats.begin(), Stats.end(),
                   [](const Statistic *LHS, const Statistic *RHS) {
    if (int Cmp = std::strcmp(LHS->getDebugType(), RHS->getDebugType()))
      return Cmp < 0;

    if (int Cmp = std::strcmp(LHS->getName(), RHS->getName()))
      return Cmp < 0;

    return std::strcmp(LHS->getDesc(), RHS->getDesc()) < 0;
  });
}

void llvm::PrintStatistics(raw_ostream &OS) {
  StatisticInfo &Stats = *StatInfo;

  // Figure out how long the biggest Value and Name fields are.
  unsigned MaxDebugTypeLen = 0, MaxValLen = 0;
  for (size_t i = 0, e = Stats.Stats.size(); i != e; ++i) {
    MaxValLen = std::max(MaxValLen,
                         (unsigned)utostr(Stats.Stats[i]->getValue()).size());
    MaxDebugTypeLen = std::max(MaxDebugTypeLen,
                         (unsigned)std::strlen(Stats.Stats[i]->getDebugType()));
  }

  Stats.sort();

  // Print out the statistics header...
  OS << "===" << std::string(73, '-') << "===\n"
     << "                          ... Statistics Collected ...\n"
     << "===" << std::string(73, '-') << "===\n\n";

  // Print all of the statistics.
  for (size_t i = 0, e = Stats.Stats.size(); i != e; ++i)
    OS << format("%*u %-*s - %s\n",
                 MaxValLen, Stats.Stats[i]->getValue(),
                 MaxDebugTypeLen, Stats.Stats[i]->getDebugType(),
                 Stats.Stats[i]->getDesc());

  OS << '\n';  // Flush the output stream.
  OS.flush();
}

void llvm::PrintStatisticsJSON(raw_ostream &OS) {
  sys::SmartScopedLock<true> Reader(*StatLock);
  StatisticInfo &Stats = *StatInfo;

  Stats.sort();

  // Print all of the statistics.
  OS << "{\n";
  const char *delim = "";
  for (const Statistic *Stat : Stats.Stats) {
    OS << delim;
    assert(yaml::needsQuotes(Stat->getDebugType()) == yaml::QuotingType::None &&
           "Statistic group/type name is simple.");
    assert(yaml::needsQuotes(Stat->getName()) == yaml::QuotingType::None &&
           "Statistic name is simple");
    OS << "\t\"" << Stat->getDebugType() << '.' << Stat->getName() << "\": "
       << Stat->getValue();
    delim = ",\n";
  }
  // Print timers.
  TimerGroup::printAllJSONValues(OS, delim);

  OS << "\n}\n";
  OS.flush();
}

void llvm::PrintStatistics() {
#if LLVM_ENABLE_STATS
  sys::SmartScopedLock<true> Reader(*StatLock);
  StatisticInfo &Stats = *StatInfo;

  // Statistics not enabled?
  if (Stats.Stats.empty()) return;

  // Get the stream to write to.
  std::unique_ptr<raw_ostream> OutStream = CreateInfoOutputFile();
  if (StatsAsJSON)
    PrintStatisticsJSON(*OutStream);
  else
    PrintStatistics(*OutStream);

#else
  // Check if the -stats option is set instead of checking
  // !Stats.Stats.empty().  In release builds, Statistics operators
  // do nothing, so stats are never Registered.
  if (Stats) {
    // Get the stream to write to.
    std::unique_ptr<raw_ostream> OutStream = CreateInfoOutputFile();
    (*OutStream) << "Statistics are disabled.  "
                 << "Build with asserts or with -DLLVM_ENABLE_STATS\n";
  }
#endif
}

const std::vector<std::pair<StringRef, unsigned>> llvm::GetStatistics() {
  sys::SmartScopedLock<true> Reader(*StatLock);
  std::vector<std::pair<StringRef, unsigned>> ReturnStats;

  for (const auto &Stat : StatInfo->statistics())
    ReturnStats.emplace_back(Stat->getName(), Stat->getValue());
  return ReturnStats;
}
<|endoftext|>


<commit_before>/*
 *
 * GAMS - General Algebraic Modeling System C++ API
 *
 * Copyright (c) 2017 GAMS Software GmbH <support@gams.com>
 * Copyright (c) 2017 GAMS Development Corp. <support@gams.com>
 *
 * 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 "gams.h"
#include <iostream>
#include <vector>

using namespace gams;
using namespace std;

#ifdef __unix__

int main()
{
    cout << "---------- Transport 10 --------------" << endl;
    cout << "Transport 10 is a Microsoft Windows only example." << endl;
    return 0;
}

#else

#include <QAxObject>
#include <Windows.h> // includes "Ole2.h" that includes "objbase.h" to access CoInitialize() and CoUninitialize()

string getModelText()
{
    return  "  Sets                                                                     \n"
            "       i   canning plants                                                  \n"
            "       j   markets                                                         \n"
            "                                                                           \n"
            "  Parameters                                                               \n"
            "       a(i)   capacity of plant i in cases                                 \n"
            "       b(j)   demand at market j in cases                                  \n"
            "       d(i,j) distance in thousands of miles                               \n"
            "  Scalar f  freight in dollars per case per thousand miles /90/;           \n"
            "                                                                           \n"
            "$if not set gdxincname $abort 'no include file name for data file provided'\n"
            "$gdxin %gdxincname%                                                        \n"
            "$load i j a b d                                                            \n"
            "$gdxin                                                                     \n"
            "                                                                           \n"
            "  Parameter c(i,j)  transport cost in thousands of dollars per case ;      \n"
            "                                                                           \n"
            "            c(i,j) = f * d(i,j) / 1000 ;                                   \n"
            "                                                                           \n"
            "  Variables                                                                \n"
            "       x(i,j)  shipment quantities in cases                                \n"
            "       z       total transportation costs in thousands of dollars ;        \n"
            "                                                                           \n"
            "  Positive Variable x ;                                                    \n"
            "                                                                           \n"
            "  Equations                                                                \n"
            "       cost        define objective function                               \n"
            "       supply(i)   observe supply limit at plant i                         \n"
            "       demand(j)   satisfy demand at market j ;                            \n"
            "                                                                           \n"
            "  cost ..        z  =e=  sum((i,j), c(i,j)*x(i,j)) ;                       \n"
            "                                                                           \n"
            "  supply(i) ..   sum(j, x(i,j))  =l=  a(i) ;                               \n"
            "                                                                           \n"
            "  demand(j) ..   sum(i, x(i,j))  =g=  b(j) ;                               \n"
            "                                                                           \n"
            "  Model transport /all/ ;                                                  \n"
            "                                                                           \n"
            "  Solve transport using lp minimizing z ;                                  \n"
            "                                                                           \n"
            "  Display x.l, x.m ;                                                       \n";
}

/// Creates an 1 dimensional GAMSParameter and transfers data from an Excel sheet (horizontal ordered)
///
/// \param sheets The sheets object of an open Excel workbook
/// \param sheetName The name of the sheet to be read
/// \param db The GAMSDatabase where the GAMSParameter is created in
/// \param paramName The name of the new GAMSParameter
/// \param paramText The explplanatory text of the new GAMSParameter
/// \param set The GAMSSet for GAMSParameter dimension
/// \return The new GAMSParameter in the GAMSDatabase
///
GAMSParameter sheetToParameter(QAxObject* sheets, string sheetName
                               , GAMSDatabase db, string paramName, string paramText, GAMSSet set)
{
    QAxObject* sheet = sheets->querySubObject( "Item( string )", sheetName.c_str() );
    GAMSParameter param = db.addParameter(paramName, paramText, set);

    QAxObject* usedrange = sheet->querySubObject( "UsedRange");
    QAxObject * columns = usedrange->querySubObject("Columns");
    int intCols = columns->property("Count").toInt();

    for (int i = 1; i <= intCols; i++) {
        std::string name = sheet->querySubObject("Cells( int, int )", 1, i)->dynamicCall("Value()").toString().toStdString();
        double value = sheet->querySubObject("Cells( int, int )", 2, i)->dynamicCall("Value()").toDouble();
        set.addRecord(name);
        GAMSParameterRecord rec = param.addRecord(name);
        rec.setValue(value);
    }
    return param;
}

/// Creates a 2 dimensional GAMSParameter and transfers data from an Excel sheet
///
/// \param sheets The sheets object of an open Excel workbook
/// \param sheetName The name of the sheet to be read
/// \param db The GAMSDatabase where the GAMSParameter is created in
/// \param paramName The name of the new GAMSParameter
/// \param paramText The explplanatory text of the new GAMSParameter
/// \param set1 The GAMSSet for first GAMSParameter dimension
/// \param set2 The GAMSSet for second GAMSParameter dimension
/// \return The new GAMSParameter in the GAMSDatabase
///
GAMSParameter sheetToParameter(QAxObject* sheets, string sheetName
                               , GAMSDatabase db, string paramName, string paramText, GAMSSet set1, GAMSSet set2)
{
    QAxObject* sheet = sheets->querySubObject( "Item( string )", sheetName.c_str() );
    vector<GAMSDomain> sets {set1, set2};
    GAMSParameter param = db.addParameter(paramName, paramText, sets);

    QAxObject* usedrange = sheet->querySubObject( "UsedRange");
    QAxObject * columns = usedrange->querySubObject("Columns");
    int intCols = columns->property("Count").toInt();
    QAxObject * rows = usedrange->querySubObject("Rows");
    int intRows = rows->property("Count").toInt();

    for (int j = 2; j <= intCols; j++) {
        string namej = sheet->querySubObject("Cells( int, int )", 1, j)->dynamicCall("Value()").toString().toStdString();
        for (int i = 2; i <= intRows; ++i) {
            string namei = sheet->querySubObject("Cells( int, int )", i, 1)->dynamicCall("Value()").toString().toStdString();
            GAMSParameterRecord rec = param.addRecord(namei, namej);
            double value = sheet->querySubObject("Cells( int, int )", i, j)->dynamicCall("Value()").toDouble();
            rec.setValue(value);
        }
    }
    return param;
}

/// This is the 10th model in a series of tutorial examples. Here we show:
///   - How to fill a GAMSDatabase by reading from MS Excel
int main(int argc, char* argv[])
{
    cout << "---------- Transport 10 --------------" << endl;
    cout << "Transport 10 is a Microsoft Windows only example." << endl;

    ::CoInitialize(0); // initialize thread to use ActiveX (some systems may need CoInititializeEx)

    GAMSWorkspaceInfo wsInfo;
    if (argc > 1)
        wsInfo.setSystemDirectory(argv[1]);
    GAMSWorkspace ws(wsInfo);

    // Creating the GAMSDatabase and fill with the workbook data
    GAMSDatabase db = ws.addDatabase();
    QString fileName = QString::fromStdString(ws.systemDirectory())+ cPathSep + "apifiles" + cPathSep + "Data" + cPathSep + "transport.xls";

    QAxObject* excel = new QAxObject( "Excel.Application", 0 );
    QAxObject* workbooks = excel->querySubObject( "Workbooks" );
    QAxObject* workbook = workbooks->querySubObject( "Open(const QString&)", fileName );
    QAxObject* sheets = workbook->querySubObject( "Worksheets" );

    GAMSSet i = db.addSet("i", 1, "Plants");
    GAMSSet j = db.addSet("j", 1, "Markets");

    // read parameters
    sheetToParameter(sheets, "capacity", db, "a", "Capacity", i);
    sheetToParameter(sheets, "demand", db, "b", "Demand", j);
    sheetToParameter(sheets, "distance", db, "d", "Distance", i, j);

    // clean up and close up
    workbook->dynamicCall("Close()");
    excel->dynamicCall("Quit()");

    // Create and run the GAMSJob
    GAMSOptions opt = ws.addOptions();
    GAMSJob t10 = ws.addJobFromString(getModelText());
    opt.setDefine("gdxincname", db.name());
    opt.setAllModelTypes("xpress");
    t10.run(opt, db);
    for (GAMSVariableRecord record : t10.outDB().getVariable("x"))
        cout << "x(" << record.key(0) << "," << record.key(1) << "): level=" << record.level() <<
                " marginal=" << record.marginal() << endl;

    ::CoUninitialize();

    return 0;
}
#endif
<commit_msg>Transport10 typo.<commit_after>/*
 *
 * GAMS - General Algebraic Modeling System C++ API
 *
 * Copyright (c) 2017 GAMS Software GmbH <support@gams.com>
 * Copyright (c) 2017 GAMS Development Corp. <support@gams.com>
 *
 * 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 "gams.h"
#include <iostream>
#include <vector>

using namespace gams;
using namespace std;

#ifdef __unix__

int main()
{
    cout << "---------- Transport 10 --------------" << endl;
    cout << "Transport 10 is a Microsoft Windows only example." << endl;
    return 0;
}

#else

#include <QAxObject>
#include <Windows.h> // includes "Ole2.h" that includes "objbase.h" to access CoInitialize() and CoUninitialize()

string getModelText()
{
    return  "  Sets                                                                     \n"
            "       i   canning plants                                                  \n"
            "       j   markets                                                         \n"
            "                                                                           \n"
            "  Parameters                                                               \n"
            "       a(i)   capacity of plant i in cases                                 \n"
            "       b(j)   demand at market j in cases                                  \n"
            "       d(i,j) distance in thousands of miles                               \n"
            "  Scalar f  freight in dollars per case per thousand miles /90/;           \n"
            "                                                                           \n"
            "$if not set gdxincname $abort 'no include file name for data file provided'\n"
            "$gdxin %gdxincname%                                                        \n"
            "$load i j a b d                                                            \n"
            "$gdxin                                                                     \n"
            "                                                                           \n"
            "  Parameter c(i,j)  transport cost in thousands of dollars per case ;      \n"
            "                                                                           \n"
            "            c(i,j) = f * d(i,j) / 1000 ;                                   \n"
            "                                                                           \n"
            "  Variables                                                                \n"
            "       x(i,j)  shipment quantities in cases                                \n"
            "       z       total transportation costs in thousands of dollars ;        \n"
            "                                                                           \n"
            "  Positive Variable x ;                                                    \n"
            "                                                                           \n"
            "  Equations                                                                \n"
            "       cost        define objective function                               \n"
            "       supply(i)   observe supply limit at plant i                         \n"
            "       demand(j)   satisfy demand at market j ;                            \n"
            "                                                                           \n"
            "  cost ..        z  =e=  sum((i,j), c(i,j)*x(i,j)) ;                       \n"
            "                                                                           \n"
            "  supply(i) ..   sum(j, x(i,j))  =l=  a(i) ;                               \n"
            "                                                                           \n"
            "  demand(j) ..   sum(i, x(i,j))  =g=  b(j) ;                               \n"
            "                                                                           \n"
            "  Model transport /all/ ;                                                  \n"
            "                                                                           \n"
            "  Solve transport using lp minimizing z ;                                  \n"
            "                                                                           \n"
            "  Display x.l, x.m ;                                                       \n";
}

/// Creates an 1 dimensional GAMSParameter and transfers data from an Excel sheet (horizontal ordered)
///
/// \param sheets The sheets object of an open Excel workbook
/// \param sheetName The name of the sheet to be read
/// \param db The GAMSDatabase where the GAMSParameter is created in
/// \param paramName The name of the new GAMSParameter
/// \param paramText The explplanatory text of the new GAMSParameter
/// \param set The GAMSSet for GAMSParameter dimension
/// \return The new GAMSParameter in the GAMSDatabase
///
GAMSParameter sheetToParameter(QAxObject* sheets, string sheetName
                               , GAMSDatabase db, string paramName, string paramText, GAMSSet set)
{
    QAxObject* sheet = sheets->querySubObject( "Item( string )", sheetName.c_str() );
    GAMSParameter param = db.addParameter(paramName, paramText, set);

    QAxObject* usedrange = sheet->querySubObject( "UsedRange");
    QAxObject * columns = usedrange->querySubObject("Columns");
    int intCols = columns->property("Count").toInt();

    for (int i = 1; i <= intCols; i++) {
        std::string name = sheet->querySubObject("Cells( int, int )", 1, i)->dynamicCall("Value()").toString().toStdString();
        double value = sheet->querySubObject("Cells( int, int )", 2, i)->dynamicCall("Value()").toDouble();
        set.addRecord(name);
        GAMSParameterRecord rec = param.addRecord(name);
        rec.setValue(value);
    }
    return param;
}

/// Creates a 2 dimensional GAMSParameter and transfers data from an Excel sheet
///
/// \param sheets The sheets object of an open Excel workbook
/// \param sheetName The name of the sheet to be read
/// \param db The GAMSDatabase where the GAMSParameter is created in
/// \param paramName The name of the new GAMSParameter
/// \param paramText The explplanatory text of the new GAMSParameter
/// \param set1 The GAMSSet for first GAMSParameter dimension
/// \param set2 The GAMSSet for second GAMSParameter dimension
/// \return The new GAMSParameter in the GAMSDatabase
///
GAMSParameter sheetToParameter(QAxObject* sheets, string sheetName
                               , GAMSDatabase db, string paramName, string paramText, GAMSSet set1, GAMSSet set2)
{
    QAxObject* sheet = sheets->querySubObject( "Item( string )", sheetName.c_str() );
    vector<GAMSDomain> sets {set1, set2};
    GAMSParameter param = db.addParameter(paramName, paramText, sets);

    QAxObject* usedrange = sheet->querySubObject( "UsedRange");
    QAxObject * columns = usedrange->querySubObject("Columns");
    int intCols = columns->property("Count").toInt();
    QAxObject * rows = usedrange->querySubObject("Rows");
    int intRows = rows->property("Count").toInt();

    for (int j = 2; j <= intCols; j++) {
        string namej = sheet->querySubObject("Cells( int, int )", 1, j)->dynamicCall("Value()").toString().toStdString();
        for (int i = 2; i <= intRows; ++i) {
            string namei = sheet->querySubObject("Cells( int, int )", i, 1)->dynamicCall("Value()").toString().toStdString();
            GAMSParameterRecord rec = param.addRecord(namei, namej);
            double value = sheet->querySubObject("Cells( int, int )", i, j)->dynamicCall("Value()").toDouble();
            rec.setValue(value);
        }
    }
    return param;
}

/// This is the 10th model in a series of tutorial examples. Here we show:
///   - How to fill a GAMSDatabase by reading from MS Excel
int main(int argc, char* argv[])
{
    cout << "---------- Transport 10 --------------" << endl;

    ::CoInitialize(0); // initialize thread to use ActiveX (some systems may need CoInititializeEx)

    GAMSWorkspaceInfo wsInfo;
    if (argc > 1)
        wsInfo.setSystemDirectory(argv[1]);
    GAMSWorkspace ws(wsInfo);

    // Creating the GAMSDatabase and fill with the workbook data
    GAMSDatabase db = ws.addDatabase();
    QString fileName = QString::fromStdString(ws.systemDirectory())+ cPathSep + "apifiles" + cPathSep + "Data" + cPathSep + "transport.xls";

    QAxObject* excel = new QAxObject( "Excel.Application", 0 );
    QAxObject* workbooks = excel->querySubObject( "Workbooks" );
    QAxObject* workbook = workbooks->querySubObject( "Open(const QString&)", fileName );
    QAxObject* sheets = workbook->querySubObject( "Worksheets" );

    GAMSSet i = db.addSet("i", 1, "Plants");
    GAMSSet j = db.addSet("j", 1, "Markets");

    // read parameters
    sheetToParameter(sheets, "capacity", db, "a", "Capacity", i);
    sheetToParameter(sheets, "demand", db, "b", "Demand", j);
    sheetToParameter(sheets, "distance", db, "d", "Distance", i, j);

    // clean up and close up
    workbook->dynamicCall("Close()");
    excel->dynamicCall("Quit()");

    // Create and run the GAMSJob
    GAMSOptions opt = ws.addOptions();
    GAMSJob t10 = ws.addJobFromString(getModelText());
    opt.setDefine("gdxincname", db.name());
    opt.setAllModelTypes("xpress");
    t10.run(opt, db);
    for (GAMSVariableRecord record : t10.outDB().getVariable("x"))
        cout << "x(" << record.key(0) << "," << record.key(1) << "): level=" << record.level() <<
                " marginal=" << record.marginal() << endl;

    ::CoUninitialize();

    return 0;
}
#endif
<|endoftext|>


<commit_before>// Swap the contents of two containers

#include <algorithm>
#include <utility>
#include <vector>

int main()
{
	std::vector<int> v1 = { 1, 3, 5, 7 };
	std::vector<int> v2 = { 2, 4, 6, 8 };

	std::swap_ranges(std::begin(v1), std::end(v1), std::begin(v2));

	v1.swap(v2);

	using std::swap;
	swap(v1, v2);
}

// Swap the contents of two containers.
//
// On [9-10] we create a pair of `vectors`s, and fill them with values.
//
// On [12] we swap the contents of the two vectors using
// [`std::swap_ranges`](cpp/algorithm/swap_ranges), which goes through
// two ranges and does an element-by-element swap of their values.
// (So in this example, it does four swaps - one for each of the four
// elements in the `vector`s.)
//
// On [14] we swap the `vector`s' contents all in one shot - not
// element-by-element.
// (`v2.swap(v1)` would have the same effect.)
//
// On [16-17] we again swap the `vector`s all in one shot, this time
// using the generic swap pattern.
//
// The difference between `swap_ranges()` and the `swap()` methods is
// that `swap_ranges()` goes through both containers element-by-element
// and swaps each pair of elements individually, while `swap()` (either
// the member function or the generic non-member function) swaps the
// *entire* container at once.
// The two methods each have their pros and cons.
//
// `swap_ranges()` is generally much slower than `swap()`, because it
// has to swap each pair of values one at a time, rather than all at
// once.
// It also requires that both of the ranges we swap are the same size.
// However, it does not invalidate the iterators of the container, and
// it allows us to swap *portions* of a container - even within
// the same container (for example, if your container has 10 or more
// elements we could swap the first 5 elements with the last 5).
//
// `swap()` is usually *much* faster than `swap_ranges()` - for large
// containers it can be thousands or millions of times faster (but
// this is not true for *all* container types).
// `swap()` can swap the contents of two containers even if they are
// not the same size (so we can swap a container with 100 elements
// with an empty container).
// However, it will invalidate the container's iterators, and there is
// no option to swap only portions of a container with `swap()`.
<commit_msg>Review/edit swap containers sample<commit_after>// Swap containers

#include <algorithm>
#include <utility>
#include <vector>

int main()
{
	std::vector<int> v1 = { 1, 3, 5, 7 };
	std::vector<int> v2 = { 2, 4, 6, 8 };

	std::swap_ranges(std::begin(v1), std::end(v1), std::begin(v2));

	v1.swap(v2);

	using std::swap;
	swap(v1, v2);
}

// Swap the contents of two containers.
//
// On [9-10], we create two [`std::vector`](cpp/container/vector)s,
// and fill them with values.
//
// On [12], we swap the contents of the two `std::vector`s using the
// [`std::swap_ranges`](cpp/algorithm/swap_ranges) algorithm, which
// is given the beginning and end iterators of one range and the
// beginning iterator of a second range and performs an
// element-by-element swap of their values (in this case, four swaps).
// The second range must have at least the number of elements in the
// first range. After this operation, iterators remain valid and point
// at the same container as they did previously.
//
// On [14], we use `std::vector`'s `swap` member function to swap the
// contents all in one shot. [!16-17] perform the same operation with
// the [generic swap pattern](/common-tasks/algorithms/swap-values.html).
// This approach is much faster than `std::swap_ranges`, as it simply
// swaps over the internal storage in constant time. It also does not
// require the containers to have the same size. However, after the
// operation, iterators will now point at the other container and
// past-the-end iterators are invalidated.
<|endoftext|>


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

#ifndef __PROCESS_EVENT_HPP__
#define __PROCESS_EVENT_HPP__

#include <memory> // TODO(benh): Replace shared_ptr with unique_ptr.

#include <process/future.hpp>
#include <process/http.hpp>
#include <process/message.hpp>
#include <process/socket.hpp>

#include <stout/abort.hpp>
#include <stout/json.hpp>
#include <stout/lambda.hpp>

namespace process {

// Forward declarations.
class ProcessBase;
struct MessageEvent;
struct DispatchEvent;
struct HttpEvent;
struct ExitedEvent;
struct TerminateEvent;

struct EventVisitor
{
  virtual ~EventVisitor() {}
  virtual void visit(const MessageEvent&) {}
  virtual void visit(const DispatchEvent&) {}
  virtual void visit(const HttpEvent&) {}
  virtual void visit(const ExitedEvent&) {}
  virtual void visit(const TerminateEvent&) {}
};

struct EventConsumer
{
  virtual ~EventConsumer() {}
  virtual void consume(MessageEvent&&) {}
  virtual void consume(DispatchEvent&&) {}
  virtual void consume(HttpEvent&&) {}
  virtual void consume(ExitedEvent&&) {}
  virtual void consume(TerminateEvent&&) {}
};

struct Event
{
  virtual ~Event() {}

  virtual void visit(EventVisitor* visitor) const = 0;
  virtual void consume(EventConsumer* consumer) && = 0;

  template <typename T>
  bool is() const
  {
    bool result = false;
    struct IsVisitor : EventVisitor
    {
      explicit IsVisitor(bool* _result) : result(_result) {}
      virtual void visit(const T&) { *result = true; }
      bool* result;
    } visitor(&result);
    visit(&visitor);
    return result;
  }

  template <typename T>
  const T& as() const
  {
    const T* result = nullptr;
    struct AsVisitor : EventVisitor
    {
      explicit AsVisitor(const T** _result) : result(_result) {}
      virtual void visit(const T& t) { *result = &t; }
      const T** result;
    } visitor(&result);
    visit(&visitor);
    if (result == nullptr) {
      ABORT("Attempting to \"cast\" event incorrectly!");
    }
    return *result;
  }

  // JSON representation for an Event.
  operator JSON::Object() const;
};

struct MessageEvent : Event
{
  explicit MessageEvent(Message&& _message)
    : message(std::move(_message)) {}

  MessageEvent(
      const UPID& from,
      const UPID& to,
      const std::string& name,
      const char* data,
      size_t length)
    : message{name, from, to, std::string(data, length)} {}

  MessageEvent(
      const UPID& from,
      const UPID& to,
      std::string&& name,
      std::string&& data)
    : message{std::move(name), from, to, std::move(data)} {}

  MessageEvent(MessageEvent&& that) = default;
  // TODO(dzhuk) Make it movable only, when move is properly supported in defer.
  MessageEvent(const MessageEvent& that) = default;
  MessageEvent& operator=(MessageEvent&&) = default;
  MessageEvent& operator=(const MessageEvent&) = delete;

  void visit(EventVisitor* visitor) const override
  {
    visitor->visit(*this);
  }

  void consume(EventConsumer* consumer) && override
  {
    consumer->consume(std::move(*this));
  }

  Message message;
};

struct HttpEvent : Event
{
  HttpEvent(
      http::Request* _request,
      Promise<http::Response>* _response)
    : request(_request),
      response(_response) {}

  HttpEvent(HttpEvent&&) = default;
  HttpEvent(const HttpEvent&) = delete;
  HttpEvent& operator=(HttpEvent&&) = default;
  HttpEvent& operator=(const HttpEvent&) = delete;

  virtual ~HttpEvent()
  {
    if (response) {
      // Fail the response in case it wasn't set.
      response->set(http::InternalServerError());
    }
  }

  void visit(EventVisitor* visitor) const override
  {
    visitor->visit(*this);
  }

  void consume(EventConsumer* consumer) && override
  {
    consumer->consume(std::move(*this));
  }

  std::unique_ptr<http::Request> request;
  std::unique_ptr<Promise<http::Response>> response;
};

struct DispatchEvent : Event
{
  DispatchEvent(
      const UPID& _pid,
      const std::shared_ptr<lambda::CallableOnce<void(ProcessBase*)>>& _f,
      const Option<const std::type_info*>& _functionType)
    : pid(_pid),
      f(_f),
      functionType(_functionType)
  {}

  DispatchEvent(DispatchEvent&&) = default;
  DispatchEvent(const DispatchEvent&) = delete;
  DispatchEvent& operator=(DispatchEvent&&) = default;
  DispatchEvent& operator=(const DispatchEvent&) = delete;

  void visit(EventVisitor* visitor) const override
  {
    visitor->visit(*this);
  }

  void consume(EventConsumer* consumer) && override
  {
    consumer->consume(std::move(*this));
  }

  // PID receiving the dispatch.
  UPID pid;

  // Function to get invoked as a result of this dispatch event.
  std::shared_ptr<lambda::CallableOnce<void(ProcessBase*)>> f;

  Option<const std::type_info*> functionType;
};

struct ExitedEvent : Event
{
  explicit ExitedEvent(const UPID& _pid)
    : pid(_pid) {}

  ExitedEvent(ExitedEvent&&) = default;
  // TODO(dzhuk) Make it movable only, when move is properly supported in defer.
  ExitedEvent(const ExitedEvent&) = default;
  ExitedEvent& operator=(ExitedEvent&&) = default;
  ExitedEvent& operator=(const ExitedEvent&) = delete;

  void visit(EventVisitor* visitor) const override
  {
    visitor->visit(*this);
  }

  void consume(EventConsumer* consumer) && override
  {
    consumer->consume(std::move(*this));
  }

  UPID pid;
};

struct TerminateEvent : Event
{
  TerminateEvent(const UPID& _from, bool _inject)
    : from(_from), inject(_inject) {}

  TerminateEvent(TerminateEvent&&) = default;
  TerminateEvent(const TerminateEvent&) = delete;
  TerminateEvent& operator=(TerminateEvent&&) = default;
  TerminateEvent& operator=(const TerminateEvent&) = delete;

  void visit(EventVisitor* visitor) const override
  {
    visitor->visit(*this);
  }

  void consume(EventConsumer* consumer) && override
  {
    consumer->consume(std::move(*this));
  }

  UPID from;
  bool inject;
};

inline Event::operator JSON::Object() const
{
  JSON::Object object;

  struct Visitor : EventVisitor
  {
    explicit Visitor(JSON::Object* _object) : object(_object) {}

    virtual void visit(const MessageEvent& event)
    {
      object->values["type"] = "MESSAGE";

      const Message& message = event.message;

      object->values["name"] = message.name;
      object->values["from"] = stringify(message.from);
      object->values["to"] = stringify(message.to);
      object->values["body"] = message.body;
    }

    virtual void visit(const HttpEvent& event)
    {
      object->values["type"] = "HTTP";

      const http::Request& request = *event.request;

      object->values["method"] = request.method;
      object->values["url"] = stringify(request.url);
    }

    virtual void visit(const DispatchEvent& event)
    {
      object->values["type"] = "DISPATCH";
    }

    virtual void visit(const ExitedEvent& event)
    {
      object->values["type"] = "EXITED";
    }

    virtual void visit(const TerminateEvent& event)
    {
      object->values["type"] = "TERMINATE";
    }

    JSON::Object* object;
  } visitor(&object);

  visit(&visitor);

  return object;
}

} // namespace process {

#endif // __PROCESS_EVENT_HPP__
<commit_msg>Made `Event` move-only in libprocess.<commit_after>// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License

#ifndef __PROCESS_EVENT_HPP__
#define __PROCESS_EVENT_HPP__

#include <memory> // TODO(benh): Replace shared_ptr with unique_ptr.

#include <process/future.hpp>
#include <process/http.hpp>
#include <process/message.hpp>
#include <process/socket.hpp>

#include <stout/abort.hpp>
#include <stout/json.hpp>
#include <stout/lambda.hpp>

namespace process {

// Forward declarations.
class ProcessBase;
struct MessageEvent;
struct DispatchEvent;
struct HttpEvent;
struct ExitedEvent;
struct TerminateEvent;

struct EventVisitor
{
  virtual ~EventVisitor() {}
  virtual void visit(const MessageEvent&) {}
  virtual void visit(const DispatchEvent&) {}
  virtual void visit(const HttpEvent&) {}
  virtual void visit(const ExitedEvent&) {}
  virtual void visit(const TerminateEvent&) {}
};

struct EventConsumer
{
  virtual ~EventConsumer() {}
  virtual void consume(MessageEvent&&) {}
  virtual void consume(DispatchEvent&&) {}
  virtual void consume(HttpEvent&&) {}
  virtual void consume(ExitedEvent&&) {}
  virtual void consume(TerminateEvent&&) {}
};

struct Event
{
  virtual ~Event() {}

  virtual void visit(EventVisitor* visitor) const = 0;
  virtual void consume(EventConsumer* consumer) && = 0;

  template <typename T>
  bool is() const
  {
    bool result = false;
    struct IsVisitor : EventVisitor
    {
      explicit IsVisitor(bool* _result) : result(_result) {}
      virtual void visit(const T&) { *result = true; }
      bool* result;
    } visitor(&result);
    visit(&visitor);
    return result;
  }

  template <typename T>
  const T& as() const
  {
    const T* result = nullptr;
    struct AsVisitor : EventVisitor
    {
      explicit AsVisitor(const T** _result) : result(_result) {}
      virtual void visit(const T& t) { *result = &t; }
      const T** result;
    } visitor(&result);
    visit(&visitor);
    if (result == nullptr) {
      ABORT("Attempting to \"cast\" event incorrectly!");
    }
    return *result;
  }

  // JSON representation for an Event.
  operator JSON::Object() const;
};

struct MessageEvent : Event
{
  explicit MessageEvent(Message&& _message)
    : message(std::move(_message)) {}

  MessageEvent(
      const UPID& from,
      const UPID& to,
      const std::string& name,
      const char* data,
      size_t length)
    : message{name, from, to, std::string(data, length)} {}

  MessageEvent(
      const UPID& from,
      const UPID& to,
      std::string&& name,
      std::string&& data)
    : message{std::move(name), from, to, std::move(data)} {}

  MessageEvent(MessageEvent&& that) = default;
  MessageEvent(const MessageEvent& that) = delete;
  MessageEvent& operator=(MessageEvent&&) = default;
  MessageEvent& operator=(const MessageEvent&) = delete;

  void visit(EventVisitor* visitor) const override
  {
    visitor->visit(*this);
  }

  void consume(EventConsumer* consumer) && override
  {
    consumer->consume(std::move(*this));
  }

  Message message;
};

struct HttpEvent : Event
{
  HttpEvent(
      http::Request* _request,
      Promise<http::Response>* _response)
    : request(_request),
      response(_response) {}

  HttpEvent(HttpEvent&&) = default;
  HttpEvent(const HttpEvent&) = delete;
  HttpEvent& operator=(HttpEvent&&) = default;
  HttpEvent& operator=(const HttpEvent&) = delete;

  virtual ~HttpEvent()
  {
    if (response) {
      // Fail the response in case it wasn't set.
      response->set(http::InternalServerError());
    }
  }

  void visit(EventVisitor* visitor) const override
  {
    visitor->visit(*this);
  }

  void consume(EventConsumer* consumer) && override
  {
    consumer->consume(std::move(*this));
  }

  std::unique_ptr<http::Request> request;
  std::unique_ptr<Promise<http::Response>> response;
};

struct DispatchEvent : Event
{
  DispatchEvent(
      const UPID& _pid,
      const std::shared_ptr<lambda::CallableOnce<void(ProcessBase*)>>& _f,
      const Option<const std::type_info*>& _functionType)
    : pid(_pid),
      f(_f),
      functionType(_functionType)
  {}

  DispatchEvent(DispatchEvent&&) = default;
  DispatchEvent(const DispatchEvent&) = delete;
  DispatchEvent& operator=(DispatchEvent&&) = default;
  DispatchEvent& operator=(const DispatchEvent&) = delete;

  void visit(EventVisitor* visitor) const override
  {
    visitor->visit(*this);
  }

  void consume(EventConsumer* consumer) && override
  {
    consumer->consume(std::move(*this));
  }

  // PID receiving the dispatch.
  UPID pid;

  // Function to get invoked as a result of this dispatch event.
  std::shared_ptr<lambda::CallableOnce<void(ProcessBase*)>> f;

  Option<const std::type_info*> functionType;
};

struct ExitedEvent : Event
{
  explicit ExitedEvent(const UPID& _pid)
    : pid(_pid) {}

  ExitedEvent(ExitedEvent&&) = default;
  ExitedEvent(const ExitedEvent&) = delete;
  ExitedEvent& operator=(ExitedEvent&&) = default;
  ExitedEvent& operator=(const ExitedEvent&) = delete;

  void visit(EventVisitor* visitor) const override
  {
    visitor->visit(*this);
  }

  void consume(EventConsumer* consumer) && override
  {
    consumer->consume(std::move(*this));
  }

  UPID pid;
};

struct TerminateEvent : Event
{
  TerminateEvent(const UPID& _from, bool _inject)
    : from(_from), inject(_inject) {}

  TerminateEvent(TerminateEvent&&) = default;
  TerminateEvent(const TerminateEvent&) = delete;
  TerminateEvent& operator=(TerminateEvent&&) = default;
  TerminateEvent& operator=(const TerminateEvent&) = delete;

  void visit(EventVisitor* visitor) const override
  {
    visitor->visit(*this);
  }

  void consume(EventConsumer* consumer) && override
  {
    consumer->consume(std::move(*this));
  }

  UPID from;
  bool inject;
};

inline Event::operator JSON::Object() const
{
  JSON::Object object;

  struct Visitor : EventVisitor
  {
    explicit Visitor(JSON::Object* _object) : object(_object) {}

    virtual void visit(const MessageEvent& event)
    {
      object->values["type"] = "MESSAGE";

      const Message& message = event.message;

      object->values["name"] = message.name;
      object->values["from"] = stringify(message.from);
      object->values["to"] = stringify(message.to);
      object->values["body"] = message.body;
    }

    virtual void visit(const HttpEvent& event)
    {
      object->values["type"] = "HTTP";

      const http::Request& request = *event.request;

      object->values["method"] = request.method;
      object->values["url"] = stringify(request.url);
    }

    virtual void visit(const DispatchEvent& event)
    {
      object->values["type"] = "DISPATCH";
    }

    virtual void visit(const ExitedEvent& event)
    {
      object->values["type"] = "EXITED";
    }

    virtual void visit(const TerminateEvent& event)
    {
      object->values["type"] = "TERMINATE";
    }

    JSON::Object* object;
  } visitor(&object);

  visit(&visitor);

  return object;
}

} // namespace process {

#endif // __PROCESS_EVENT_HPP__
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2004-2009  See the AUTHORS file for details.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 as published
 * by the Free Software Foundation.
 */

#include "znc.h"
#include "User.h"

struct reply {
	const char *szReply;
	bool bLastResponse;
};

// TODO this list is far from complete, no errors are handled
static const struct {
	const char *szRequest;
	struct reply vReplies[10];
} vRouteReplies[] = {
	{"WHO", {
		{"352", false},
		{"403", true}, // No such chan
		{"315", true},
		{NULL, true}
	}},
	{"LIST", {
		{"321", false},
		{"322", false},
		{"323", true},
		{NULL, true}
	}},
	{"NAMES", {
		{"353", false},
		{"366", true},
		{NULL, true},
	}},
	{"LUSERS", {
		{"251", false},
		{"252", false},
		{"253", false},
		{"254", false},
		{"255", false},
		{"265", false},
		{"266", true},
		// We don't handle 250 here since some IRCds don't sent it
		//{"250", true},
		{NULL, true}
	}},
	{"WHOIS", {
		{"311", false},
		{"319", false},
		{"312", false},
		// "<ip> :actually using host"
		{"338", false},
		{"318", true},
		// No such nick/channel
		{"401", true},
		// No such server
		{"402", true},
		{NULL, true}
	}},
	{"PING", {
		{"PONG", true},
		{NULL, true}
	}},
	{"USERHOST", {
		{"302", true},
		{NULL, true}
	}},
	{"TIME", {
		{"391", true},
		{NULL, true}
	}},
	{"WHOWAS", {
		{"312", false},
		{"314", false},
		{"369", true},
		{NULL, true}
	}},
	{"ISON", {
		{"303", true},
		{NULL, true}
	}},
	{"LINKS", {
		{"364", false},
		{"365", true},
		{NULL, true}
	}},
	{"MAP", {
		{"006", false},
		// inspircd
		{"270", false},
		// SilverLeo wants this two added
		{"015", false},
		{"017", true},
		{"007", true},
		{NULL, true}
	}},
	{"TRACE", {
		{"200", false},
		{"205", false},
		{"262", true},
		{NULL, true}
	}},
	{"USERS", {
		{"265", false},
		{"266", true},
		{NULL, true},
	}},
	// END (last item!)
	{NULL, {{NULL, true}}}
};

class CRouteTimeout : public CTimer {
public:
	CRouteTimeout(CModule* pModule, unsigned int uInterval, unsigned int uCycles,
			const CString& sLabel, const CString& sDescription)
		: CTimer(pModule, uInterval, uCycles, sLabel, sDescription) {}
	virtual ~CRouteTimeout() {}

protected:
	virtual void RunJob();
};

struct queued_req {
	CString sLine;
	const struct reply *reply;
};

typedef std::map<CClient *, std::vector<struct queued_req> > requestQueue;

class CRouteRepliesMod : public CModule
{
public:
	MODCONSTRUCTOR(CRouteRepliesMod)
	{
		m_pDoing = NULL;
		m_pReplies = NULL;
	}

	virtual ~CRouteRepliesMod() {
		requestQueue::iterator it;

		while (!m_vsPending.empty()) {
			it = m_vsPending.begin();

			while (!it->second.empty()) {
				PutIRC(it->second[0].sLine);
				it->second.erase(it->second.begin());
			}

			m_vsPending.erase(it);
		}
	}

	virtual void OnIRCConnected()
	{
		m_pDoing = NULL;
		m_pReplies = NULL;
		m_vsPending.clear();

		// No way we get a reply, so stop the timer (If it's running)
		RemTimer("RouteTimeout");
	}

	virtual void OnIRCDisconnected()
	{
		OnIRCConnected(); // Let's keep it in one place
	}

	virtual void OnClientDisconnect()
	{
		requestQueue::iterator it;

		if (m_pClient == m_pDoing) {
			// The replies which aren't received yet will be
			// broadcasted to everyone, but at least nothing breaks
			m_pDoing = NULL;
			m_pReplies = NULL;
		}

		it = m_vsPending.find(m_pClient);

		if (it == m_vsPending.end())
			return;

		m_vsPending.erase(it);
	}

	virtual EModRet OnRaw(CString& sLine)
	{
		CString sCmd = sLine.Token(1).AsUpper();
		size_t i = 0;

		if (!m_pReplies)
			return CONTINUE;

		// Is this a "not enough arguments" error?
		if (sCmd == "461") {
			// :server 461 nick WHO :Not enough parameters
			CString sOrigCmd = sLine.Token(3);

			if (m_sLastRequest.Token(0).Equals(sOrigCmd)) {
				// This is the reply to the last request
				if (RouteReply(sLine, true))
					return HALTCORE;
				return CONTINUE;
			}
		}

		while (m_pReplies[i].szReply != NULL) {
			if (m_pReplies[i].szReply == sCmd) {
				if (RouteReply(sLine, m_pReplies[i].bLastResponse))
					return HALTCORE;
				return CONTINUE;
			}
			i++;
		}

		// TODO HALTCORE is wrong, it should not be passed to
		// the clients, but the core itself should still handle it!

		return CONTINUE;
	}

	virtual EModRet OnUserRaw(CString& sLine)
	{
		CString sCmd = sLine.Token(0).AsUpper();
		size_t i = 0;

		if (!m_pUser->GetIRCSock())
			return CONTINUE;

		while (vRouteReplies[i].szRequest != NULL) {
			if (vRouteReplies[i].szRequest == sCmd) {

				struct queued_req req = {
					sLine, vRouteReplies[i].vReplies
				};
				m_vsPending[m_pClient].push_back(req);
				SendRequest();

				return HALTCORE;
			}
			i++;
		}

		return CONTINUE;
	}

	void Timeout()
	{
		// The timer will be deleted after this by the event loop

		PutModule("This module hit a timeout. This is a BUG!");

		PutModule("Last request: " + m_sLastRequest);

		PutModule("Expected replies: ");

		for (size_t i = 0; m_pReplies[i].szReply != NULL; i++) {
			if (m_pReplies[i].bLastResponse)
				PutModule(m_pReplies[i].szReply +
						CString(" (last)"));
			else
				PutModule(m_pReplies[i].szReply);
		}

		m_pDoing = NULL;
		m_pReplies = NULL;
		SendRequest();
	}

private:
	bool RouteReply(const CString& sLine, bool bFinished = false)
	{
		if (!m_pDoing)
			return false;

		m_pDoing->PutClient(sLine);

		if (bFinished) {
			// Stop the timeout
			RemTimer("RouteTimeout");

			m_pDoing = NULL;
			m_pReplies = NULL;
			SendRequest();
		}

		return true;
	}

	void SendRequest()
	{
		requestQueue::iterator it;

		if (m_pDoing || m_pReplies)
			return;

		if (m_vsPending.empty())
			return;

		it = m_vsPending.begin();

		if (it->second.empty()) {
			m_vsPending.erase(it);
			SendRequest();
			return;
		}

		// When we are called from the timer, we need to remove it.
		// We can't delete it (segfault on return), thus we
		// just stop it. The main loop will delete it.
		CTimer *pTimer = FindTimer("RouteTimeout");
		if (pTimer) {
			pTimer->Stop();
			UnlinkTimer(pTimer);
		}
		AddTimer(new CRouteTimeout(this, 20, 1, "RouteTimeout",
				"Recover from missing / wrong server replies"));

		m_pDoing = it->first;
		m_pReplies = it->second[0].reply;
		m_sLastRequest = it->second[0].sLine;
		PutIRC(it->second[0].sLine);
		it->second.erase(it->second.begin());
	}

	CClient	*m_pDoing;
	const struct reply	*m_pReplies;
	requestQueue	m_vsPending;
	// This field is only used for display purpose.
	CString		m_sLastRequest;
};

void CRouteTimeout::RunJob()
{
	CRouteRepliesMod *pMod = (CRouteRepliesMod *) m_pModule;
	pMod->Timeout();
}

MODULEDEFS(CRouteRepliesMod, "Send replies (e.g. to /who) to the right client only")
<commit_msg>route_replies: Handle 401 for /names<commit_after>/*
 * Copyright (C) 2004-2009  See the AUTHORS file for details.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 as published
 * by the Free Software Foundation.
 */

#include "znc.h"
#include "User.h"

struct reply {
	const char *szReply;
	bool bLastResponse;
};

// TODO this list is far from complete, no errors are handled
static const struct {
	const char *szRequest;
	struct reply vReplies[10];
} vRouteReplies[] = {
	{"WHO", {
		{"352", false},
		{"403", true}, // No such chan
		{"315", true},
		{NULL, true}
	}},
	{"LIST", {
		{"321", false},
		{"322", false},
		{"323", true},
		{NULL, true}
	}},
	{"NAMES", {
		{"353", false},
		{"366", true},
		// No such nick/channel
		{"401", true},
		{NULL, true},
	}},
	{"LUSERS", {
		{"251", false},
		{"252", false},
		{"253", false},
		{"254", false},
		{"255", false},
		{"265", false},
		{"266", true},
		// We don't handle 250 here since some IRCds don't sent it
		//{"250", true},
		{NULL, true}
	}},
	{"WHOIS", {
		{"311", false},
		{"319", false},
		{"312", false},
		// "<ip> :actually using host"
		{"338", false},
		{"318", true},
		// No such nick/channel
		{"401", true},
		// No such server
		{"402", true},
		{NULL, true}
	}},
	{"PING", {
		{"PONG", true},
		{NULL, true}
	}},
	{"USERHOST", {
		{"302", true},
		{NULL, true}
	}},
	{"TIME", {
		{"391", true},
		{NULL, true}
	}},
	{"WHOWAS", {
		{"312", false},
		{"314", false},
		{"369", true},
		{NULL, true}
	}},
	{"ISON", {
		{"303", true},
		{NULL, true}
	}},
	{"LINKS", {
		{"364", false},
		{"365", true},
		{NULL, true}
	}},
	{"MAP", {
		{"006", false},
		// inspircd
		{"270", false},
		// SilverLeo wants this two added
		{"015", false},
		{"017", true},
		{"007", true},
		{NULL, true}
	}},
	{"TRACE", {
		{"200", false},
		{"205", false},
		{"262", true},
		{NULL, true}
	}},
	{"USERS", {
		{"265", false},
		{"266", true},
		{NULL, true},
	}},
	// END (last item!)
	{NULL, {{NULL, true}}}
};

class CRouteTimeout : public CTimer {
public:
	CRouteTimeout(CModule* pModule, unsigned int uInterval, unsigned int uCycles,
			const CString& sLabel, const CString& sDescription)
		: CTimer(pModule, uInterval, uCycles, sLabel, sDescription) {}
	virtual ~CRouteTimeout() {}

protected:
	virtual void RunJob();
};

struct queued_req {
	CString sLine;
	const struct reply *reply;
};

typedef std::map<CClient *, std::vector<struct queued_req> > requestQueue;

class CRouteRepliesMod : public CModule
{
public:
	MODCONSTRUCTOR(CRouteRepliesMod)
	{
		m_pDoing = NULL;
		m_pReplies = NULL;
	}

	virtual ~CRouteRepliesMod() {
		requestQueue::iterator it;

		while (!m_vsPending.empty()) {
			it = m_vsPending.begin();

			while (!it->second.empty()) {
				PutIRC(it->second[0].sLine);
				it->second.erase(it->second.begin());
			}

			m_vsPending.erase(it);
		}
	}

	virtual void OnIRCConnected()
	{
		m_pDoing = NULL;
		m_pReplies = NULL;
		m_vsPending.clear();

		// No way we get a reply, so stop the timer (If it's running)
		RemTimer("RouteTimeout");
	}

	virtual void OnIRCDisconnected()
	{
		OnIRCConnected(); // Let's keep it in one place
	}

	virtual void OnClientDisconnect()
	{
		requestQueue::iterator it;

		if (m_pClient == m_pDoing) {
			// The replies which aren't received yet will be
			// broadcasted to everyone, but at least nothing breaks
			m_pDoing = NULL;
			m_pReplies = NULL;
		}

		it = m_vsPending.find(m_pClient);

		if (it == m_vsPending.end())
			return;

		m_vsPending.erase(it);
	}

	virtual EModRet OnRaw(CString& sLine)
	{
		CString sCmd = sLine.Token(1).AsUpper();
		size_t i = 0;

		if (!m_pReplies)
			return CONTINUE;

		// Is this a "not enough arguments" error?
		if (sCmd == "461") {
			// :server 461 nick WHO :Not enough parameters
			CString sOrigCmd = sLine.Token(3);

			if (m_sLastRequest.Token(0).Equals(sOrigCmd)) {
				// This is the reply to the last request
				if (RouteReply(sLine, true))
					return HALTCORE;
				return CONTINUE;
			}
		}

		while (m_pReplies[i].szReply != NULL) {
			if (m_pReplies[i].szReply == sCmd) {
				if (RouteReply(sLine, m_pReplies[i].bLastResponse))
					return HALTCORE;
				return CONTINUE;
			}
			i++;
		}

		// TODO HALTCORE is wrong, it should not be passed to
		// the clients, but the core itself should still handle it!

		return CONTINUE;
	}

	virtual EModRet OnUserRaw(CString& sLine)
	{
		CString sCmd = sLine.Token(0).AsUpper();
		size_t i = 0;

		if (!m_pUser->GetIRCSock())
			return CONTINUE;

		while (vRouteReplies[i].szRequest != NULL) {
			if (vRouteReplies[i].szRequest == sCmd) {

				struct queued_req req = {
					sLine, vRouteReplies[i].vReplies
				};
				m_vsPending[m_pClient].push_back(req);
				SendRequest();

				return HALTCORE;
			}
			i++;
		}

		return CONTINUE;
	}

	void Timeout()
	{
		// The timer will be deleted after this by the event loop

		PutModule("This module hit a timeout. This is a BUG!");

		PutModule("Last request: " + m_sLastRequest);

		PutModule("Expected replies: ");

		for (size_t i = 0; m_pReplies[i].szReply != NULL; i++) {
			if (m_pReplies[i].bLastResponse)
				PutModule(m_pReplies[i].szReply +
						CString(" (last)"));
			else
				PutModule(m_pReplies[i].szReply);
		}

		m_pDoing = NULL;
		m_pReplies = NULL;
		SendRequest();
	}

private:
	bool RouteReply(const CString& sLine, bool bFinished = false)
	{
		if (!m_pDoing)
			return false;

		m_pDoing->PutClient(sLine);

		if (bFinished) {
			// Stop the timeout
			RemTimer("RouteTimeout");

			m_pDoing = NULL;
			m_pReplies = NULL;
			SendRequest();
		}

		return true;
	}

	void SendRequest()
	{
		requestQueue::iterator it;

		if (m_pDoing || m_pReplies)
			return;

		if (m_vsPending.empty())
			return;

		it = m_vsPending.begin();

		if (it->second.empty()) {
			m_vsPending.erase(it);
			SendRequest();
			return;
		}

		// When we are called from the timer, we need to remove it.
		// We can't delete it (segfault on return), thus we
		// just stop it. The main loop will delete it.
		CTimer *pTimer = FindTimer("RouteTimeout");
		if (pTimer) {
			pTimer->Stop();
			UnlinkTimer(pTimer);
		}
		AddTimer(new CRouteTimeout(this, 20, 1, "RouteTimeout",
				"Recover from missing / wrong server replies"));

		m_pDoing = it->first;
		m_pReplies = it->second[0].reply;
		m_sLastRequest = it->second[0].sLine;
		PutIRC(it->second[0].sLine);
		it->second.erase(it->second.begin());
	}

	CClient	*m_pDoing;
	const struct reply	*m_pReplies;
	requestQueue	m_vsPending;
	// This field is only used for display purpose.
	CString		m_sLastRequest;
};

void CRouteTimeout::RunJob()
{
	CRouteRepliesMod *pMod = (CRouteRepliesMod *) m_pModule;
	pMod->Timeout();
}

MODULEDEFS(CRouteRepliesMod, "Send replies (e.g. to /who) to the right client only")
<|endoftext|>


<commit_before>#define CATCH_CONFIG_MAIN
#include <catch.hpp>

#include <cstring>
#include <string>

#include "../include/fixed_string.hpp"
#include "../include/tokenaizer.hpp"

TEST_CASE("fixed string test", "[basic_fixed_string]")
{
        using namespace fappy;

        constexpr auto max_size_ = 10;

        fixed_string_char<max_size_> str;

        REQUIRE(str.size() == 0);
        REQUIRE(str.max_size() == max_size_);

        SECTION("assign string shorter than max size")
        {
                const char* str__ = "gsomix";
                str               = str__;
                REQUIRE(str.size() == std::strlen(str__));
                REQUIRE(str.as_std_string() == std::string(str__));
        }
        SECTION("assign string larger than max size")
        {
                const char* str__ = "forneverbatmann";
                str               = str__;
                REQUIRE(str.size() == str.max_size());
                REQUIRE(str.as_std_string() == std::string(str__, str__ + 10));
        }
        SECTION("strip left")
        {
                const char* str__ = "   gsomix";
                str               = str__;
                str.strip_left();
                REQUIRE(str.as_std_string() == std::string("gsomix"));
        }
        SECTION("strip right")
        {
                const char* str__ = "gsomix   ";
                str               = str__;
                str.strip_right();
                REQUIRE(str.as_std_string() == std::string("gsomix"));
        }
        SECTION("trim")
        {
                const char* str__ = "  gsomix  ";
                str               = str__;
                str.trim();
                REQUIRE(str.as_std_string() == std::string("gsomix"));
        }

        SECTION("tokenaizer test")
        {
                tokenaizer<std::string>("Gsomix street.") tk;
                tk.tokenize();
                auto toks = tok.tokens();
                (void)tokens;
        }
}
<commit_msg>Fix test<commit_after>#define CATCH_CONFIG_MAIN
#include <catch.hpp>

#include <cstring>
#include <string>

#include "../include/fixed_string.hpp"
#include "../include/tokenaizer.hpp"

TEST_CASE("fixed string test", "[basic_fixed_string]")
{
        using namespace fappy;

        constexpr auto max_size_ = 10;

        fixed_string_char<max_size_> str;

        REQUIRE(str.size() == 0);
        REQUIRE(str.max_size() == max_size_);

        SECTION("assign string shorter than max size")
        {
                const char* str__ = "gsomix";
                str               = str__;
                REQUIRE(str.size() == std::strlen(str__));
                REQUIRE(str.as_std_string() == std::string(str__));
        }
        SECTION("assign string larger than max size")
        {
                const char* str__ = "forneverbatmann";
                str               = str__;
                REQUIRE(str.size() == str.max_size());
                REQUIRE(str.as_std_string() == std::string(str__, str__ + 10));
        }
        SECTION("strip left")
        {
                const char* str__ = "   gsomix";
                str               = str__;
                str.strip_left();
                REQUIRE(str.as_std_string() == std::string("gsomix"));
        }
        SECTION("strip right")
        {
                const char* str__ = "gsomix   ";
                str               = str__;
                str.strip_right();
                REQUIRE(str.as_std_string() == std::string("gsomix"));
        }
        SECTION("trim")
        {
                const char* str__ = "  gsomix  ";
                str               = str__;
                str.trim();
                REQUIRE(str.as_std_string() == std::string("gsomix"));
        }

        SECTION("tokenaizer test")
        {
                tokenaizer<std::string> tk("Gsomix street.");
                tk.tokenize();
                auto toks = tk.tokens();
                (void)toks;
        }
}
<|endoftext|>


<commit_before>/***********************************************
 * Author: Jun Jiang - jiangjun4@sina.com
 * Create: 2017-08-19 21:06
 * Last modified : 2017-08-30 13:43
 * Filename      : cnn.cpp
 * Description   :
 **********************************************/
#include <vector>
#include "cnn/CNN.h"
#include "cnn/Layer.h"
#include "utils/Log.h"
#include "utils/MnistHelper.h"

int main(int argc, char** argv){
    abcdl::utils::log::set_min_log_level(abcdl::utils::log::INFO);
    abcdl::utils::log::initialize_log(argc, argv);

    const std::string path = "./data/cnn.model";

    std::vector<abcdl::cnn::Layer*> layers;
    layers.push_back(new abcdl::cnn::InputLayer(28, 28));
    layers.push_back(new abcdl::cnn::ConvolutionLayer(3, 1, 5, new abcdl::framework::SigmoidActivateFunc()));
    layers.push_back(new abcdl::cnn::SubSamplingLayer(2, new abcdl::framework::MeanPooling()));
    layers.push_back(new abcdl::cnn::ConvolutionLayer(3, 1, 5, new abcdl::framework::SigmoidActivateFunc()));
//    layers.push_back(new abcdl::cnn::SubSamplingLayer(2, new abcdl::cnn::MeanPooling()));
    layers.push_back(new abcdl::cnn::OutputLayer(10, new abcdl::framework::SigmoidActivateFunc(), new abcdl::framework::CrossEntropyCost()));

    abcdl::cnn::CNN cnn;
    cnn.set_layers(layers);

    abcdl::utils::FashionMnistReader<real> helper("data");
    const size_t train_size = 60000;
    const size_t test_size  = 10000;

    abcdl::algebra::Mat train_data;
    helper.read_train_image(&train_data, train_size, 30);

    for(size_t i = 0; i != 20 && i != train_data.rows(); i++){
        ((abcdl::algebra::IMat)train_data.get_row(i)).reshape(28, 28).display("", false);
    }

    abcdl::algebra::Mat train_label;
    helper.read_train_vec_label(&train_label, train_size);

    abcdl::algebra::Mat test_data;
    helper.read_test_image(&test_data, test_size);

    abcdl::algebra::Mat test_label;
    helper.read_test_vec_label(&test_label, test_size);

    cnn.train(train_data, train_label, test_data, test_label);
}
<commit_msg>optimize matrix wrapper<commit_after>/***********************************************
 * Author: Jun Jiang - jiangjun4@sina.com
 * Create: 2017-08-19 21:06
 * Last modified : 2017-08-30 13:43
 * Filename      : cnn.cpp
 * Description   :
 **********************************************/
#include <vector>
#include "cnn/CNN.h"
#include "cnn/Layer.h"
#include "utils/Log.h"
#include "utils/MnistHelper.h"

int main(int argc, char** argv){
    abcdl::utils::log::set_min_log_level(abcdl::utils::log::INFO);
    abcdl::utils::log::initialize_log(argc, argv);

    const std::string path = "./data/cnn.model";

    std::vector<abcdl::cnn::Layer*> layers;
    layers.push_back(new abcdl::cnn::InputLayer(28, 28));
    layers.push_back(new abcdl::cnn::ConvolutionLayer(3, 1, 5, new abcdl::framework::SigmoidActivateFunc()));
    layers.push_back(new abcdl::cnn::SubSamplingLayer(2, new abcdl::framework::MeanPooling()));
    layers.push_back(new abcdl::cnn::ConvolutionLayer(3, 1, 5, new abcdl::framework::SigmoidActivateFunc()));
//    layers.push_back(new abcdl::cnn::SubSamplingLayer(2, new abcdl::cnn::MeanPooling()));
    layers.push_back(new abcdl::cnn::OutputLayer(10, new abcdl::framework::SigmoidActivateFunc(), new abcdl::framework::CrossEntropyCost()));

    abcdl::cnn::CNN cnn;
    cnn.set_layers(layers);

    abcdl::utils::FashionMnistReader<real> helper("data");
    const size_t train_size = 60000;
    const size_t test_size  = 10000;

    abcdl::algebra::MatSet train_data;
    helper.read_train_images(train_data, train_size, 30);

    for(size_t i = 0; i != 20 && i != train_data.rows(); i++){
        ((abcdl::algebra::IMat)train_data[i]).display("", false);
    }

    abcdl::algebra::MatSet train_label;
    helper.read_train_vec_labels(train_label, train_size);

    abcdl::algebra::MatSet test_data;
    helper.read_test_images(test_data, test_size);

    abcdl::algebra::MatSet test_label;
    helper.read_test_vec_labels(test_label, test_size);

    cnn.train(train_data, train_label, test_data, test_label);
}
<|endoftext|>