<commit_before>//------------------------------------------------------------------------------
// CLING - the C++ LLVM-based InterpreterG :)
// version: $Id$
// author:  Vassil Vassilev <vasil.georgiev.vasilev@cern.ch>
//------------------------------------------------------------------------------

#include "cling/Interpreter/ValuePrinter.h"

#include "cling/Interpreter/CValuePrinter.h"
#include "cling/Interpreter/ValuePrinterInfo.h"
#include "cling/Interpreter/StoredValueRef.h"
#include "cling/Interpreter/Value.h"

#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/Expr.h"
#include "clang/AST/Type.h"

#include "llvm/Support/raw_ostream.h"

#include <string>

using namespace cling;

// Implements the CValuePrinter interface.
extern "C" void cling_PrintValue(void* /*clang::Expr**/ E,
                      void* /*clang::ASTContext**/ C,
                      const void* value) {
  clang::Expr* Exp = (clang::Expr*)E;
  clang::ASTContext* Context = (clang::ASTContext*)C;
  ValuePrinterInfo VPI(Exp->getType(), Context);
  printValuePublic(llvm::outs(), value, value, VPI);

  flushOStream(llvm::outs());
}

static void StreamValue(llvm::raw_ostream& o, const void* const p,
                        const ValuePrinterInfo& VPI,
                        const char* Sep = "\n");

static void StreamChar(llvm::raw_ostream& o, const char v,
                       const char* Sep = "\n") {
  o << '"' << v << "\"" << Sep;
}

static void StreamCharPtr(llvm::raw_ostream& o, const char* const v,
                          const char* Sep = "\n") {
  if (!v) {
    o << "<<<NULL>>>" << Sep;
    return;
  }
  o << '"';
  const char* p = v;
  for (;*p && p - v < 128; ++p) {
    o << *p;
  }
  if (*p) o << "\"..." << Sep;
  else o << "\"" << Sep;
}

static void StreamRef(llvm::raw_ostream& o, const void* v,
                      const char* Sep = "\n") {
  o <<"&" << v << Sep;
}

static void StreamPtr(llvm::raw_ostream& o, const void* v,
                      const char* Sep = "\n") {
  o << v << Sep;
}

static void StreamArr(llvm::raw_ostream& o, const void* p,
                      const ValuePrinterInfo& VPI,
                      const char* Sep = "\n") {
  const clang::QualType& Ty = VPI.getType();
  clang::ASTContext& C = *VPI.getASTContext();
  const clang::ArrayType* ArrTy = Ty->getAsArrayTypeUnsafe();
  clang::QualType ElementTy = ArrTy->getElementType();
  if (ElementTy->isCharType())
    StreamCharPtr(o, (const char*)p);
  else if (Ty->isConstantArrayType()) {
    // Stream a constant array by streaming up to 5 elements.
    const clang::ConstantArrayType* CArrTy
      = C.getAsConstantArrayType(Ty);
    const llvm::APInt& APSize = CArrTy->getSize();
    size_t ElBytes = C.getTypeSize(ElementTy) / C.getCharWidth();
    size_t Size = (size_t)APSize.getZExtValue();
    o << "{ ";
    ValuePrinterInfo ElVPI(ElementTy, &C);
    for (size_t i = 0; i < Size; ++i) {
      StreamValue(o, ((const char*)p) + i * ElBytes, ElVPI, "");
      if (i + 1 < Size) {
        if (i == 4) {
          o << "...";
          break;
        }
        else o << ", ";
      }
    }
    o << " }" << Sep;
  } else
    StreamPtr(o, p, Sep);
}

static void StreamFunction(llvm::raw_ostream& o, const void* addr,
                           ValuePrinterInfo VPI, const char* Sep = "\n") {
  o << "Function @" << addr << '\n';

  const clang::DeclRefExpr* DeclRefExp
    = llvm::dyn_cast_or_null<clang::DeclRefExpr>(VPI.getExpr());
  const clang::FunctionDecl* FD
    = llvm::dyn_cast_or_null<clang::FunctionDecl>(DeclRefExp->getDecl());
  if (FD) {
    clang::SourceRange SRange = FD->getSourceRange();
    const char* cBegin = 0;
    const char* cEnd = 0;
    bool Invalid;
    if (SRange.isValid()) {
      clang::SourceManager& SM = VPI.getASTContext()->getSourceManager();
      clang::SourceLocation LocBegin = SRange.getBegin();
      LocBegin = SM.getExpansionRange(LocBegin).first;
      o << "  at " << SM.getFilename(LocBegin);
      unsigned LineNo = SM.getSpellingLineNumber(LocBegin, &Invalid);
      if (!Invalid)
        o << ':' << LineNo;
      o << ":\n";
      bool Invalid = false;
      cBegin = SM.getCharacterData(LocBegin, &Invalid);
      if (!Invalid) {
        clang::SourceLocation LocEnd = SRange.getEnd();
        LocEnd = SM.getExpansionRange(LocEnd).second;
        cEnd = SM.getCharacterData(LocEnd, &Invalid);
        if (Invalid)
          cBegin = 0;
      } else {
        cBegin = 0;
      }
    }
    if (cBegin && cEnd && cEnd > cBegin && cEnd - cBegin < 16 * 1024) {
      o << llvm::StringRef(cBegin, cEnd - cBegin + 1);
    } else {
      const clang::FunctionDecl* FDef;
      if (FD->hasBody(FDef))
        FD = FDef;
      FD->print(o);
      //const clang::FunctionDecl* FD
      //  = llvm::cast<const clang::FunctionType>(Ty)->getDecl();
    }
  } else {
    o << ":\n";
    // type-based printing:
    VPI.getType().print(o, VPI.getASTContext()->getPrintingPolicy());
  }
  // type-based print() never and decl-based print() sometimes does not include
  // a final newline:
  o << '\n';
}

static void StreamClingValue(llvm::raw_ostream& o, const Value* value,
                             clang::ASTContext& C, const char* Sep = "\n") {
  if (!value || !value->isValid()) {
    o << "<<<invalid>>> @" << value << Sep;
  } else {
    o << "boxes [";
    o << "("
      << value->type.getAsString(C.getPrintingPolicy())
      << ") ";
    clang::QualType valType = value->type.getDesugaredType(C);
    if (valType->isFloatingType())
      o << value->value.DoubleVal;
    else if (valType->isIntegerType())
      o << value->value.IntVal.getSExtValue();
    else if (valType->isBooleanType())
      o << value->value.IntVal.getBoolValue();
    else
      StreamValue(o, value->value.PointerVal,
                  ValuePrinterInfo(valType, &C), "");
    o << "]" << Sep;
  }
}

void cling::StreamStoredValueRef(llvm::raw_ostream& o, const StoredValueRef* VR,
                                 clang::ASTContext& C,
                                 const char* Sep /*= "\n"*/) {

  if (VR->isValid()) {
    StreamClingValue(o, &VR->get(), C, Sep);
  } else {
    o << "<<<invalid>>> @" << VR << Sep;
  }
}

static void StreamObj(llvm::raw_ostream& o, const void* v,
                      const ValuePrinterInfo& VPI,
                      const char* Sep = "\n") {
  const clang::Type* Ty = VPI.getType().getTypePtr();
  if (clang::CXXRecordDecl* CXXRD = Ty->getAsCXXRecordDecl()) {
    std::string QualName = CXXRD->getQualifiedNameAsString();
    if (QualName == "cling::StoredValueRef"){
      StreamStoredValueRef(o, (const StoredValueRef*)v,
                           *VPI.getASTContext(), Sep);
      return;
    } else if (QualName == "cling::Value") {
      StreamClingValue(o, (const Value*)v, *VPI.getASTContext(), Sep);
      return;
    }
  } // if CXXRecordDecl

  // TODO: Print the object members.
  o << "@" << v << Sep;
}

static void StreamValue(llvm::raw_ostream& o, const void* const p,
                        const ValuePrinterInfo& VPI,
                        const char* Sep /*= "\n"*/) {
  clang::ASTContext& C = *VPI.getASTContext();
  clang::QualType Ty = VPI.getType().getDesugaredType(C);
  if (const clang::BuiltinType *BT
           = llvm::dyn_cast<clang::BuiltinType>(Ty.getCanonicalType())) {
    switch (BT->getKind()) {
    case clang::BuiltinType::Bool:
      if (*(const bool*)p) o << "true" << Sep;
      else o << "false" << Sep; break;
    case clang::BuiltinType::Char_U:
    case clang::BuiltinType::UChar:
    case clang::BuiltinType::Char_S:
    case clang::BuiltinType::SChar:  StreamChar(o, *(const char*)p); break;
    case clang::BuiltinType::Short:  o << *(const short*)p << Sep; break;
    case clang::BuiltinType::UShort:
      o << *(const unsigned short*)p << Sep;
      break;
    case clang::BuiltinType::Int:    o << *(const int*)p << Sep; break;
    case clang::BuiltinType::UInt:
      o << *(const unsigned int*)p << Sep;
      break;
    case clang::BuiltinType::Long:   o << *(const long*)p << Sep; break;
    case clang::BuiltinType::ULong:
      o << *(const unsigned long*)p << Sep;
      break;
    case clang::BuiltinType::LongLong:
      o << *(const long long*)p << Sep;
      break;
    case clang::BuiltinType::ULongLong:
      o << *(const unsigned long long*)p << Sep;
      break;
    case clang::BuiltinType::Float:  o << *(const float*)p << Sep; break;
    case clang::BuiltinType::Double: o << *(const double*)p << Sep; break;
    default:
      StreamObj(o, p, ValuePrinterInfo(Ty, &C), Sep);
    }
  }
  else if (Ty.getAsString().compare("class std::basic_string<char>") == 0) {
    StreamObj(o, p, ValuePrinterInfo(Ty, &C), Sep);
    if (!Sep[0]) o << " "; // force a space
    o <<"c_str: ";
    StreamCharPtr(o, ((const char*) (*(const std::string*)p).c_str()), Sep);
  }
  else if (Ty->isEnumeralType()) {
    StreamObj(o, p, ValuePrinterInfo(Ty, &C), Sep);
    clang::EnumDecl* ED = Ty->getAs<clang::EnumType>()->getDecl();
    uint64_t value = *(const uint64_t*)p;
    bool IsFirst = true;
    llvm::APSInt ValAsAPSInt = C.MakeIntValue(value, Ty);
    for (clang::EnumDecl::enumerator_iterator I = ED->enumerator_begin(),
           E = ED->enumerator_end(); I != E; ++I) {
      if (I->getInitVal() == ValAsAPSInt) {
        if (!IsFirst) {
          o << " ? ";
        }
        o << "(" << I->getQualifiedNameAsString() << ")";
        IsFirst = false;
      }
    }
    o << " : (int) " << ValAsAPSInt.toString(/*Radix = */10) << Sep;
  }
  else if (Ty->isReferenceType())
    StreamRef(o, p, Sep);
  else if (Ty->isPointerType()) {
    clang::QualType PointeeTy = Ty->getPointeeType();
    if (PointeeTy->isCharType())
      StreamCharPtr(o, (const char*)p, Sep);
    else
      StreamPtr(o, p, Sep);
  }
  else if (Ty->isArrayType())
    StreamArr(o, p, ValuePrinterInfo(Ty, &C), Sep);
  else if (Ty->isFunctionType())
     StreamFunction(o, p, VPI, Sep);
  else
    StreamObj(o, p, ValuePrinterInfo(Ty, &C), Sep);
}

namespace cling {
  void printValuePublicDefault(llvm::raw_ostream& o, const void* const p,
                               const ValuePrinterInfo& VPI) {
    o << "(";
    o << VPI.getType().getAsString();
    o << ") ";
    StreamValue(o, p, VPI);
  }

  void flushOStream(llvm::raw_ostream& o) {
    o.flush();
  }

} // end namespace cling
<commit_msg>Check that the expression is indeed a DeclRefExpr.<commit_after>//------------------------------------------------------------------------------
// CLING - the C++ LLVM-based InterpreterG :)
// version: $Id$
// author:  Vassil Vassilev <vasil.georgiev.vasilev@cern.ch>
//------------------------------------------------------------------------------

#include "cling/Interpreter/ValuePrinter.h"

#include "cling/Interpreter/CValuePrinter.h"
#include "cling/Interpreter/ValuePrinterInfo.h"
#include "cling/Interpreter/StoredValueRef.h"
#include "cling/Interpreter/Value.h"

#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/Expr.h"
#include "clang/AST/Type.h"

#include "llvm/Support/raw_ostream.h"

#include <string>

using namespace cling;

// Implements the CValuePrinter interface.
extern "C" void cling_PrintValue(void* /*clang::Expr**/ E,
                      void* /*clang::ASTContext**/ C,
                      const void* value) {
  clang::Expr* Exp = (clang::Expr*)E;
  clang::ASTContext* Context = (clang::ASTContext*)C;
  ValuePrinterInfo VPI(Exp->getType(), Context);
  printValuePublic(llvm::outs(), value, value, VPI);

  flushOStream(llvm::outs());
}

static void StreamValue(llvm::raw_ostream& o, const void* const p,
                        const ValuePrinterInfo& VPI,
                        const char* Sep = "\n");

static void StreamChar(llvm::raw_ostream& o, const char v,
                       const char* Sep = "\n") {
  o << '"' << v << "\"" << Sep;
}

static void StreamCharPtr(llvm::raw_ostream& o, const char* const v,
                          const char* Sep = "\n") {
  if (!v) {
    o << "<<<NULL>>>" << Sep;
    return;
  }
  o << '"';
  const char* p = v;
  for (;*p && p - v < 128; ++p) {
    o << *p;
  }
  if (*p) o << "\"..." << Sep;
  else o << "\"" << Sep;
}

static void StreamRef(llvm::raw_ostream& o, const void* v,
                      const char* Sep = "\n") {
  o <<"&" << v << Sep;
}

static void StreamPtr(llvm::raw_ostream& o, const void* v,
                      const char* Sep = "\n") {
  o << v << Sep;
}

static void StreamArr(llvm::raw_ostream& o, const void* p,
                      const ValuePrinterInfo& VPI,
                      const char* Sep = "\n") {
  const clang::QualType& Ty = VPI.getType();
  clang::ASTContext& C = *VPI.getASTContext();
  const clang::ArrayType* ArrTy = Ty->getAsArrayTypeUnsafe();
  clang::QualType ElementTy = ArrTy->getElementType();
  if (ElementTy->isCharType())
    StreamCharPtr(o, (const char*)p);
  else if (Ty->isConstantArrayType()) {
    // Stream a constant array by streaming up to 5 elements.
    const clang::ConstantArrayType* CArrTy
      = C.getAsConstantArrayType(Ty);
    const llvm::APInt& APSize = CArrTy->getSize();
    size_t ElBytes = C.getTypeSize(ElementTy) / C.getCharWidth();
    size_t Size = (size_t)APSize.getZExtValue();
    o << "{ ";
    ValuePrinterInfo ElVPI(ElementTy, &C);
    for (size_t i = 0; i < Size; ++i) {
      StreamValue(o, ((const char*)p) + i * ElBytes, ElVPI, "");
      if (i + 1 < Size) {
        if (i == 4) {
          o << "...";
          break;
        }
        else o << ", ";
      }
    }
    o << " }" << Sep;
  } else
    StreamPtr(o, p, Sep);
}

static void StreamFunction(llvm::raw_ostream& o, const void* addr,
                           ValuePrinterInfo VPI, const char* Sep = "\n") {
  o << "Function @" << addr << '\n';

  const clang::DeclRefExpr* DeclRefExp
    = llvm::dyn_cast_or_null<clang::DeclRefExpr>(VPI.getExpr());
  const clang::FunctionDecl* FD = 0;
  if (DeclRefExp)
    FD = llvm::dyn_cast_or_null<clang::FunctionDecl>(DeclRefExp->getDecl());
  if (FD) {
    clang::SourceRange SRange = FD->getSourceRange();
    const char* cBegin = 0;
    const char* cEnd = 0;
    bool Invalid;
    if (SRange.isValid()) {
      clang::SourceManager& SM = VPI.getASTContext()->getSourceManager();
      clang::SourceLocation LocBegin = SRange.getBegin();
      LocBegin = SM.getExpansionRange(LocBegin).first;
      o << "  at " << SM.getFilename(LocBegin);
      unsigned LineNo = SM.getSpellingLineNumber(LocBegin, &Invalid);
      if (!Invalid)
        o << ':' << LineNo;
      o << ":\n";
      bool Invalid = false;
      cBegin = SM.getCharacterData(LocBegin, &Invalid);
      if (!Invalid) {
        clang::SourceLocation LocEnd = SRange.getEnd();
        LocEnd = SM.getExpansionRange(LocEnd).second;
        cEnd = SM.getCharacterData(LocEnd, &Invalid);
        if (Invalid)
          cBegin = 0;
      } else {
        cBegin = 0;
      }
    }
    if (cBegin && cEnd && cEnd > cBegin && cEnd - cBegin < 16 * 1024) {
      o << llvm::StringRef(cBegin, cEnd - cBegin + 1);
    } else {
      const clang::FunctionDecl* FDef;
      if (FD->hasBody(FDef))
        FD = FDef;
      FD->print(o);
      //const clang::FunctionDecl* FD
      //  = llvm::cast<const clang::FunctionType>(Ty)->getDecl();
    }
  } else {
    o << ":\n";
    // type-based printing:
    VPI.getType().print(o, VPI.getASTContext()->getPrintingPolicy());
  }
  // type-based print() never and decl-based print() sometimes does not include
  // a final newline:
  o << '\n';
}

static void StreamClingValue(llvm::raw_ostream& o, const Value* value,
                             clang::ASTContext& C, const char* Sep = "\n") {
  if (!value || !value->isValid()) {
    o << "<<<invalid>>> @" << value << Sep;
  } else {
    o << "boxes [";
    o << "("
      << value->type.getAsString(C.getPrintingPolicy())
      << ") ";
    clang::QualType valType = value->type.getDesugaredType(C);
    if (valType->isFloatingType())
      o << value->value.DoubleVal;
    else if (valType->isIntegerType())
      o << value->value.IntVal.getSExtValue();
    else if (valType->isBooleanType())
      o << value->value.IntVal.getBoolValue();
    else
      StreamValue(o, value->value.PointerVal,
                  ValuePrinterInfo(valType, &C), "");
    o << "]" << Sep;
  }
}

void cling::StreamStoredValueRef(llvm::raw_ostream& o, const StoredValueRef* VR,
                                 clang::ASTContext& C,
                                 const char* Sep /*= "\n"*/) {

  if (VR->isValid()) {
    StreamClingValue(o, &VR->get(), C, Sep);
  } else {
    o << "<<<invalid>>> @" << VR << Sep;
  }
}

static void StreamObj(llvm::raw_ostream& o, const void* v,
                      const ValuePrinterInfo& VPI,
                      const char* Sep = "\n") {
  const clang::Type* Ty = VPI.getType().getTypePtr();
  if (clang::CXXRecordDecl* CXXRD = Ty->getAsCXXRecordDecl()) {
    std::string QualName = CXXRD->getQualifiedNameAsString();
    if (QualName == "cling::StoredValueRef"){
      StreamStoredValueRef(o, (const StoredValueRef*)v,
                           *VPI.getASTContext(), Sep);
      return;
    } else if (QualName == "cling::Value") {
      StreamClingValue(o, (const Value*)v, *VPI.getASTContext(), Sep);
      return;
    }
  } // if CXXRecordDecl

  // TODO: Print the object members.
  o << "@" << v << Sep;
}

static void StreamValue(llvm::raw_ostream& o, const void* const p,
                        const ValuePrinterInfo& VPI,
                        const char* Sep /*= "\n"*/) {
  clang::ASTContext& C = *VPI.getASTContext();
  clang::QualType Ty = VPI.getType().getDesugaredType(C);
  if (const clang::BuiltinType *BT
           = llvm::dyn_cast<clang::BuiltinType>(Ty.getCanonicalType())) {
    switch (BT->getKind()) {
    case clang::BuiltinType::Bool:
      if (*(const bool*)p) o << "true" << Sep;
      else o << "false" << Sep; break;
    case clang::BuiltinType::Char_U:
    case clang::BuiltinType::UChar:
    case clang::BuiltinType::Char_S:
    case clang::BuiltinType::SChar:  StreamChar(o, *(const char*)p); break;
    case clang::BuiltinType::Short:  o << *(const short*)p << Sep; break;
    case clang::BuiltinType::UShort:
      o << *(const unsigned short*)p << Sep;
      break;
    case clang::BuiltinType::Int:    o << *(const int*)p << Sep; break;
    case clang::BuiltinType::UInt:
      o << *(const unsigned int*)p << Sep;
      break;
    case clang::BuiltinType::Long:   o << *(const long*)p << Sep; break;
    case clang::BuiltinType::ULong:
      o << *(const unsigned long*)p << Sep;
      break;
    case clang::BuiltinType::LongLong:
      o << *(const long long*)p << Sep;
      break;
    case clang::BuiltinType::ULongLong:
      o << *(const unsigned long long*)p << Sep;
      break;
    case clang::BuiltinType::Float:  o << *(const float*)p << Sep; break;
    case clang::BuiltinType::Double: o << *(const double*)p << Sep; break;
    default:
      StreamObj(o, p, ValuePrinterInfo(Ty, &C), Sep);
    }
  }
  else if (Ty.getAsString().compare("class std::basic_string<char>") == 0) {
    StreamObj(o, p, ValuePrinterInfo(Ty, &C), Sep);
    if (!Sep[0]) o << " "; // force a space
    o <<"c_str: ";
    StreamCharPtr(o, ((const char*) (*(const std::string*)p).c_str()), Sep);
  }
  else if (Ty->isEnumeralType()) {
    StreamObj(o, p, ValuePrinterInfo(Ty, &C), Sep);
    clang::EnumDecl* ED = Ty->getAs<clang::EnumType>()->getDecl();
    uint64_t value = *(const uint64_t*)p;
    bool IsFirst = true;
    llvm::APSInt ValAsAPSInt = C.MakeIntValue(value, Ty);
    for (clang::EnumDecl::enumerator_iterator I = ED->enumerator_begin(),
           E = ED->enumerator_end(); I != E; ++I) {
      if (I->getInitVal() == ValAsAPSInt) {
        if (!IsFirst) {
          o << " ? ";
        }
        o << "(" << I->getQualifiedNameAsString() << ")";
        IsFirst = false;
      }
    }
    o << " : (int) " << ValAsAPSInt.toString(/*Radix = */10) << Sep;
  }
  else if (Ty->isReferenceType())
    StreamRef(o, p, Sep);
  else if (Ty->isPointerType()) {
    clang::QualType PointeeTy = Ty->getPointeeType();
    if (PointeeTy->isCharType())
      StreamCharPtr(o, (const char*)p, Sep);
    else
      StreamPtr(o, p, Sep);
  }
  else if (Ty->isArrayType())
    StreamArr(o, p, ValuePrinterInfo(Ty, &C), Sep);
  else if (Ty->isFunctionType())
     StreamFunction(o, p, VPI, Sep);
  else
    StreamObj(o, p, ValuePrinterInfo(Ty, &C), Sep);
}

namespace cling {
  void printValuePublicDefault(llvm::raw_ostream& o, const void* const p,
                               const ValuePrinterInfo& VPI) {
    o << "(";
    o << VPI.getType().getAsString();
    o << ") ";
    StreamValue(o, p, VPI);
  }

  void flushOStream(llvm::raw_ostream& o) {
    o.flush();
  }

} // end namespace cling
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include <mfapi.h>
#include <mfidl.h>
#include <mferror.h>
#include <d3d9.h>
#include <evr9.h>
#include <mmdeviceapi.h>

int main(int, char**)
{
    return 0;
}
<commit_msg>Fix the config.tests for WMF backend.<commit_after>/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include <mfapi.h>
#include <mfidl.h>
#include <mferror.h>
#include <d3d9.h>
#include <evr9.h>
#include <mmdeviceapi.h>

int main(int, char**)
{
    HRESULT hr = MENonFatalError;
    if (SUCCEEDED(hr)) {
        return 1;
    }
    return 0;
}
<|endoftext|>


<commit_before>#include "sar.h"
#include <assert.h>
#include <cmath>

using namespace arma;

SAR::SAR(const colvec &y, const mat &X, const sp_mat &W) :
  y(y), W(W), X(X),
  IX(speye<sp_mat>(X.n_rows, X.n_rows) - X * pinv(X.t() * X) * X.t()),
  m(X.n_rows), n(X.n_cols) {}

SAR::~SAR() {}

const colvec &
SAR::get_beta(){
  return beta;
}

double
SAR::get_rho(){
  return rho;
}

double
SAR::get_sigma_sq(){
  return sigma_sq;
}

/* from: http://web.stanford.edu/class/ee364a/lectures/problems.pdf */
double
SAR::bisection(double l, double u, double tol) {
  assert(l < u);
  assert(tol > 0);

  double t, ll;
  do {
    t = (l + u) / 2;
    ll = rho_ll(t);
    if (! isnan(ll) && ! isinf(ll)){
      u = t;
    }
    else {
      l = t;
    }
  } while ((u - l) > tol);
  return t;
}

/* algo from: http://en.wikipedia.org/wiki/Golden_section_search */
double
SAR::golden_section_search(double a, double b, double c, double tol) {
  static const double phi = (1 + sqrt(5)) / 2;
  static const double resphi = 2 - phi;
  double x;
  if (c - b > b - a){
    x = b + resphi * (c - b);
  }
  else {
    x = b - resphi * (b - a);
  }
  if (abs(c - a) <= tol * (abs(b) + abs(x))){
    return (c + a) / 2;
  }

  double ll_x = rho_ll(x);
  double ll_b = rho_ll(b);
  assert(ll_x != ll_b);
  if (ll_x < ll_b) {
    if (c - b > b - a) {
      return golden_section_search(b, x, c, tol);
    }
    else {
      return golden_section_search(a, x, b, tol);
    }
  }
  else {
    if (c - b > b - a) {
      return golden_section_search(a, b, x, tol);
    }
    else {
      return golden_section_search(x, b, c, tol);
    }
  }
}

void
SAR::solve(){
  calculate_rho();
  const sp_mat A = speye<sp_mat>(W.n_rows, W.n_cols) - rho * W;
  const colvec A_y = A * y;
  if (! arma::solve(beta, X.t() * X, X.t() * A_y) || ! is_finite(beta)){
    beta = zeros<colvec>(X.n_cols);
  }
  const colvec IX_A_y = IX * A_y;
  sigma_sq = dot(IX_A_y, IX_A_y) / m;
}

void
SAR::get_bound(double &x, const double multiplier){
  double ll = rho_ll(x);
  while (isinf(ll) || isnan(ll)) {
    if (x == 0){
      x = .01;
    }
    else {
      x *= multiplier;
    }
    ll = rho_ll(x);
  }
}

void
SAR::calculate_rho(){
  double lower = 0, upper = 1 - datum::eps;
  get_bound(lower, 1.05);
  get_bound(upper, 0.95);

  double theta = 2 / (3 + sqrt(5));
  double avg = (1 - theta) * lower + theta * upper;
  rho = golden_section_search(lower, avg, upper);
}
<commit_msg>go faster<commit_after>#include "sar.h"
#include <assert.h>
#include <cmath>

using namespace arma;

SAR::SAR(const colvec &y, const mat &X, const sp_mat &W) :
  y(y), W(W), X(X),
  IX(speye<sp_mat>(X.n_rows, X.n_rows) - X * pinv(X.t() * X) * X.t()),
  m(X.n_rows), n(X.n_cols) {}

SAR::~SAR() {}

const colvec &
SAR::get_beta(){
  return beta;
}

double
SAR::get_rho(){
  return rho;
}

double
SAR::get_sigma_sq(){
  return sigma_sq;
}

/* from: http://web.stanford.edu/class/ee364a/lectures/problems.pdf */
double
SAR::bisection(double l, double u, double tol) {
  assert(l < u);
  assert(tol > 0);

  double t, ll;
  do {
    t = (l + u) / 2;
    ll = rho_ll(t);
    if (! isnan(ll) && ! isinf(ll)){
      u = t;
    }
    else {
      l = t;
    }
  } while ((u - l) > tol);
  return t;
}

/* algo from: http://en.wikipedia.org/wiki/Golden_section_search */
double
SAR::golden_section_search(double a, double b, double c, double tol) {
  static const double phi = (1 + sqrt(5)) / 2;
  static const double resphi = 2 - phi;
  double x;
  if (c - b > b - a){
    x = b + resphi * (c - b);
  }
  else {
    x = b - resphi * (b - a);
  }
  if (abs(c - a) <= tol * (abs(b) + abs(x))){
    return (c + a) / 2;
  }

  double ll_x = rho_ll(x);
  double ll_b = rho_ll(b);
  assert(ll_x != ll_b);
  if (ll_x < ll_b) {
    if (c - b > b - a) {
      return golden_section_search(b, x, c, tol);
    }
    else {
      return golden_section_search(a, x, b, tol);
    }
  }
  else {
    if (c - b > b - a) {
      return golden_section_search(a, b, x, tol);
    }
    else {
      return golden_section_search(x, b, c, tol);
    }
  }
}

void
SAR::solve(){
  calculate_rho();
  const sp_mat A = speye<sp_mat>(W.n_rows, W.n_cols) - rho * W;
  const colvec A_y = A * y;
  if (! arma::solve(beta, X.t() * X, X.t() * A_y) || ! is_finite(beta)){
    beta = zeros<colvec>(X.n_cols);
  }
  const colvec IX_A_y = IX * A_y;
  sigma_sq = dot(IX_A_y, IX_A_y) / m;
}

void
SAR::get_bound(double &x, const double multiplier){
  double ll = rho_ll(x);
  while (isinf(ll) || isnan(ll)) {
    if (x == 0){
      x = .01;
    }
    else {
      x *= multiplier;
    }
    ll = rho_ll(x);
  }
}

void
SAR::calculate_rho(){
  double lower = 0, upper = 1 - datum::eps;
  //get_bound(lower, 1.05);
  //get_bound(upper, 0.95);

  double theta = 2 / (3 + sqrt(5));
  double avg = (1 - theta) * lower + theta * upper;
  rho = golden_section_search(lower, avg, upper);
}
<|endoftext|>


<commit_before>/*
Copyright (c) 2016, Taiga Nomi
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the <organization> nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <iostream>
#include <vector>
#include "tiny_dnn/tiny_dnn.h"

using namespace tiny_dnn;
using namespace tiny_dnn::activation;
using namespace std;

template <typename N>
void construct_net(N &nn) {
  typedef convolutional_layer<activation::identity> conv;
  typedef max_pooling_layer<relu> pool;

  const serial_size_t n_fmaps = 32;  ///< number of feature maps for upper layer
  const serial_size_t n_fmaps2 =
    64;  ///< number of feature maps for lower layer
  const serial_size_t n_fc =
    64;  ///< number of hidden units in fully-connected layer

  nn << conv(32, 32, 5, 3, n_fmaps, padding::same) << pool(32, 32, n_fmaps, 2)
     << conv(16, 16, 5, n_fmaps, n_fmaps, padding::same)
     << pool(16, 16, n_fmaps, 2)
     << conv(8, 8, 5, n_fmaps, n_fmaps2, padding::same)
     << pool(8, 8, n_fmaps2, 2)
     << fully_connected_layer<activation::identity>(4 * 4 * n_fmaps2, n_fc)
     << fully_connected_layer<softmax>(n_fc, 10);
}

void train_cifar10(string data_dir_path, double learning_rate, ostream &log) {
  // specify loss-function and learning strategy
  network<sequential> nn;
  adam optimizer;

  construct_net(nn);

  log << "learning rate:" << learning_rate << endl;

  cout << "load models..." << endl;

  // load cifar dataset
  vector<label_t> train_labels, test_labels;
  vector<vec_t> train_images, test_images;

  for (int i = 1; i <= 5; i++) {
    parse_cifar10(data_dir_path + "/data_batch_" + to_string(i) + ".bin",
                  &train_images, &train_labels, -1.0, 1.0, 0, 0);
  }

  parse_cifar10(data_dir_path + "/test_batch.bin", &test_images, &test_labels,
                -1.0, 1.0, 0, 0);

  cout << "start learning" << endl;

  progress_display disp(train_images.size());
  timer t;
  const int n_minibatch    = 10;  ///< minibatch size
  const int n_train_epochs = 30;  ///< training duration

  optimizer.alpha *=
    static_cast<tiny_dnn::float_t>(sqrt(n_minibatch) * learning_rate);

  // create callback
  auto on_enumerate_epoch = [&]() {
    cout << t.elapsed() << "s elapsed." << endl;
    tiny_dnn::result res = nn.test(test_images, test_labels);
    log << res.num_success << "/" << res.num_total << endl;

    disp.restart(train_images.size());
    t.restart();
  };

  auto on_enumerate_minibatch = [&]() { disp += n_minibatch; };

  // training
  nn.train<cross_entropy>(optimizer, train_images, train_labels, n_minibatch,
                          n_train_epochs, on_enumerate_minibatch,
                          on_enumerate_epoch);

  cout << "end training." << endl;

  // test and show results
  nn.test(test_images, test_labels).print_detail(cout);

  // save networks
  ofstream ofs("cifar-weights");
  ofs << nn;
}

int main(int argc, char **argv) {
  if (argc != 3) {
    cerr << "Usage : " << argv[0] << "arg[0]: path_to_data (example:../data)"
         << "arg[1]: learning rate (example:0.01)" << endl;
    return -1;
  }
  train_cifar10(argv[1], stod(argv[2]), cout);
}
<commit_msg>Fixes example_cifar_train usage syntax (and to be consistent with other examples). (#565)<commit_after>/*
Copyright (c) 2016, Taiga Nomi
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the <organization> nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <iostream>
#include <vector>
#include "tiny_dnn/tiny_dnn.h"

using namespace tiny_dnn;
using namespace tiny_dnn::activation;
using namespace std;

template <typename N>
void construct_net(N &nn) {
  typedef convolutional_layer<activation::identity> conv;
  typedef max_pooling_layer<relu> pool;

  const serial_size_t n_fmaps = 32;  ///< number of feature maps for upper layer
  const serial_size_t n_fmaps2 =
    64;  ///< number of feature maps for lower layer
  const serial_size_t n_fc =
    64;  ///< number of hidden units in fully-connected layer

  nn << conv(32, 32, 5, 3, n_fmaps, padding::same) << pool(32, 32, n_fmaps, 2)
     << conv(16, 16, 5, n_fmaps, n_fmaps, padding::same)
     << pool(16, 16, n_fmaps, 2)
     << conv(8, 8, 5, n_fmaps, n_fmaps2, padding::same)
     << pool(8, 8, n_fmaps2, 2)
     << fully_connected_layer<activation::identity>(4 * 4 * n_fmaps2, n_fc)
     << fully_connected_layer<softmax>(n_fc, 10);
}

void train_cifar10(string data_dir_path, double learning_rate, ostream &log) {
  // specify loss-function and learning strategy
  network<sequential> nn;
  adam optimizer;

  construct_net(nn);

  log << "learning rate:" << learning_rate << endl;

  cout << "load models..." << endl;

  // load cifar dataset
  vector<label_t> train_labels, test_labels;
  vector<vec_t> train_images, test_images;

  for (int i = 1; i <= 5; i++) {
    parse_cifar10(data_dir_path + "/data_batch_" + to_string(i) + ".bin",
                  &train_images, &train_labels, -1.0, 1.0, 0, 0);
  }

  parse_cifar10(data_dir_path + "/test_batch.bin", &test_images, &test_labels,
                -1.0, 1.0, 0, 0);

  cout << "start learning" << endl;

  progress_display disp(train_images.size());
  timer t;
  const int n_minibatch    = 10;  ///< minibatch size
  const int n_train_epochs = 30;  ///< training duration

  optimizer.alpha *=
    static_cast<tiny_dnn::float_t>(sqrt(n_minibatch) * learning_rate);

  // create callback
  auto on_enumerate_epoch = [&]() {
    cout << t.elapsed() << "s elapsed." << endl;
    tiny_dnn::result res = nn.test(test_images, test_labels);
    log << res.num_success << "/" << res.num_total << endl;

    disp.restart(train_images.size());
    t.restart();
  };

  auto on_enumerate_minibatch = [&]() { disp += n_minibatch; };

  // training
  nn.train<cross_entropy>(optimizer, train_images, train_labels, n_minibatch,
                          n_train_epochs, on_enumerate_minibatch,
                          on_enumerate_epoch);

  cout << "end training." << endl;

  // test and show results
  nn.test(test_images, test_labels).print_detail(cout);

  // save networks
  ofstream ofs("cifar-weights");
  ofs << nn;
}

int main(int argc, char **argv) {
  if (argc != 3) {
    cerr << "Usage : " << argv[0] << " path_to_data (example:../data)"
         << " learning rate (example:0.01)" << endl;
    return -1;
  }
  train_cifar10(argv[1], stod(argv[2]), cout);
}
<|endoftext|>


<commit_before>///
/// @file t_GroupLabelLogger.cpp
/// @brief test getting frequent group labels
/// @author Jun Jiang <jun.jiang@izenesoft.com>
/// @date Created 2011-07-26
///

#include <mining-manager/group-label-logger/GroupLabelLogger.h>

#include <string>
#include <map>
#include <set>

#include <climits> // INT_MAX

#include <boost/test/unit_test.hpp>
#include <boost/filesystem.hpp>
#include <boost/filesystem/path.hpp>
#include <boost/random.hpp>
#include <boost/lexical_cast.hpp>

using namespace std;
using namespace boost;
using namespace sf1r;

namespace bfs = boost::filesystem;

namespace
{
const char* TEST_DIR_STR = "group_label_log_test";
const char* PROP_NAME_STR = "CATEGORY";

class LogChecker
{
private:
    // param "query" of GroupLabelLogger::logLabel()
    boost::mt19937 engine_;
    boost::uniform_int<> queryDistribution_;
    boost::variate_generator<mt19937, uniform_int<> > queryRandom_;

    // param "propValue" of GroupLabelLogger::logLabel()
    boost::mt11213b groupEngine_;
    boost::uniform_int<> groupDistribution_;
    boost::variate_generator<mt11213b, uniform_int<> > groupRandom_;

    // param "limit" of GroupLabelLogger::getFreqLabel()
    boost::uniform_int<> limitDistribution_;
    boost::variate_generator<mt19937, uniform_int<> > limitRandom_;

    typedef map<string, int> GroupCountMap;
    typedef map<string, GroupCountMap> QueryGroupMap;
    QueryGroupMap queryGroupMap_;

private:
    void checkGroup_(
        int limit,
        const std::vector<std::string>& propValueVec,
        const std::vector<int>& freqVec,
        const GroupCountMap& groupCountMap
    )
    {
        //cout << "checkGroup_(), limit: " << limit
             //<< ", propValueVec.size(): " << propValueVec.size();
        //for (size_t i=0; i<propValueVec.size(); ++i)
        //{
            //cout << ", (" << propValueVec[i] << ", " << freqVec[i] << ")";
        //}
        //cout << endl;

        BOOST_CHECK_EQUAL(propValueVec.size(), freqVec.size());
        BOOST_CHECK_LE(propValueVec.size(), limit);
        BOOST_CHECK_GT(propValueVec.size(), 0);

        set<string> checkedSet;
        int maxFreq = INT_MAX;
        for (size_t i=0; i<propValueVec.size(); ++i)
        {
            const string& groupStr = propValueVec[i];
            const int freqValue = freqVec[i];

            // freq value
            GroupCountMap::const_iterator findIt = groupCountMap.find(groupStr);
            BOOST_CHECK(findIt != groupCountMap.end());
            BOOST_CHECK_EQUAL(freqValue, findIt->second);

            // not inserted before
            BOOST_CHECK(checkedSet.insert(groupStr).second);

            // decreasing freq
            BOOST_CHECK_LE(freqValue, maxFreq);
            maxFreq = freqValue;
        }

        // check rest <= maxFreq
        for (GroupCountMap::const_iterator mapIt = groupCountMap.begin();
            mapIt != groupCountMap.end(); ++mapIt)
        {
            if (checkedSet.find(mapIt->first) == checkedSet.end())
            {
                BOOST_CHECK_LE(mapIt->second, maxFreq);
            }
        }
    }

public:
    LogChecker(int queryLimit, int groupLimit)
        : queryDistribution_(1, queryLimit)
        , queryRandom_(engine_, queryDistribution_)
        , groupDistribution_(1, groupLimit)
        , groupRandom_(groupEngine_, groupDistribution_)
        , limitDistribution_(1, groupLimit * 10)
        , limitRandom_(engine_, limitDistribution_)
    {
    }

    void createLog(GroupLabelLogger& logger, int logNum)
    {
        string query;
        string group;

        for (int i=0; i<logNum; ++i)
        {
            query = "query_" + lexical_cast<string>(queryRandom_());
            group = "group_" + lexical_cast<string>(groupRandom_());

            //cout << "create log: " << query << ", " << group << endl;

            ++queryGroupMap_[query][group];
            BOOST_CHECK(logger.logLabel(query, group));
        }
    }

    void checkLog(GroupLabelLogger& logger)
    {
        for (QueryGroupMap::const_iterator queryIt = queryGroupMap_.begin();
            queryIt != queryGroupMap_.end(); ++queryIt)
        {
            const string& query = queryIt->first;
            const GroupCountMap& groupCountMap = queryIt->second;

            int limit = limitRandom_();
            // in 80% test, "limit" value would be 1,
            // as it's used most frequently
            if (limit > limitDistribution_.max() * 0.2)
            {
                limit = 1;
            }
            std::vector<std::string> propValueVec;
            std::vector<int> freqVec;
            BOOST_CHECK(logger.getFreqLabel(query, limit, propValueVec, freqVec));

            //cout << "check query: " << query << endl;
            checkGroup_(limit, propValueVec, freqVec, groupCountMap);
        }
    }
};

}

BOOST_AUTO_TEST_SUITE(GroupLabelLogger_test)

BOOST_AUTO_TEST_CASE(getFreqLabel)
{
    bfs::remove_all(TEST_DIR_STR);
    bfs::create_directory(TEST_DIR_STR);

    LogChecker logChecker(100, 10); // query range, group range
    const int LOG_NUM = 10000; // log number

    {
        GroupLabelLogger logger(TEST_DIR_STR, PROP_NAME_STR);
        BOOST_CHECK(logger.open());

        BOOST_TEST_MESSAGE("check empty log");
        logChecker.checkLog(logger);

        BOOST_TEST_MESSAGE("create log 1st time");
        logChecker.createLog(logger, LOG_NUM);
        logChecker.checkLog(logger);
    }

    {
        GroupLabelLogger logger(TEST_DIR_STR, PROP_NAME_STR);
        BOOST_CHECK(logger.open());

        BOOST_TEST_MESSAGE("check loaded log");
        logChecker.checkLog(logger);

        BOOST_TEST_MESSAGE("create log 2nd time");
        logChecker.createLog(logger, LOG_NUM);
        logChecker.checkLog(logger);
    }
}

BOOST_AUTO_TEST_SUITE_END()
<commit_msg>add test case for GroupLabelLogger::setTopLabel() into t_GroupLabelLogger.cpp<commit_after>///
/// @file t_GroupLabelLogger.cpp
/// @brief test getting frequent group labels
/// @author Jun Jiang <jun.jiang@izenesoft.com>
/// @date Created 2011-07-26
///

#include <mining-manager/group-label-logger/GroupLabelLogger.h>

#include <string>
#include <map>
#include <set>

#include <climits> // INT_MAX

#include <boost/test/unit_test.hpp>
#include <boost/filesystem.hpp>
#include <boost/filesystem/path.hpp>
#include <boost/random.hpp>
#include <boost/lexical_cast.hpp>

using namespace std;
using namespace boost;
using namespace sf1r;

namespace bfs = boost::filesystem;

namespace
{
const char* TEST_DIR_STR = "group_label_log_test";
const char* PROP_NAME_STR = "CATEGORY";

class LogChecker
{
private:
    // param "query" of GroupLabelLogger::logLabel()
    boost::mt19937 engine_;
    boost::uniform_int<> queryDistribution_;
    boost::variate_generator<mt19937, uniform_int<> > queryRandom_;

    // param "propValue" of GroupLabelLogger::logLabel()
    boost::mt11213b groupEngine_;
    boost::uniform_int<> groupDistribution_;
    boost::variate_generator<mt11213b, uniform_int<> > groupRandom_;

    // param "limit" of GroupLabelLogger::getFreqLabel()
    boost::uniform_int<> limitDistribution_;
    boost::variate_generator<mt19937, uniform_int<> > limitRandom_;

    typedef map<string, int> GroupCountMap;
    struct GroupCounter
    {
        GroupCountMap countMap_;
        string manualTop_;
    };

    typedef map<string, GroupCounter> QueryGroupMap;
    QueryGroupMap queryGroupMap_;

private:
    void checkGroup_(
        int limit,
        const std::vector<std::string>& propValueVec,
        const std::vector<int>& freqVec,
        const GroupCounter& groupCounter
    )
    {
        //cout << "checkGroup_(), limit: " << limit
             //<< ", propValueVec.size(): " << propValueVec.size();
        //for (size_t i=0; i<propValueVec.size(); ++i)
        //{
            //cout << ", (" << propValueVec[i] << ", " << freqVec[i] << ")";
        //}
        //cout << endl;

        BOOST_CHECK_EQUAL(propValueVec.size(), freqVec.size());
        BOOST_CHECK_LE(propValueVec.size(), limit);
        BOOST_CHECK_GT(propValueVec.size(), 0);

        const GroupCountMap& groupCountMap = groupCounter.countMap_;
        set<string> checkedSet;
        size_t i = 0;
        if (groupCounter.manualTop_.empty() == false)
        {
            const string& groupStr = groupCounter.manualTop_;
            BOOST_CHECK_EQUAL(propValueVec[0], groupStr);

            GroupCountMap::const_iterator findIt = groupCountMap.find(groupStr);
            BOOST_CHECK_EQUAL(freqVec[0], (findIt != groupCountMap.end()) ? findIt->second : 0);

            BOOST_CHECK(checkedSet.insert(groupStr).second);

            ++i;
        }

        int maxFreq = INT_MAX;
        for (; i<propValueVec.size(); ++i)
        {
            const string& groupStr = propValueVec[i];
            const int freqValue = freqVec[i];

            // freq value
            GroupCountMap::const_iterator findIt = groupCountMap.find(groupStr);
            BOOST_CHECK(findIt != groupCountMap.end());
            BOOST_CHECK_EQUAL(freqValue, findIt->second);

            // not inserted before
            BOOST_CHECK(checkedSet.insert(groupStr).second);

            // decreasing freq
            BOOST_CHECK_LE(freqValue, maxFreq);
            maxFreq = freqValue;
        }

        // check rest <= maxFreq
        for (GroupCountMap::const_iterator mapIt = groupCountMap.begin();
            mapIt != groupCountMap.end(); ++mapIt)
        {
            if (checkedSet.find(mapIt->first) == checkedSet.end())
            {
                BOOST_CHECK_LE(mapIt->second, maxFreq);
            }
        }
    }

public:
    LogChecker(int queryLimit, int groupLimit)
        : queryDistribution_(1, queryLimit)
        , queryRandom_(engine_, queryDistribution_)
        , groupDistribution_(1, groupLimit)
        , groupRandom_(groupEngine_, groupDistribution_)
        , limitDistribution_(1, groupLimit * 10)
        , limitRandom_(engine_, limitDistribution_)
    {
    }

    void createLog(GroupLabelLogger& logger, int logNum)
    {
        string query;
        string group;

        for (int i=0; i<logNum; ++i)
        {
            query = "query_" + lexical_cast<string>(queryRandom_());
            group = "group_" + lexical_cast<string>(groupRandom_());

            //cout << "create log: " << query << ", " << group << endl;

            ++queryGroupMap_[query].countMap_[group];
            BOOST_CHECK(logger.logLabel(query, group));
        }
    }

    void setTopLabel(GroupLabelLogger& logger, int topNum)
    {
        for (int i=0; i<topNum; ++i)
        {
            string query = "query_" + lexical_cast<string>(queryRandom_());
            string group;

            // in 50% test, "group" would be empty to reset the top label
            if (i % 2 == 0)
            {
                group = "group_" + lexical_cast<string>(groupRandom_());
            }

            //cout << "set top label: " << query << ", " << group << endl;

            queryGroupMap_[query].manualTop_ = group;
            BOOST_CHECK(logger.setTopLabel(query, group));
        }
    }

    void checkLog(GroupLabelLogger& logger)
    {
        for (QueryGroupMap::const_iterator queryIt = queryGroupMap_.begin();
            queryIt != queryGroupMap_.end(); ++queryIt)
        {
            const string& query = queryIt->first;
            const GroupCounter& groupCounter = queryIt->second;

            int limit = limitRandom_();
            // in 80% test, "limit" value would be 1,
            // as it's used most frequently
            if (limit > limitDistribution_.max() * 0.2)
            {
                limit = 1;
            }
            std::vector<std::string> propValueVec;
            std::vector<int> freqVec;
            BOOST_CHECK(logger.getFreqLabel(query, limit, propValueVec, freqVec));

            //cout << "check query: " << query << endl;
            checkGroup_(limit, propValueVec, freqVec, groupCounter);
        }
    }
};

}

BOOST_AUTO_TEST_SUITE(GroupLabelLogger_test)

BOOST_AUTO_TEST_CASE(getFreqLabel)
{
    bfs::remove_all(TEST_DIR_STR);
    bfs::create_directory(TEST_DIR_STR);

    LogChecker logChecker(100, 10); // query range, group range
    const int LOG_NUM = 10000; // log number
    const int TOP_NUM = 1000; // set top label number

    {
        GroupLabelLogger logger(TEST_DIR_STR, PROP_NAME_STR);
        BOOST_CHECK(logger.open());

        BOOST_TEST_MESSAGE("check empty log");
        logChecker.checkLog(logger);

        BOOST_TEST_MESSAGE("create log 1st time");
        logChecker.createLog(logger, LOG_NUM);
        logChecker.setTopLabel(logger, TOP_NUM);
        logChecker.checkLog(logger);
    }

    {
        GroupLabelLogger logger(TEST_DIR_STR, PROP_NAME_STR);
        BOOST_CHECK(logger.open());

        BOOST_TEST_MESSAGE("check loaded log");
        logChecker.checkLog(logger);

        BOOST_TEST_MESSAGE("create log 2nd time");
        logChecker.createLog(logger, LOG_NUM);
        logChecker.setTopLabel(logger, TOP_NUM);
        logChecker.checkLog(logger);
    }
}

BOOST_AUTO_TEST_SUITE_END()
<|endoftext|>


<commit_before>/*
 * Software License Agreement (BSD License)
 *
 *  Point Cloud Library (PCL) - www.pointclouds.org
 *  Copyright (c) 2009-2012, Willow Garage, Inc.
 *  Copyright (c) 2012-, Open Perception, Inc.
 *  Copyright (c) 2014, RadiantBlue Technologies, Inc.
 *
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above
 *     copyright notice, this list of conditions and the following
 *     disclaimer in the documentation and/or other materials provided
 *     with the distribution.
 *   * Neither the name of the copyright holder(s) nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *  POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef PCL_SEGMENTATION_APPROXIMATE_PROGRESSIVE_MORPHOLOGICAL_FILTER_HPP_
#define PCL_SEGMENTATION_APPROXIMATE_PROGRESSIVE_MORPHOLOGICAL_FILTER_HPP_

#include <pcl/common/common.h>
#include <pcl/common/io.h>
#include <pcl/filters/morphological_filter.h>
#include <pcl/filters/extract_indices.h>
#include <pcl/segmentation/approximate_progressive_morphological_filter.h>
#include <pcl/point_cloud.h>
#include <pcl/point_types.h>

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointT>
pcl::ApproximateProgressiveMorphologicalFilter<PointT>::ApproximateProgressiveMorphologicalFilter () :
  max_window_size_ (33),
  slope_ (0.7f),
  max_distance_ (10.0f),
  initial_distance_ (0.15f),
  cell_size_ (1.0f),
  base_ (2.0f),
  exponential_ (true),
  threads_ (0)
{
}

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointT>
pcl::ApproximateProgressiveMorphologicalFilter<PointT>::~ApproximateProgressiveMorphologicalFilter ()
{
}

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointT> void
pcl::ApproximateProgressiveMorphologicalFilter<PointT>::extract (std::vector<int>& ground)
{
  bool segmentation_is_possible = initCompute ();
  if (!segmentation_is_possible)
  {
    deinitCompute ();
    return;
  }

  // Compute the series of window sizes and height thresholds
  std::vector<float> height_thresholds;
  std::vector<float> window_sizes;
  std::vector<int> half_sizes;
  int iteration = 0;
  int half_size = 0.0f;
  float window_size = 0.0f;
  float height_threshold = 0.0f;

  while (window_size < max_window_size_)
  {
    // Determine the initial window size.
    if (exponential_)
      half_size = static_cast<int> (std::pow (static_cast<float> (base_), iteration));
    else
      half_size = (iteration+1) * base_;

    window_size = 2 * half_size + 1;

    // Calculate the height threshold to be used in the next iteration.
    if (iteration == 0)
      height_threshold = initial_distance_;
    else
      height_threshold = slope_ * (window_size - window_sizes[iteration-1]) * cell_size_ + initial_distance_;

    // Enforce max distance on height threshold
    if (height_threshold > max_distance_)
      height_threshold = max_distance_;

    half_sizes.push_back (half_size);
    window_sizes.push_back (window_size);
    height_thresholds.push_back (height_threshold);

    iteration++;
  }

  // setup grid based on scale and extents
  Eigen::Vector4f global_max, global_min;
  pcl::getMinMax3D<PointT> (*input_, global_min, global_max);

  float xextent = global_max.x () - global_min.x ();
  float yextent = global_max.y () - global_min.y ();

  int rows = static_cast<int> (std::floor (yextent / cell_size_) + 1);
  int cols = static_cast<int> (std::floor (xextent / cell_size_) + 1);

  Eigen::MatrixXf A (rows, cols);
  A.setConstant (std::numeric_limits<float>::quiet_NaN ());

  Eigen::MatrixXf Z (rows, cols);
  Z.setConstant (std::numeric_limits<float>::quiet_NaN ());

  Eigen::MatrixXf Zf (rows, cols);
  Zf.setConstant (std::numeric_limits<float>::quiet_NaN ());

#ifdef _OPENMP
#pragma omp parallel for num_threads(threads_)
#endif
  for (int i = 0; i < (int)input_->points.size (); ++i)
  {
    // ...then test for lower points within the cell
    PointT p = input_->points[i];
    int row = std::floor(p.y - global_min.y ());
    int col = std::floor(p.x - global_min.x ());

    if (p.z < A (row, col) || pcl_isnan (A (row, col)))
    {
      A (row, col) = p.z;
    }
  }

  // Ground indices are initially limited to those points in the input cloud we
  // wish to process
  ground = *indices_;

  // Progressively filter ground returns using morphological open
  for (size_t i = 0; i < window_sizes.size (); ++i)
  {
    PCL_DEBUG ("      Iteration %d (height threshold = %f, window size = %f, half size = %d)...",
               i, height_thresholds[i], window_sizes[i], half_sizes[i]);

    // Limit filtering to those points currently considered ground returns
    typename pcl::PointCloud<PointT>::Ptr cloud (new pcl::PointCloud<PointT>);
    pcl::copyPointCloud<PointT> (*input_, ground, *cloud);

    // Apply the morphological opening operation at the current window size.
#ifdef _OPENMP
#pragma omp parallel for num_threads(threads_)
#endif
    for (int row = 0; row < rows; ++row)
    {
      int rs, re;
      rs = ((row - half_sizes[i]) < 0) ? 0 : row - half_sizes[i];
      re = ((row + half_sizes[i]) > (rows-1)) ? (rows-1) : row + half_sizes[i];

      for (int col = 0; col < cols; ++col)
      {
        int cs, ce;
        cs = ((col - half_sizes[i]) < 0) ? 0 : col - half_sizes[i];
        ce = ((col + half_sizes[i]) > (cols-1)) ? (cols-1) : col + half_sizes[i];

        float min_coeff = std::numeric_limits<float>::max ();

        for (int j = rs; j < (re + 1); ++j)
        {
          for (int k = cs; k < (ce + 1); ++k)
          {
            if (A (j, k) != std::numeric_limits<float>::quiet_NaN ())
            {
              if (A (j, k) < min_coeff)
                min_coeff = A (j, k);
            }
          }
        }

        if (min_coeff != std::numeric_limits<float>::max ())
          Z(row, col) = min_coeff;
      }
    }

#ifdef _OPENMP
#pragma omp parallel for num_threads(threads_)
#endif
    for (int row = 0; row < rows; ++row)
    {
      int rs, re;
      rs = ((row - half_sizes[i]) < 0) ? 0 : row - half_sizes[i];
      re = ((row + half_sizes[i]) > (rows-1)) ? (rows-1) : row + half_sizes[i];

      for (int col = 0; col < cols; ++col)
      {
        int cs, ce;
        cs = ((col - half_sizes[i]) < 0) ? 0 : col - half_sizes[i];
        ce = ((col + half_sizes[i]) > (cols-1)) ? (cols-1) : col + half_sizes[i];

        float max_coeff = -std::numeric_limits<float>::max ();

        for (int j = rs; j < (re + 1); ++j)
        {
          for (int k = cs; k < (ce + 1); ++k)
          {
            if (Z (j, k) != std::numeric_limits<float>::quiet_NaN ())
            {
              if (Z (j, k) > max_coeff)
                max_coeff = Z (j, k);
            }
          }
        }

        if (max_coeff != -std::numeric_limits<float>::max ())
          Zf (row, col) = max_coeff;
      }
    }

    // Find indices of the points whose difference between the source and
    // filtered point clouds is less than the current height threshold.
    std::vector<int> pt_indices;
    for (size_t p_idx = 0; p_idx < ground.size (); ++p_idx)
    {
      PointT p = cloud->points[p_idx];
      int erow = static_cast<int> (std::floor ((p.y - global_min.y ()) / cell_size_));
      int ecol = static_cast<int> (std::floor ((p.x - global_min.x ()) / cell_size_));

      float diff = p.z - Zf (erow, ecol);
      if (diff < height_thresholds[i])
        pt_indices.push_back (ground[p_idx]);
    }

    A.swap (Zf);

    // Ground is now limited to pt_indices
    ground.swap (pt_indices);

    PCL_DEBUG ("ground now has %d points\n", ground.size ());
  }

  deinitCompute ();
}

#define PCL_INSTANTIATE_ApproximateProgressiveMorphologicalFilter(T) template class pcl::ApproximateProgressiveMorphologicalFilter<T>;

#endif    // PCL_SEGMENTATION_APPROXIMATE_PROGRESSIVE_MORPHOLOGICAL_FILTER_HPP_

<commit_msg>Update approximate_progressive_morphological_filter.hpp<commit_after>/*
 * Software License Agreement (BSD License)
 *
 *  Point Cloud Library (PCL) - www.pointclouds.org
 *  Copyright (c) 2009-2012, Willow Garage, Inc.
 *  Copyright (c) 2012-, Open Perception, Inc.
 *  Copyright (c) 2014, RadiantBlue Technologies, Inc.
 *
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above
 *     copyright notice, this list of conditions and the following
 *     disclaimer in the documentation and/or other materials provided
 *     with the distribution.
 *   * Neither the name of the copyright holder(s) nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *  POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef PCL_SEGMENTATION_APPROXIMATE_PROGRESSIVE_MORPHOLOGICAL_FILTER_HPP_
#define PCL_SEGMENTATION_APPROXIMATE_PROGRESSIVE_MORPHOLOGICAL_FILTER_HPP_

#include <pcl/common/common.h>
#include <pcl/common/io.h>
#include <pcl/filters/morphological_filter.h>
#include <pcl/filters/extract_indices.h>
#include <pcl/segmentation/approximate_progressive_morphological_filter.h>
#include <pcl/point_cloud.h>
#include <pcl/point_types.h>

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointT>
pcl::ApproximateProgressiveMorphologicalFilter<PointT>::ApproximateProgressiveMorphologicalFilter () :
  max_window_size_ (33),
  slope_ (0.7f),
  max_distance_ (10.0f),
  initial_distance_ (0.15f),
  cell_size_ (1.0f),
  base_ (2.0f),
  exponential_ (true),
  threads_ (0)
{
}

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointT>
pcl::ApproximateProgressiveMorphologicalFilter<PointT>::~ApproximateProgressiveMorphologicalFilter ()
{
}

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointT> void
pcl::ApproximateProgressiveMorphologicalFilter<PointT>::extract (std::vector<int>& ground)
{
  bool segmentation_is_possible = initCompute ();
  if (!segmentation_is_possible)
  {
    deinitCompute ();
    return;
  }

  // Compute the series of window sizes and height thresholds
  std::vector<float> height_thresholds;
  std::vector<float> window_sizes;
  std::vector<int> half_sizes;
  int iteration = 0;
  int half_size = 0.0f;
  float window_size = 0.0f;
  float height_threshold = 0.0f;

  while (window_size < max_window_size_)
  {
    // Determine the initial window size.
    if (exponential_)
      half_size = static_cast<int> (std::pow (static_cast<float> (base_), iteration));
    else
      half_size = (iteration+1) * base_;

    window_size = 2 * half_size + 1;

    // Calculate the height threshold to be used in the next iteration.
    if (iteration == 0)
      height_threshold = initial_distance_;
    else
      height_threshold = slope_ * (window_size - window_sizes[iteration-1]) * cell_size_ + initial_distance_;

    // Enforce max distance on height threshold
    if (height_threshold > max_distance_)
      height_threshold = max_distance_;

    half_sizes.push_back (half_size);
    window_sizes.push_back (window_size);
    height_thresholds.push_back (height_threshold);

    iteration++;
  }

  // setup grid based on scale and extents
  Eigen::Vector4f global_max, global_min;
  pcl::getMinMax3D<PointT> (*input_, global_min, global_max);

  float xextent = global_max.x () - global_min.x ();
  float yextent = global_max.y () - global_min.y ();

  int rows = static_cast<int> (std::floor (yextent / cell_size_) + 1);
  int cols = static_cast<int> (std::floor (xextent / cell_size_) + 1);

  Eigen::MatrixXf A (rows, cols);
  A.setConstant (std::numeric_limits<float>::quiet_NaN ());

  Eigen::MatrixXf Z (rows, cols);
  Z.setConstant (std::numeric_limits<float>::quiet_NaN ());

  Eigen::MatrixXf Zf (rows, cols);
  Zf.setConstant (std::numeric_limits<float>::quiet_NaN ());

#ifdef _OPENMP
#pragma omp parallel for num_threads(threads_)
#endif
  for (int i = 0; i < (int)input_->points.size (); ++i)
  {
    // ...then test for lower points within the cell
    PointT p = input_->points[i];
    int row = std::floor((p.y - global_min.y ()) / cell_size_);
    int col = std::floor((p.x - global_min.x ()) / cell_size_);

    if (p.z < A (row, col) || pcl_isnan (A (row, col)))
    {
      A (row, col) = p.z;
    }
  }

  // Ground indices are initially limited to those points in the input cloud we
  // wish to process
  ground = *indices_;

  // Progressively filter ground returns using morphological open
  for (size_t i = 0; i < window_sizes.size (); ++i)
  {
    PCL_DEBUG ("      Iteration %d (height threshold = %f, window size = %f, half size = %d)...",
               i, height_thresholds[i], window_sizes[i], half_sizes[i]);

    // Limit filtering to those points currently considered ground returns
    typename pcl::PointCloud<PointT>::Ptr cloud (new pcl::PointCloud<PointT>);
    pcl::copyPointCloud<PointT> (*input_, ground, *cloud);

    // Apply the morphological opening operation at the current window size.
#ifdef _OPENMP
#pragma omp parallel for num_threads(threads_)
#endif
    for (int row = 0; row < rows; ++row)
    {
      int rs, re;
      rs = ((row - half_sizes[i]) < 0) ? 0 : row - half_sizes[i];
      re = ((row + half_sizes[i]) > (rows-1)) ? (rows-1) : row + half_sizes[i];

      for (int col = 0; col < cols; ++col)
      {
        int cs, ce;
        cs = ((col - half_sizes[i]) < 0) ? 0 : col - half_sizes[i];
        ce = ((col + half_sizes[i]) > (cols-1)) ? (cols-1) : col + half_sizes[i];

        float min_coeff = std::numeric_limits<float>::max ();

        for (int j = rs; j < (re + 1); ++j)
        {
          for (int k = cs; k < (ce + 1); ++k)
          {
            if (A (j, k) != std::numeric_limits<float>::quiet_NaN ())
            {
              if (A (j, k) < min_coeff)
                min_coeff = A (j, k);
            }
          }
        }

        if (min_coeff != std::numeric_limits<float>::max ())
          Z(row, col) = min_coeff;
      }
    }

#ifdef _OPENMP
#pragma omp parallel for num_threads(threads_)
#endif
    for (int row = 0; row < rows; ++row)
    {
      int rs, re;
      rs = ((row - half_sizes[i]) < 0) ? 0 : row - half_sizes[i];
      re = ((row + half_sizes[i]) > (rows-1)) ? (rows-1) : row + half_sizes[i];

      for (int col = 0; col < cols; ++col)
      {
        int cs, ce;
        cs = ((col - half_sizes[i]) < 0) ? 0 : col - half_sizes[i];
        ce = ((col + half_sizes[i]) > (cols-1)) ? (cols-1) : col + half_sizes[i];

        float max_coeff = -std::numeric_limits<float>::max ();

        for (int j = rs; j < (re + 1); ++j)
        {
          for (int k = cs; k < (ce + 1); ++k)
          {
            if (Z (j, k) != std::numeric_limits<float>::quiet_NaN ())
            {
              if (Z (j, k) > max_coeff)
                max_coeff = Z (j, k);
            }
          }
        }

        if (max_coeff != -std::numeric_limits<float>::max ())
          Zf (row, col) = max_coeff;
      }
    }

    // Find indices of the points whose difference between the source and
    // filtered point clouds is less than the current height threshold.
    std::vector<int> pt_indices;
    for (size_t p_idx = 0; p_idx < ground.size (); ++p_idx)
    {
      PointT p = cloud->points[p_idx];
      int erow = static_cast<int> (std::floor ((p.y - global_min.y ()) / cell_size_));
      int ecol = static_cast<int> (std::floor ((p.x - global_min.x ()) / cell_size_));

      float diff = p.z - Zf (erow, ecol);
      if (diff < height_thresholds[i])
        pt_indices.push_back (ground[p_idx]);
    }

    A.swap (Zf);

    // Ground is now limited to pt_indices
    ground.swap (pt_indices);

    PCL_DEBUG ("ground now has %d points\n", ground.size ());
  }

  deinitCompute ();
}

#define PCL_INSTANTIATE_ApproximateProgressiveMorphologicalFilter(T) template class pcl::ApproximateProgressiveMorphologicalFilter<T>;

#endif    // PCL_SEGMENTATION_APPROXIMATE_PROGRESSIVE_MORPHOLOGICAL_FILTER_HPP_

<|endoftext|>


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

#include "cc/dual_net/batching_dual_net.h"

#include <queue>
#include <string>
#include <thread>
#include <vector>

#include "absl/container/flat_hash_map.h"
#include "absl/memory/memory.h"
#include "absl/synchronization/mutex.h"
#include "cc/dual_net/dual_net.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"

namespace minigo {
namespace {

class WaitingDualNet;
class WaitingDualNetFactory;

struct EvaluatedBatch {
  EvaluatedBatch() = default;
  EvaluatedBatch(std::string model_path, size_t size)
      : model_path(std::move(model_path)), size(size) {}
  std::string model_path;
  size_t size = 0;
};

// Why doesn't absl have this already?
class Semaphore {
 public:
  void Post() {
    absl::MutexLock lock(&mutex_);
    ++count_;
    cond_var_.Signal();
  }

  void Wait() {
    absl::MutexLock lock(&mutex_);
    while (count_ == 0) {
      cond_var_.Wait(&mutex_);
    }
    --count_;
  }

 private:
  absl::Mutex mutex_;
  absl::CondVar cond_var_;
  int count_ = 0;
};

// DualNet implementation whos RunMany method blocks until Notify is called.
// This is used in tests where multiple BatchingDualNet clients are running in
// parallel and we want to control the evaluation order of the implementation
// models.
// WaitingDualNet also records each RunMany call with its factory.
class WaitingDualNet : public DualNet {
 public:
  WaitingDualNet(WaitingDualNetFactory* factory, std::string model);

  // Blocks until Notify is called.
  // Each call pushes an EvaluatedBatch instance onto the factory's queue
  // containing the model name and size of the batch.
  void RunMany(std::vector<const BoardFeatures*> features,
               std::vector<Output*> outputs, std::string* model) override;

  // Allows one call to RunMany to complete.
  // Blocks until the executed RunMany call completes.
  void Notify();

 private:
  Semaphore before_;
  Semaphore after_;
  WaitingDualNetFactory* factory_;
  std::string model_;
};

class WaitingDualNetFactory : public DualNetFactory {
 public:
  explicit WaitingDualNetFactory(int buffer_count);

  int GetBufferCount() const override;
  std::unique_ptr<DualNet> NewDualNet(const std::string& model_path) override;

  // Notifies the batcher for the given model_path, so that it can run a single
  // batch of inferences.
  // CHECK fails if batches_ is empty.
  // CHECK fails if the front element in the batches_ queue doesn't match the
  // given model_path or expected_batch_size.
  void FlushBatch(const std::string& model_path, size_t expected_batch_size);

  // Called by WaitingDualNet::RunMany.
  void PushEvaluatedBatch(const std::string& model, size_t size);

 private:
  const int buffer_count_;
  mutable absl::Mutex mutex_;
  absl::flat_hash_map<std::string, WaitingDualNet*> models_ GUARDED_BY(&mutex_);
  std::queue<EvaluatedBatch> batches_ GUARDED_BY(&mutex_);
};

WaitingDualNet::WaitingDualNet(WaitingDualNetFactory* factory,
                               std::string model)
    : factory_(factory), model_(std::move(model)) {}

void WaitingDualNet::RunMany(std::vector<const BoardFeatures*> features,
                             std::vector<Output*> outputs, std::string* model) {
  before_.Wait();
  factory_->PushEvaluatedBatch(model_, features.size());
  if (model != nullptr) {
    *model = model_;
  }
  after_.Post();
}

void WaitingDualNet::Notify() {
  before_.Post();
  after_.Wait();
}

WaitingDualNetFactory::WaitingDualNetFactory(int buffer_count)
    : buffer_count_(buffer_count) {}

int WaitingDualNetFactory::GetBufferCount() const { return buffer_count_; }

std::unique_ptr<DualNet> WaitingDualNetFactory::NewDualNet(
    const std::string& model_path) {
  absl::MutexLock lock(&mutex_);
  auto model = absl::make_unique<WaitingDualNet>(this, model_path);
  MG_CHECK(models_.emplace(model_path, model.get()).second);
  return model;
}

void WaitingDualNetFactory::FlushBatch(const std::string& model_path,
                                       size_t expected_batch_size) {
  // Find the model for the given model_path.
  WaitingDualNet* model;
  {
    absl::MutexLock lock(&mutex_);
    auto it = models_.find(model_path);
    MG_CHECK(it != models_.end());
    model = it->second;
  }

  // Notify it, letting it run a single batch.
  model->Notify();

  // The model should now have pushed a batch on to the batches_ queue: pop it
  // off or die trying.
  EvaluatedBatch batch;
  {
    absl::MutexLock lock(&mutex_);
    MG_CHECK(!batches_.empty());
    batch = std::move(batches_.front());
    batches_.pop();
  }

  // Check the popped batch matches the expected batch.
  MG_CHECK(batch.model_path == model_path);
  MG_CHECK(batch.size == expected_batch_size);
}

void WaitingDualNetFactory::PushEvaluatedBatch(const std::string& model,
                                               size_t size) {
  absl::MutexLock lock(&mutex_);
  batches_.emplace(model, size);
}

class BatchingDualNetTest : public ::testing::Test {
 protected:
  void InitFactory(int buffer_count) {
    auto impl = absl::make_unique<WaitingDualNetFactory>(buffer_count);
    waiting_factory_ = impl.get();
    batching_factory_ = NewBatchingDualNetFactory(std::move(impl));
  }

  std::unique_ptr<DualNet> NewDualNet(const std::string& model_path) {
    return batching_factory_->NewDualNet(model_path);
  }

  void StartGame(DualNet* black, DualNet* white) {
    batching_factory_->StartGame(black, white);
  }

  void EndGame(DualNet* black, DualNet* white) {
    batching_factory_->EndGame(black, white);
  }

  void FlushBatch(const std::string& model_path, size_t expected_batch_size) {
    waiting_factory_->FlushBatch(model_path, expected_batch_size);
  }

 private:
  // Owned by batching_factory_.
  WaitingDualNetFactory* waiting_factory_ = nullptr;
  std::unique_ptr<DualNetFactory> batching_factory_;
};

TEST_F(BatchingDualNetTest, SelfPlay) {
  constexpr int kNumGames = 6;

  struct Game {
    DualNet::BoardFeatures features;
    DualNet::Output output;
    std::unique_ptr<DualNet> model;
    std::thread thread;
  };

  // Test single, double and triple buffering.
  for (int buffer_count = 1; buffer_count <= 3; ++buffer_count) {
    InitFactory(buffer_count);
    int expected_batch_size = kNumGames / buffer_count;

    std::vector<Game> games;
    for (int i = 0; i < kNumGames; ++i) {
      Game game;
      game.model = NewDualNet("a");
      StartGame(game.model.get(), game.model.get());
      games.push_back(std::move(game));
    }

    for (auto& game : games) {
      game.thread = std::thread([this, &game] {
        game.model->RunMany({&game.features}, {&game.output}, nullptr);
      });
    }

    for (int i = 0; i < kNumGames / expected_batch_size; ++i) {
      FlushBatch("a", expected_batch_size);
    }

    for (auto& game : games) {
      EndGame(game.model.get(), game.model.get());
      game.thread.join();
    }
  }
}

TEST_F(BatchingDualNetTest, EvalDoubleBuffer) {
  constexpr int kNumGames = 6;

  struct Game {
    DualNet::BoardFeatures features;
    DualNet::Output output;
    std::unique_ptr<DualNet> black;
    std::unique_ptr<DualNet> white;
    std::thread thread;
  };

  // Test single, double and triple buffering.
  for (int buffer_count = 1; buffer_count <= 3; ++buffer_count) {
    InitFactory(buffer_count);
    int expected_batch_size = kNumGames / buffer_count;

    std::vector<Game> games;
    for (int i = 0; i < kNumGames; ++i) {
      Game game;
      game.black = NewDualNet("black");
      game.white = NewDualNet("white");
      StartGame(game.black.get(), game.white.get());
      games.push_back(std::move(game));
    }

    for (auto& game : games) {
      game.thread = std::thread([this, &game] {
        game.black->RunMany({&game.features}, {&game.output}, nullptr);
        game.white->RunMany({&game.features}, {&game.output}, nullptr);
      });
    }

    for (int i = 0; i < kNumGames / expected_batch_size; ++i) {
      FlushBatch("black", expected_batch_size);
      FlushBatch("white", expected_batch_size);
    }

    for (auto& game : games) {
      EndGame(game.black.get(), game.black.get());
      game.thread.join();
    }
  }
}
}  // namespace
}  // namespace minigo
<commit_msg>fix typo<commit_after>// Copyright 2018 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "cc/dual_net/batching_dual_net.h"

#include <queue>
#include <string>
#include <thread>
#include <vector>

#include "absl/container/flat_hash_map.h"
#include "absl/memory/memory.h"
#include "absl/synchronization/mutex.h"
#include "cc/dual_net/dual_net.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"

namespace minigo {
namespace {

class WaitingDualNet;
class WaitingDualNetFactory;

struct EvaluatedBatch {
  EvaluatedBatch() = default;
  EvaluatedBatch(std::string model_path, size_t size)
      : model_path(std::move(model_path)), size(size) {}
  std::string model_path;
  size_t size = 0;
};

// Why doesn't absl have this already?
class Semaphore {
 public:
  void Post() {
    absl::MutexLock lock(&mutex_);
    ++count_;
    cond_var_.Signal();
  }

  void Wait() {
    absl::MutexLock lock(&mutex_);
    while (count_ == 0) {
      cond_var_.Wait(&mutex_);
    }
    --count_;
  }

 private:
  absl::Mutex mutex_;
  absl::CondVar cond_var_;
  int count_ = 0;
};

// DualNet implementation whose RunMany method blocks until Notify is called.
// This is used in tests where multiple BatchingDualNet clients are running in
// parallel and we want to control the evaluation order of the implementation
// models.
// WaitingDualNet also records each RunMany call with its factory.
class WaitingDualNet : public DualNet {
 public:
  WaitingDualNet(WaitingDualNetFactory* factory, std::string model);

  // Blocks until Notify is called.
  // Each call pushes an EvaluatedBatch instance onto the factory's queue
  // containing the model name and size of the batch.
  void RunMany(std::vector<const BoardFeatures*> features,
               std::vector<Output*> outputs, std::string* model) override;

  // Allows one call to RunMany to complete.
  // Blocks until the executed RunMany call completes.
  void Notify();

 private:
  Semaphore before_;
  Semaphore after_;
  WaitingDualNetFactory* factory_;
  std::string model_;
};

class WaitingDualNetFactory : public DualNetFactory {
 public:
  explicit WaitingDualNetFactory(int buffer_count);

  int GetBufferCount() const override;
  std::unique_ptr<DualNet> NewDualNet(const std::string& model_path) override;

  // Notifies the batcher for the given model_path, so that it can run a single
  // batch of inferences.
  // CHECK fails if batches_ is empty.
  // CHECK fails if the front element in the batches_ queue doesn't match the
  // given model_path or expected_batch_size.
  void FlushBatch(const std::string& model_path, size_t expected_batch_size);

  // Called by WaitingDualNet::RunMany.
  void PushEvaluatedBatch(const std::string& model, size_t size);

 private:
  const int buffer_count_;
  mutable absl::Mutex mutex_;
  absl::flat_hash_map<std::string, WaitingDualNet*> models_ GUARDED_BY(&mutex_);
  std::queue<EvaluatedBatch> batches_ GUARDED_BY(&mutex_);
};

WaitingDualNet::WaitingDualNet(WaitingDualNetFactory* factory,
                               std::string model)
    : factory_(factory), model_(std::move(model)) {}

void WaitingDualNet::RunMany(std::vector<const BoardFeatures*> features,
                             std::vector<Output*> outputs, std::string* model) {
  before_.Wait();
  factory_->PushEvaluatedBatch(model_, features.size());
  if (model != nullptr) {
    *model = model_;
  }
  after_.Post();
}

void WaitingDualNet::Notify() {
  before_.Post();
  after_.Wait();
}

WaitingDualNetFactory::WaitingDualNetFactory(int buffer_count)
    : buffer_count_(buffer_count) {}

int WaitingDualNetFactory::GetBufferCount() const { return buffer_count_; }

std::unique_ptr<DualNet> WaitingDualNetFactory::NewDualNet(
    const std::string& model_path) {
  absl::MutexLock lock(&mutex_);
  auto model = absl::make_unique<WaitingDualNet>(this, model_path);
  MG_CHECK(models_.emplace(model_path, model.get()).second);
  return model;
}

void WaitingDualNetFactory::FlushBatch(const std::string& model_path,
                                       size_t expected_batch_size) {
  // Find the model for the given model_path.
  WaitingDualNet* model;
  {
    absl::MutexLock lock(&mutex_);
    auto it = models_.find(model_path);
    MG_CHECK(it != models_.end());
    model = it->second;
  }

  // Notify it, letting it run a single batch.
  model->Notify();

  // The model should now have pushed a batch on to the batches_ queue: pop it
  // off or die trying.
  EvaluatedBatch batch;
  {
    absl::MutexLock lock(&mutex_);
    MG_CHECK(!batches_.empty());
    batch = std::move(batches_.front());
    batches_.pop();
  }

  // Check the popped batch matches the expected batch.
  MG_CHECK(batch.model_path == model_path);
  MG_CHECK(batch.size == expected_batch_size);
}

void WaitingDualNetFactory::PushEvaluatedBatch(const std::string& model,
                                               size_t size) {
  absl::MutexLock lock(&mutex_);
  batches_.emplace(model, size);
}

class BatchingDualNetTest : public ::testing::Test {
 protected:
  void InitFactory(int buffer_count) {
    auto impl = absl::make_unique<WaitingDualNetFactory>(buffer_count);
    waiting_factory_ = impl.get();
    batching_factory_ = NewBatchingDualNetFactory(std::move(impl));
  }

  std::unique_ptr<DualNet> NewDualNet(const std::string& model_path) {
    return batching_factory_->NewDualNet(model_path);
  }

  void StartGame(DualNet* black, DualNet* white) {
    batching_factory_->StartGame(black, white);
  }

  void EndGame(DualNet* black, DualNet* white) {
    batching_factory_->EndGame(black, white);
  }

  void FlushBatch(const std::string& model_path, size_t expected_batch_size) {
    waiting_factory_->FlushBatch(model_path, expected_batch_size);
  }

 private:
  // Owned by batching_factory_.
  WaitingDualNetFactory* waiting_factory_ = nullptr;
  std::unique_ptr<DualNetFactory> batching_factory_;
};

TEST_F(BatchingDualNetTest, SelfPlay) {
  constexpr int kNumGames = 6;

  struct Game {
    DualNet::BoardFeatures features;
    DualNet::Output output;
    std::unique_ptr<DualNet> model;
    std::thread thread;
  };

  // Test single, double and triple buffering.
  for (int buffer_count = 1; buffer_count <= 3; ++buffer_count) {
    InitFactory(buffer_count);
    int expected_batch_size = kNumGames / buffer_count;

    std::vector<Game> games;
    for (int i = 0; i < kNumGames; ++i) {
      Game game;
      game.model = NewDualNet("a");
      StartGame(game.model.get(), game.model.get());
      games.push_back(std::move(game));
    }

    for (auto& game : games) {
      game.thread = std::thread([this, &game] {
        game.model->RunMany({&game.features}, {&game.output}, nullptr);
      });
    }

    for (int i = 0; i < kNumGames / expected_batch_size; ++i) {
      FlushBatch("a", expected_batch_size);
    }

    for (auto& game : games) {
      EndGame(game.model.get(), game.model.get());
      game.thread.join();
    }
  }
}

TEST_F(BatchingDualNetTest, EvalDoubleBuffer) {
  constexpr int kNumGames = 6;

  struct Game {
    DualNet::BoardFeatures features;
    DualNet::Output output;
    std::unique_ptr<DualNet> black;
    std::unique_ptr<DualNet> white;
    std::thread thread;
  };

  // Test single, double and triple buffering.
  for (int buffer_count = 1; buffer_count <= 3; ++buffer_count) {
    InitFactory(buffer_count);
    int expected_batch_size = kNumGames / buffer_count;

    std::vector<Game> games;
    for (int i = 0; i < kNumGames; ++i) {
      Game game;
      game.black = NewDualNet("black");
      game.white = NewDualNet("white");
      StartGame(game.black.get(), game.white.get());
      games.push_back(std::move(game));
    }

    for (auto& game : games) {
      game.thread = std::thread([this, &game] {
        game.black->RunMany({&game.features}, {&game.output}, nullptr);
        game.white->RunMany({&game.features}, {&game.output}, nullptr);
      });
    }

    for (int i = 0; i < kNumGames / expected_batch_size; ++i) {
      FlushBatch("black", expected_batch_size);
      FlushBatch("white", expected_batch_size);
    }

    for (auto& game : games) {
      EndGame(game.black.get(), game.black.get());
      game.thread.join();
    }
  }
}
}  // namespace
}  // namespace minigo
<|endoftext|>


<commit_before>//=======================================================================
// Copyright (c) 2014-2017 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#include <deque>

#include "dll/neural/dense_layer.hpp"
#include "dll/test.hpp"
#include "dll/dbn.hpp"
#include "dll/trainer/stochastic_gradient_descent.hpp"

#include "mnist/mnist_reader.hpp"
#include "mnist/mnist_utils.hpp"

int main(int /*argc*/, char* /*argv*/ []) {
    // Load the dataset
    auto dataset = mnist::read_dataset_direct<std::vector, etl::dyn_vector<float>>();

    // Limit the test
    dataset.training_images.resize(10000);
    dataset.training_labels.resize(10000);

    mnist::binarize_dataset(dataset);

    // Build the network

    using network_t = dll::dbn_desc<
        dll::dbn_layers<
            dll::dense_desc<28 * 28, 500>::layer_t,
            dll::dense_desc<500, 250>::layer_t,
            dll::dense_desc<250, 10, dll::activation<dll::function::SOFTMAX>>::layer_t>,
        dll::momentum, dll::batch_size<100>, dll::trainer<dll::sgd_trainer>>::dbn_t;

    auto net = std::make_unique<network_t>();

    // Display the network
    net->display();

    // Train the network for performance sake
    net->fine_tune(dataset.training_images, dataset.training_labels, 20);

    // Test the network on test set
    auto error = dll::test_set(net, dataset.test_images, dataset.test_labels, dll::predictor());
    std::cout << "Test error: " << error << std::endl;

    return 0;
}
<commit_msg>Review the example<commit_after>//=======================================================================
// Copyright (c) 2014-2017 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#include <deque>

#include "dll/neural/dense_layer.hpp"
#include "dll/test.hpp"
#include "dll/dbn.hpp"
#include "dll/trainer/stochastic_gradient_descent.hpp"

#include "mnist/mnist_reader.hpp"
#include "mnist/mnist_utils.hpp"

int main(int /*argc*/, char* /*argv*/ []) {
    // Load the dataset
    auto dataset = mnist::read_dataset_direct<std::vector, etl::fast_dyn_matrix<float, 28 * 28>>();

    // Limit the test
    dataset.training_images.resize(10000);
    dataset.training_labels.resize(10000);

    mnist::binarize_dataset(dataset);

    // Build the network

    using network_t = dll::dbn_desc<
        dll::dbn_layers<
            dll::dense_desc<28 * 28, 500>::layer_t,
            dll::dense_desc<500, 250>::layer_t,
            dll::dense_desc<250, 10, dll::activation<dll::function::SOFTMAX>>::layer_t>,
        dll::momentum, dll::batch_size<100>, dll::trainer<dll::sgd_trainer>>::dbn_t;

    auto net = std::make_unique<network_t>();

    // Display the network
    net->display();

    // Train the network for performance sake
    net->fine_tune(dataset.training_images, dataset.training_labels, 20);

    // Test the network on test set
    auto error = dll::test_set(net, dataset.test_images, dataset.test_labels, dll::predictor());
    std::cout << "Test error: " << error << std::endl;

    return 0;
}
<|endoftext|>


<commit_before>/***********************************************************************
    created:    Tue Jul 5 2005
    author:     Paul D Turner <paul@cegui.org.uk>
*************************************************************************/
/***************************************************************************
 *   Copyright (C) 2004 - 2006 Paul D Turner & The CEGUI Development Team
 *
 *   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 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 "CEGUI/WindowRendererSets/Core/StaticImage.h"
#include "CEGUI/falagard/WidgetLookManager.h"
#include "CEGUI/falagard/WidgetLookFeel.h"
#include "CEGUI/TplWindowRendererProperty.h"

// Start of CEGUI namespace section
namespace CEGUI
{
    const String FalagardStaticImage::TypeName("Core/StaticImage");

    FalagardStaticImage::FalagardStaticImage(const String& type) :
        FalagardStatic(type),
        d_image(0)
    {
        CEGUI_DEFINE_WINDOW_RENDERER_PROPERTY(FalagardStaticImage, Image*,
            "Image", "Property to get/set the image for the FalagardStaticImage widget."
            "  Value is a pointer to an Image".",
            &FalagardStaticImage::setImage, &FalagardStaticImage::getImage,
            0);
    }

    void FalagardStaticImage::render()
    {
        // base class rendering
        FalagardStatic::render();

        // render image if there is one
        if (d_image!=0)
        {
            // get WidgetLookFeel for the assigned look.
            const WidgetLookFeel& wlf = getLookNFeel();
            String imagery_name = (!d_frameEnabled && wlf.isStateImageryPresent("NoFrameImage")) ? "NoFrameImage" : "WithFrameImage";
            wlf.getStateImagery(imagery_name).render(*d_window);
        }
    }

    void FalagardStaticImage::setImage(const Image* img)
    {
        d_image = img;
        d_window->invalidate();
    }

} // End of  CEGUI namespace section
<commit_msg>MOD: Fixed a critical typo in the StaticImage Image-prop-description<commit_after>/***********************************************************************
    created:    Tue Jul 5 2005
    author:     Paul D Turner <paul@cegui.org.uk>
*************************************************************************/
/***************************************************************************
 *   Copyright (C) 2004 - 2006 Paul D Turner & The CEGUI Development Team
 *
 *   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 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 "CEGUI/WindowRendererSets/Core/StaticImage.h"
#include "CEGUI/falagard/WidgetLookManager.h"
#include "CEGUI/falagard/WidgetLookFeel.h"
#include "CEGUI/TplWindowRendererProperty.h"

// Start of CEGUI namespace section
namespace CEGUI
{
    const String FalagardStaticImage::TypeName("Core/StaticImage");

    FalagardStaticImage::FalagardStaticImage(const String& type) :
        FalagardStatic(type),
        d_image(0)
    {
        CEGUI_DEFINE_WINDOW_RENDERER_PROPERTY(FalagardStaticImage, Image*,
            "Image", "Property to get/set the image for the FalagardStaticImage widget."
            "  Value is a pointer to an Image.",
            &FalagardStaticImage::setImage, &FalagardStaticImage::getImage,
            0);
    }

    void FalagardStaticImage::render()
    {
        // base class rendering
        FalagardStatic::render();

        // render image if there is one
        if (d_image!=0)
        {
            // get WidgetLookFeel for the assigned look.
            const WidgetLookFeel& wlf = getLookNFeel();
            String imagery_name = (!d_frameEnabled && wlf.isStateImageryPresent("NoFrameImage")) ? "NoFrameImage" : "WithFrameImage";
            wlf.getStateImagery(imagery_name).render(*d_window);
        }
    }

    void FalagardStaticImage::setImage(const Image* img)
    {
        d_image = img;
        d_window->invalidate();
    }

} // End of  CEGUI namespace section
<|endoftext|>