<commit_before>//===-- Error.cpp -----------------------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

// C Includes
#ifdef __APPLE__
#include <mach/mach.h>
#endif

// C++ Includes
// Other libraries and framework includes
// Project includes
#include "lldb/Core/Error.h"
#include "lldb/Core/Log.h"
#include "llvm/ADT/SmallVector.h"
#include <cerrno>
#include <cstdarg>

#if (defined (__arm__) || defined (__arm64__) || defined (__aarch64__)) && defined (__APPLE__)
#include <SpringBoardServices/SpringBoardServer.h>
#endif

using namespace lldb;
using namespace lldb_private;

Error::Error ():
    m_code (0),
    m_type (eErrorTypeInvalid),
    m_string ()
{
}

//----------------------------------------------------------------------
// Default constructor
//----------------------------------------------------------------------
Error::Error(ValueType err, ErrorType type) :
    m_code (err),
    m_type (type),
    m_string ()
{
}

Error::Error (const Error &rhs) :
    m_code (rhs.m_code),
    m_type (rhs.m_type),
    m_string (rhs.m_string)
{
}

Error::Error (const char* format, ...):
    m_code (0),
    m_type (eErrorTypeInvalid),
    m_string ()
{
    va_list args;
    va_start (args, format);
    SetErrorToGenericError ();
    SetErrorStringWithVarArg (format, args);
    va_end (args);
}

//----------------------------------------------------------------------
// Assignment operator
//----------------------------------------------------------------------
const Error&
Error::operator = (const Error& rhs)
{
    if (this != &rhs)
    {
        m_code = rhs.m_code;
        m_type = rhs.m_type;
        m_string = rhs.m_string;
    }
    return *this;
}

//----------------------------------------------------------------------
// Assignment operator
//----------------------------------------------------------------------
const Error&
Error::operator = (uint32_t err)
{
    m_code = err;
    m_type = eErrorTypeMachKernel;
    m_string.clear();
    return *this;
}

Error::~Error()
{
}

//----------------------------------------------------------------------
// Get the error value as a NULL C string. The error string will be
// fetched and cached on demand. The cached error string value will
// remain until the error value is changed or cleared.
//----------------------------------------------------------------------
const char *
Error::AsCString(const char *default_error_str) const
{
    if (Success())
        return NULL;

    if (m_string.empty())
    {
        const char *s = NULL;
        switch (m_type)
        {
        case eErrorTypeMachKernel:
#if defined (__APPLE__)
            s = ::mach_error_string (m_code);
#endif
            break;

        case eErrorTypePOSIX:
            s = ::strerror (m_code);
            break;

        default:
            break;
        }
        if (s)
            m_string.assign(s);
    }
    if (m_string.empty())
    {
        if (default_error_str)
            m_string.assign(default_error_str);
        else
            return NULL;    // User wanted a NULL string back...
    }
    return m_string.c_str();
}

//----------------------------------------------------------------------
// Clear the error and any cached error string that it might contain.
//----------------------------------------------------------------------
void
Error::Clear ()
{
    m_code = 0;
    m_type = eErrorTypeGeneric;
    m_string.clear();
}

//----------------------------------------------------------------------
// Access the error value.
//----------------------------------------------------------------------
Error::ValueType
Error::GetError () const
{
    return m_code;
}

//----------------------------------------------------------------------
// Access the error type.
//----------------------------------------------------------------------
ErrorType
Error::GetType () const
{
    return m_type;
}

//----------------------------------------------------------------------
// Retuns true if this object contains an value that describes an
// error or otherwise non-success result.
//----------------------------------------------------------------------
bool
Error::Fail () const
{
    return m_code != 0;
}

//----------------------------------------------------------------------
// Log the error given a string with format. If the this object
// contains an error code, update the error string to contain the
// "error: " followed by the formatted string, followed by the error
// value and any string that describes the current error. This
// allows more context to be given to an error string that remains
// cached in this object. Logging always occurs even when the error
// code contains a non-error value.
//----------------------------------------------------------------------
void
Error::PutToLog (Log *log, const char *format, ...)
{
    char *arg_msg = NULL;
    va_list args;
    va_start (args, format);
    ::vasprintf (&arg_msg, format, args);
    va_end (args);

    if (arg_msg != NULL)
    {
        if (Fail())
        {
            const char *err_str = AsCString();
            if (err_str == NULL)
                err_str = "???";

            SetErrorStringWithFormat("error: %s err = %s (0x%8.8x)", arg_msg, err_str, m_code);
            if (log)
                log->Error("%s", m_string.c_str());
        }
        else
        {
            if (log)
                log->Printf("%s err = 0x%8.8x", arg_msg, m_code);
        }
        ::free (arg_msg);
    }
}

//----------------------------------------------------------------------
// Log the error given a string with format. If the this object
// contains an error code, update the error string to contain the
// "error: " followed by the formatted string, followed by the error
// value and any string that describes the current error. This
// allows more context to be given to an error string that remains
// cached in this object. Logging only occurs even when the error
// code contains a error value.
//----------------------------------------------------------------------
void
Error::LogIfError (Log *log, const char *format, ...)
{
    if (Fail())
    {
        char *arg_msg = NULL;
        va_list args;
        va_start (args, format);
        ::vasprintf (&arg_msg, format, args);
        va_end (args);

        if (arg_msg != NULL)
        {
            const char *err_str = AsCString();
            if (err_str == NULL)
                err_str = "???";

            SetErrorStringWithFormat("%s err = %s (0x%8.8x)", arg_msg, err_str, m_code);
            if (log)
                log->Error("%s", m_string.c_str());

            ::free (arg_msg);
        }
    }
}

//----------------------------------------------------------------------
// Set accesssor for the error value to "err" and the type to
// "eErrorTypeMachKernel"
//----------------------------------------------------------------------
void
Error::SetMachError (uint32_t err)
{
    m_code = err;
    m_type = eErrorTypeMachKernel;
    m_string.clear();
}

void
Error::SetExpressionError (lldb::ExpressionResults result, const char *mssg)
{
    m_code = result;
    m_type = eErrorTypeExpression;
    m_string = mssg;
}

int
Error::SetExpressionErrorWithFormat (lldb::ExpressionResults result, const char *format, ...)
{
    int length = 0;

    if (format && format[0])
    {
        va_list args;
        va_start (args, format);
        length = SetErrorStringWithVarArg (format, args);
        va_end (args);
    }
    else
    {
        m_string.clear();
    }
    m_code = result;
    m_type = eErrorTypeExpression;
    return length;
}

//----------------------------------------------------------------------
// Set accesssor for the error value and type.
//----------------------------------------------------------------------
void
Error::SetError (ValueType err, ErrorType type)
{
    m_code = err;
    m_type = type;
    m_string.clear();
}

//----------------------------------------------------------------------
// Update the error value to be "errno" and update the type to
// be "POSIX".
//----------------------------------------------------------------------
void
Error::SetErrorToErrno()
{
    m_code = errno;
    m_type = eErrorTypePOSIX;
    m_string.clear();
}

//----------------------------------------------------------------------
// Update the error value to be LLDB_GENERIC_ERROR and update the type
// to be "Generic".
//----------------------------------------------------------------------
void
Error::SetErrorToGenericError ()
{
    m_code = LLDB_GENERIC_ERROR;
    m_type = eErrorTypeGeneric;
    m_string.clear();
}

//----------------------------------------------------------------------
// Set accessor for the error string value for a specific error.
// This allows any string to be supplied as an error explanation.
// The error string value will remain until the error value is
// cleared or a new error value/type is assigned.
//----------------------------------------------------------------------
void
Error::SetErrorString (const char *err_str)
{
    if (err_str && err_str[0])
    {
        // If we have an error string, we should always at least have
        // an error set to a generic value.
        if (Success())
            SetErrorToGenericError();
        m_string = err_str;
    }
    else
        m_string.clear();
}

//------------------------------------------------------------------
/// Set the current error string to a formatted error string.
///
/// @param format
///     A printf style format string
//------------------------------------------------------------------
int
Error::SetErrorStringWithFormat (const char *format, ...)
{
    if (format && format[0])
    {
        va_list args;
        va_start (args, format);
        int length = SetErrorStringWithVarArg (format, args);
        va_end (args);
        return length;
    }
    else
    {
        m_string.clear();
    }
    return 0;
}

int
Error::SetErrorStringWithVarArg (const char *format, va_list args)
{
    if (format && format[0])
    {
        // If we have an error string, we should always at least have
        // an error set to a generic value.
        if (Success())
            SetErrorToGenericError();

        // Try and fit our error into a 1024 byte buffer first...
        llvm::SmallVector<char, 1024> buf;
        buf.resize(1024);
        // Copy in case our first call to vsnprintf doesn't fit into our
        // allocated buffer above
        va_list copy_args;
        va_copy (copy_args, args);
        unsigned length = ::vsnprintf (buf.data(), buf.size(), format, args);
        if (length >= buf.size())
        {
            // The error formatted string didn't fit into our buffer, resize it
            // to the exact needed size, and retry
            buf.resize(length + 1);
            length = ::vsnprintf (buf.data(), buf.size(), format, copy_args);
            va_end (copy_args);
            assert (length < buf.size());
        }
        m_string.assign(buf.data(), length);
        va_end (args);
        return length;
    }
    else
    {
        m_string.clear();
    }
    return 0;
}

//----------------------------------------------------------------------
// Returns true if the error code in this object is considered a
// successful return value.
//----------------------------------------------------------------------
bool
Error::Success() const
{
    return m_code == 0;
}

bool
Error::WasInterrupted() const
{
    if (m_type == eErrorTypePOSIX && m_code == EINTR)
        return true;
    else
        return false;
}

<commit_msg>Error::Clear() should reset the type to invalid instead of generic.<commit_after>//===-- Error.cpp -----------------------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

// C Includes
#ifdef __APPLE__
#include <mach/mach.h>
#endif

// C++ Includes
// Other libraries and framework includes
// Project includes
#include "lldb/Core/Error.h"
#include "lldb/Core/Log.h"
#include "llvm/ADT/SmallVector.h"
#include <cerrno>
#include <cstdarg>

#if (defined (__arm__) || defined (__arm64__) || defined (__aarch64__)) && defined (__APPLE__)
#include <SpringBoardServices/SpringBoardServer.h>
#endif

using namespace lldb;
using namespace lldb_private;

Error::Error ():
    m_code (0),
    m_type (eErrorTypeInvalid),
    m_string ()
{
}

//----------------------------------------------------------------------
// Default constructor
//----------------------------------------------------------------------
Error::Error(ValueType err, ErrorType type) :
    m_code (err),
    m_type (type),
    m_string ()
{
}

Error::Error (const Error &rhs) :
    m_code (rhs.m_code),
    m_type (rhs.m_type),
    m_string (rhs.m_string)
{
}

Error::Error (const char* format, ...):
    m_code (0),
    m_type (eErrorTypeInvalid),
    m_string ()
{
    va_list args;
    va_start (args, format);
    SetErrorToGenericError ();
    SetErrorStringWithVarArg (format, args);
    va_end (args);
}

//----------------------------------------------------------------------
// Assignment operator
//----------------------------------------------------------------------
const Error&
Error::operator = (const Error& rhs)
{
    if (this != &rhs)
    {
        m_code = rhs.m_code;
        m_type = rhs.m_type;
        m_string = rhs.m_string;
    }
    return *this;
}

//----------------------------------------------------------------------
// Assignment operator
//----------------------------------------------------------------------
const Error&
Error::operator = (uint32_t err)
{
    m_code = err;
    m_type = eErrorTypeMachKernel;
    m_string.clear();
    return *this;
}

Error::~Error()
{
}

//----------------------------------------------------------------------
// Get the error value as a NULL C string. The error string will be
// fetched and cached on demand. The cached error string value will
// remain until the error value is changed or cleared.
//----------------------------------------------------------------------
const char *
Error::AsCString(const char *default_error_str) const
{
    if (Success())
        return NULL;

    if (m_string.empty())
    {
        const char *s = NULL;
        switch (m_type)
        {
        case eErrorTypeMachKernel:
#if defined (__APPLE__)
            s = ::mach_error_string (m_code);
#endif
            break;

        case eErrorTypePOSIX:
            s = ::strerror (m_code);
            break;

        default:
            break;
        }
        if (s)
            m_string.assign(s);
    }
    if (m_string.empty())
    {
        if (default_error_str)
            m_string.assign(default_error_str);
        else
            return NULL;    // User wanted a NULL string back...
    }
    return m_string.c_str();
}

//----------------------------------------------------------------------
// Clear the error and any cached error string that it might contain.
//----------------------------------------------------------------------
void
Error::Clear ()
{
    m_code = 0;
    m_type = eErrorTypeInvalid;
    m_string.clear();
}

//----------------------------------------------------------------------
// Access the error value.
//----------------------------------------------------------------------
Error::ValueType
Error::GetError () const
{
    return m_code;
}

//----------------------------------------------------------------------
// Access the error type.
//----------------------------------------------------------------------
ErrorType
Error::GetType () const
{
    return m_type;
}

//----------------------------------------------------------------------
// Retuns true if this object contains an value that describes an
// error or otherwise non-success result.
//----------------------------------------------------------------------
bool
Error::Fail () const
{
    return m_code != 0;
}

//----------------------------------------------------------------------
// Log the error given a string with format. If the this object
// contains an error code, update the error string to contain the
// "error: " followed by the formatted string, followed by the error
// value and any string that describes the current error. This
// allows more context to be given to an error string that remains
// cached in this object. Logging always occurs even when the error
// code contains a non-error value.
//----------------------------------------------------------------------
void
Error::PutToLog (Log *log, const char *format, ...)
{
    char *arg_msg = NULL;
    va_list args;
    va_start (args, format);
    ::vasprintf (&arg_msg, format, args);
    va_end (args);

    if (arg_msg != NULL)
    {
        if (Fail())
        {
            const char *err_str = AsCString();
            if (err_str == NULL)
                err_str = "???";

            SetErrorStringWithFormat("error: %s err = %s (0x%8.8x)", arg_msg, err_str, m_code);
            if (log)
                log->Error("%s", m_string.c_str());
        }
        else
        {
            if (log)
                log->Printf("%s err = 0x%8.8x", arg_msg, m_code);
        }
        ::free (arg_msg);
    }
}

//----------------------------------------------------------------------
// Log the error given a string with format. If the this object
// contains an error code, update the error string to contain the
// "error: " followed by the formatted string, followed by the error
// value and any string that describes the current error. This
// allows more context to be given to an error string that remains
// cached in this object. Logging only occurs even when the error
// code contains a error value.
//----------------------------------------------------------------------
void
Error::LogIfError (Log *log, const char *format, ...)
{
    if (Fail())
    {
        char *arg_msg = NULL;
        va_list args;
        va_start (args, format);
        ::vasprintf (&arg_msg, format, args);
        va_end (args);

        if (arg_msg != NULL)
        {
            const char *err_str = AsCString();
            if (err_str == NULL)
                err_str = "???";

            SetErrorStringWithFormat("%s err = %s (0x%8.8x)", arg_msg, err_str, m_code);
            if (log)
                log->Error("%s", m_string.c_str());

            ::free (arg_msg);
        }
    }
}

//----------------------------------------------------------------------
// Set accesssor for the error value to "err" and the type to
// "eErrorTypeMachKernel"
//----------------------------------------------------------------------
void
Error::SetMachError (uint32_t err)
{
    m_code = err;
    m_type = eErrorTypeMachKernel;
    m_string.clear();
}

void
Error::SetExpressionError (lldb::ExpressionResults result, const char *mssg)
{
    m_code = result;
    m_type = eErrorTypeExpression;
    m_string = mssg;
}

int
Error::SetExpressionErrorWithFormat (lldb::ExpressionResults result, const char *format, ...)
{
    int length = 0;

    if (format && format[0])
    {
        va_list args;
        va_start (args, format);
        length = SetErrorStringWithVarArg (format, args);
        va_end (args);
    }
    else
    {
        m_string.clear();
    }
    m_code = result;
    m_type = eErrorTypeExpression;
    return length;
}

//----------------------------------------------------------------------
// Set accesssor for the error value and type.
//----------------------------------------------------------------------
void
Error::SetError (ValueType err, ErrorType type)
{
    m_code = err;
    m_type = type;
    m_string.clear();
}

//----------------------------------------------------------------------
// Update the error value to be "errno" and update the type to
// be "POSIX".
//----------------------------------------------------------------------
void
Error::SetErrorToErrno()
{
    m_code = errno;
    m_type = eErrorTypePOSIX;
    m_string.clear();
}

//----------------------------------------------------------------------
// Update the error value to be LLDB_GENERIC_ERROR and update the type
// to be "Generic".
//----------------------------------------------------------------------
void
Error::SetErrorToGenericError ()
{
    m_code = LLDB_GENERIC_ERROR;
    m_type = eErrorTypeGeneric;
    m_string.clear();
}

//----------------------------------------------------------------------
// Set accessor for the error string value for a specific error.
// This allows any string to be supplied as an error explanation.
// The error string value will remain until the error value is
// cleared or a new error value/type is assigned.
//----------------------------------------------------------------------
void
Error::SetErrorString (const char *err_str)
{
    if (err_str && err_str[0])
    {
        // If we have an error string, we should always at least have
        // an error set to a generic value.
        if (Success())
            SetErrorToGenericError();
        m_string = err_str;
    }
    else
        m_string.clear();
}

//------------------------------------------------------------------
/// Set the current error string to a formatted error string.
///
/// @param format
///     A printf style format string
//------------------------------------------------------------------
int
Error::SetErrorStringWithFormat (const char *format, ...)
{
    if (format && format[0])
    {
        va_list args;
        va_start (args, format);
        int length = SetErrorStringWithVarArg (format, args);
        va_end (args);
        return length;
    }
    else
    {
        m_string.clear();
    }
    return 0;
}

int
Error::SetErrorStringWithVarArg (const char *format, va_list args)
{
    if (format && format[0])
    {
        // If we have an error string, we should always at least have
        // an error set to a generic value.
        if (Success())
            SetErrorToGenericError();

        // Try and fit our error into a 1024 byte buffer first...
        llvm::SmallVector<char, 1024> buf;
        buf.resize(1024);
        // Copy in case our first call to vsnprintf doesn't fit into our
        // allocated buffer above
        va_list copy_args;
        va_copy (copy_args, args);
        unsigned length = ::vsnprintf (buf.data(), buf.size(), format, args);
        if (length >= buf.size())
        {
            // The error formatted string didn't fit into our buffer, resize it
            // to the exact needed size, and retry
            buf.resize(length + 1);
            length = ::vsnprintf (buf.data(), buf.size(), format, copy_args);
            va_end (copy_args);
            assert (length < buf.size());
        }
        m_string.assign(buf.data(), length);
        va_end (args);
        return length;
    }
    else
    {
        m_string.clear();
    }
    return 0;
}

//----------------------------------------------------------------------
// Returns true if the error code in this object is considered a
// successful return value.
//----------------------------------------------------------------------
bool
Error::Success() const
{
    return m_code == 0;
}

bool
Error::WasInterrupted() const
{
    if (m_type == eErrorTypePOSIX && m_code == EINTR)
        return true;
    else
        return false;
}

<|endoftext|>


<commit_before>/*
 *  Copyright 2004 The WebRTC Project Authors. All rights reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "webrtc/base/latebindingsymboltable.h"

#if defined(WEBRTC_POSIX)
#include <dlfcn.h>
#endif

#include "webrtc/base/logging.h"

namespace rtc {

#if defined(WEBRTC_POSIX)
static const DllHandle kInvalidDllHandle = NULL;
#else
#error Not implemented
#endif

static const char *GetDllError() {
#if defined(WEBRTC_POSIX)
  const char *err = dlerror();
  if (err) {
    return err;
  } else {
    return "No error";
  }
#else
#error Not implemented
#endif
}

static bool LoadSymbol(DllHandle handle,
                       const char *symbol_name,
                       void **symbol) {
#if defined(WEBRTC_POSIX)
  *symbol = dlsym(handle, symbol_name);
  const char *err = dlerror();
  if (err) {
    LOG(LS_ERROR) << "Error loading symbol " << symbol_name << ": " << err;
    return false;
  } else if (!*symbol) {
    // ELF allows for symbols to be NULL, but that should never happen for our
    // usage.
    LOG(LS_ERROR) << "Symbol " << symbol_name << " is NULL";
    return false;
  }
  return true;
#else
#error Not implemented
#endif
}

LateBindingSymbolTable::LateBindingSymbolTable(const TableInfo *info,
    void **table)
    : info_(info),
      table_(table),
      handle_(kInvalidDllHandle),
      undefined_symbols_(false) {
  ClearSymbols();
}

LateBindingSymbolTable::~LateBindingSymbolTable() {
  Unload();
}

bool LateBindingSymbolTable::IsLoaded() const {
  return handle_ != kInvalidDllHandle;
}

bool LateBindingSymbolTable::Load() {
  ASSERT(info_->dll_name != NULL);
  return LoadFromPath(info_->dll_name);
}

bool LateBindingSymbolTable::LoadFromPath(const char *dll_path) {
  if (IsLoaded()) {
    return true;
  }
  if (undefined_symbols_) {
    // We do not attempt to load again because repeated attempts are not
    // likely to succeed and DLL loading is costly.
    LOG(LS_ERROR) << "We know there are undefined symbols";
    return false;
  }

#if defined(WEBRTC_POSIX)
  handle_ = dlopen(dll_path,
                   // RTLD_NOW front-loads symbol resolution so that errors are
                   // caught early instead of causing a process abort later.
                   // RTLD_LOCAL prevents other modules from automatically
                   // seeing symbol definitions in the newly-loaded tree. This
                   // is necessary for same-named symbols in different ABI
                   // versions of the same library to not explode.
                   RTLD_NOW|RTLD_LOCAL
#if defined(WEBRTC_LINUX) && !defined(WEBRTC_ANDROID)
                   // RTLD_DEEPBIND makes symbol dependencies in the
                   // newly-loaded tree prefer to resolve to definitions within
                   // that tree (the default on OS X). This is necessary for
                   // same-named symbols in different ABI versions of the same
                   // library to not explode.
                   |RTLD_DEEPBIND
#endif
                   );  // NOLINT
#else
#error Not implemented
#endif

  if (handle_ == kInvalidDllHandle) {
    LOG(LS_WARNING) << "Can't load " << dll_path << ": "
                    << GetDllError();
    return false;
  }
#if defined(WEBRTC_POSIX)
  // Clear any old errors.
  dlerror();
#endif
  for (int i = 0; i < info_->num_symbols; ++i) {
    if (!LoadSymbol(handle_, info_->symbol_names[i], &table_[i])) {
      undefined_symbols_ = true;
      Unload();
      return false;
    }
  }
  return true;
}

void LateBindingSymbolTable::Unload() {
  if (!IsLoaded()) {
    return;
  }

#if defined(WEBRTC_POSIX)
  if (dlclose(handle_) != 0) {
    LOG(LS_ERROR) << GetDllError();
  }
#else
#error Not implemented
#endif

  handle_ = kInvalidDllHandle;
  ClearSymbols();
}

void LateBindingSymbolTable::ClearSymbols() {
  memset(table_, 0, sizeof(void *) * info_->num_symbols);
}

}  // namespace rtc
<commit_msg>Landing issue 15189004<commit_after>/*
 *  Copyright 2004 The WebRTC Project Authors. All rights reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "webrtc/base/latebindingsymboltable.h"

#if defined(WEBRTC_POSIX)
#include <dlfcn.h>
#endif

#include "webrtc/base/logging.h"

namespace rtc {

#if defined(WEBRTC_POSIX)
static const DllHandle kInvalidDllHandle = NULL;
#else
#error Not implemented
#endif

static const char *GetDllError() {
#if defined(WEBRTC_POSIX)
  const char *err = dlerror();
  if (err) {
    return err;
  } else {
    return "No error";
  }
#else
#error Not implemented
#endif
}

static bool LoadSymbol(DllHandle handle,
                       const char *symbol_name,
                       void **symbol) {
#if defined(WEBRTC_POSIX)
  *symbol = dlsym(handle, symbol_name);
  const char *err = dlerror();
  if (err) {
    LOG(LS_ERROR) << "Error loading symbol " << symbol_name << ": " << err;
    return false;
  } else if (!*symbol) {
    // ELF allows for symbols to be NULL, but that should never happen for our
    // usage.
    LOG(LS_ERROR) << "Symbol " << symbol_name << " is NULL";
    return false;
  }
  return true;
#else
#error Not implemented
#endif
}

LateBindingSymbolTable::LateBindingSymbolTable(const TableInfo *info,
    void **table)
    : info_(info),
      table_(table),
      handle_(kInvalidDllHandle),
      undefined_symbols_(false) {
  ClearSymbols();
}

LateBindingSymbolTable::~LateBindingSymbolTable() {
  Unload();
}

bool LateBindingSymbolTable::IsLoaded() const {
  return handle_ != kInvalidDllHandle;
}

bool LateBindingSymbolTable::Load() {
  ASSERT(info_->dll_name != NULL);
  return LoadFromPath(info_->dll_name);
}

bool LateBindingSymbolTable::LoadFromPath(const char *dll_path) {
  if (IsLoaded()) {
    return true;
  }
  if (undefined_symbols_) {
    // We do not attempt to load again because repeated attempts are not
    // likely to succeed and DLL loading is costly.
    LOG(LS_ERROR) << "We know there are undefined symbols";
    return false;
  }

#if defined(WEBRTC_POSIX)
  handle_ = dlopen(dll_path,
                   // RTLD_NOW front-loads symbol resolution so that errors are
                   // caught early instead of causing a process abort later.
                   // RTLD_LOCAL prevents other modules from automatically
                   // seeing symbol definitions in the newly-loaded tree. This
                   // is necessary for same-named symbols in different ABI
                   // versions of the same library to not explode.
                   RTLD_NOW|RTLD_LOCAL
#if defined(WEBRTC_LINUX) && !defined(WEBRTC_ANDROID) && defined(RTLD_DEEPBIND)
                   // RTLD_DEEPBIND makes symbol dependencies in the
                   // newly-loaded tree prefer to resolve to definitions within
                   // that tree (the default on OS X). This is necessary for
                   // same-named symbols in different ABI versions of the same
                   // library to not explode.
                   |RTLD_DEEPBIND
#endif
                   );  // NOLINT
#else
#error Not implemented
#endif

  if (handle_ == kInvalidDllHandle) {
    LOG(LS_WARNING) << "Can't load " << dll_path << ": "
                    << GetDllError();
    return false;
  }
#if defined(WEBRTC_POSIX)
  // Clear any old errors.
  dlerror();
#endif
  for (int i = 0; i < info_->num_symbols; ++i) {
    if (!LoadSymbol(handle_, info_->symbol_names[i], &table_[i])) {
      undefined_symbols_ = true;
      Unload();
      return false;
    }
  }
  return true;
}

void LateBindingSymbolTable::Unload() {
  if (!IsLoaded()) {
    return;
  }

#if defined(WEBRTC_POSIX)
  if (dlclose(handle_) != 0) {
    LOG(LS_ERROR) << GetDllError();
  }
#else
#error Not implemented
#endif

  handle_ = kInvalidDllHandle;
  ClearSymbols();
}

void LateBindingSymbolTable::ClearSymbols() {
  memset(table_, 0, sizeof(void *) * info_->num_symbols);
}

}  // namespace rtc
<|endoftext|>


<commit_before>#ifndef STAN_MATH_GPU_OPENCL_CONTEXT_HPP
#define STAN_MATH_GPU_OPENCL_CONTEXT_HPP
#ifdef STAN_OPENCL
#define __CL_ENABLE_EXCEPTIONS

#include <stan/math/prim/arr/err/check_opencl.hpp>
#include <stan/math/prim/scal/err/system_error.hpp>
#include <CL/cl.hpp>
#include <cmath>
#include <fstream>
#include <map>
#include <vector>
#include <system_error>
#include <cerrno>

#define DEVICE_FILTER CL_DEVICE_TYPE_GPU
#ifndef OPENCL_DEVICE_ID
#define OPENCL_DEVICE_ID 0
#endif
#ifndef OPENCL_PLATFORM_ID
#define OPENCL_PLATFORM_ID 0
#endif

/**
 *  @file stan/math/gpu/opencl_context.hpp
 *  @brief Initialization for OpenCL:
 *    1. create context
 *    2. Find OpenCL platforms and devices available
 *    3. set up command queue
 *    4. initialize kernel groups
 */

namespace stan {
namespace math {

/**
 * The opencl_context class represents the OpenCL context.
 *
 * See the OpenCL specification glossary for a list of terms:
 * https://www.khronos.org/registry/OpenCL/specs/opencl-1.2.pdf.
 * The context includes the set of devices available on the host, command
 * queues, manages kernels.
 *
 * This is designed so there's only one instance running on the host.
 *
 * Some design decisions that may need to be addressed later:
 * - we are assuming a single OpenCL platform. We may want to run on multiple
 * platforms simulatenously
 * - we are assuming a single OpenCL device. We may want to run on multiple
 * devices simulatenously
 */
class opencl_context {
 private:
  cl::Context context_;  // Manages the the device, queue, platform, memory,etc.
  cl::CommandQueue command_queue_;       // job queue for device, one per device
  std::vector<cl::Platform> platforms_;  // Vector of available platforms
  cl::Platform platform_;                // The platform for compiling kernels
  std::string platform_name_;  // The platform such as NVIDIA OpenCL or AMD SDK
  std::vector<cl::Device> devices_;  // All available GPU devices
  cl::Device device_;                    // The selected GPU device
  std::string device_name_;              // The name of the GPU
  size_t max_workgroup_size_;  // The maximum size of a block of workers on GPU
  /** Holds meta information about a kernel
   * @param exists a bool to identify whether a kernel has been compiled
   * @param group The name of the compilation group for the kernel
   * @param code The source code for the kernel
   */
  struct kernel_meta_info {
    bool exists;
    const char* group;
    const char* raw_code;
  };
  /**
   * Map of a kernel name (first) and it's meta information (second).
   */
  typedef std::map<const char*, kernel_meta_info> map_kernel_info;
  /**
   * map holding compiled kernels.
   */
  typedef std::map<const char*, cl::Kernel> map_kernel;
  map_kernel_info kernel_info; // The meta kernel info
  map_kernel kernels; // The compiled kernels

  /**
   * Construct the opencl_context by initializing the
   * OpenCL context, devices, command queues, and kernel
   * groups.
   *
   * This constructor does the following:
   * 1. Gets the available platforms and selects the platform
   *  with id OPENCL_PLATFORM_ID
   * 2. Gets the available devices and selects the device with id
   *  OPENCL_DEVICE_ID
   * 3. Creates the OpenCL context with the device
   * 4. Creates the OpenCL command queue for the selected device
   * 5. Initializes the kernel groups by filling the  kernel_info
   *  map.
   * @throw std::system_error if an OpenCL error occurs
   */
  opencl_context() {
    try {
      // platform
      cl::Platform::get(&platforms_);
      platform_ = platforms_[OPENCL_PLATFORM_ID];
      platform_name_ = platform_.getInfo<CL_PLATFORM_NAME>();
      platform_.getDevices(DEVICE_FILTER, &devices_);
      if (devices_.size() == 0) {
        system_error("OpenCL Initialization", "[Device]", -1,
                     "CL_DEVICE_NOT_FOUND");
      }
      device_ = devices_[OPENCL_DEVICE_ID];
      // context and queue
      context_ = cl::Context(device_);
      command_queue_ = cl::CommandQueue(context_, device_,
                                        CL_QUEUE_PROFILING_ENABLE, nullptr);
      // setup kernel groups
      init_kernel_groups();
      device_.getInfo<size_t>(CL_DEVICE_MAX_WORK_GROUP_SIZE,
                              &max_workgroup_size_);

    } catch (const cl::Error& e) {
      check_ocl_error("opencl_context", e.what(), e.err());
    }
  }
  /**
   * Initalizes the  kernel_info  where each kernel is mapped to
   * a logical flag to mark if the kernel was already compiled,
   * the name of the kernel group, and the OpenCL kernel sources.
   */
  inline void init_kernel_groups() {
    kernel_info["dummy"] = {
        false, "timing", "__kernel void dummy(__global const int* foo) { };"};
    kernel_info["dummy2"] = {
        false, "timing", "__kernel void dummy2(__global const int* foo) { };"};
  }

  /**
   * Compiles all the kernels in the specified. The side effect of this
   *  method places all compiled kernels for a group inside of  kernels
   *  .
   *
   * @param kernel_name[in] The kernel name
   *
   * @throw std::system_error if there are compilation errors
   * when compiling the specified kernel group sources
   */
  inline void compile_kernel_group(const char* kernel_name) {
    char temp[100];
    int local = 32;
    int gpu_local_max = sqrt(max_workgroup_size());
    if (gpu_local_max < local)
      local = gpu_local_max;
    snprintf(temp, sizeof(temp), "-D TS=%d -D TS1=%d -D TS2=%d ", local, local,
             local);
    std::string kernel_source = "";
    const char* kernel_group = kernel_info[kernel_name].group;
    for (auto kern : kernel_info) {
      if (strcmp(kern.second.group, kernel_group) == 0) {
        kernel_source += kern.second.raw_code;
      }
    }

    try {
      cl::Program::Sources source(
          1,
          std::make_pair(kernel_source.c_str(), strlen(kernel_source.c_str())));
      cl::Program program_ = cl::Program(context_ , source);
      program_.build({device_}, temp);

      cl_int err = CL_SUCCESS;
      // Iterate over the kernel list and get all the kernels from this group
      // and mark them as compiled.
      for (auto kern : kernel_info) {
        if (strcmp(kern.second.group, kernel_group) == 0) {
          kernels[(kern.first)] = cl::Kernel(program_, kern.first, &err);
          kern.second.exists = true;
        }
      }
    } catch (const cl::Error& e) {
      check_ocl_error("Kernel Compilation", e.what(), e.err());
    }
  }

 public:

  /**
   * Returns the kernel specified in kernel_name.
   * If the kernel has not yet been compiled, the kernel group is compiled
   * first.
   *
   * @brief Passing the name of a kernel compiles all kernels in the same group
   * as the selected kernel.
   * OpenCL kernels are compiled JIT, instead of compiling each kernel
   * individually this function will compile all kernels
   * in a predefined group. Groupings are made such that kernels commonly
   * called with one another will be compiled at the same time. For example,
   * An arithmetic group of kernels compiled together could contain the kernels
   * for  add() ,  subtract() ,
   * and  multiply() . This function will only return the kernel
   * which was called, but when a user asks for a kernel within the group those
   * kernels will already be compiled.
   *
   * @param[in] kernel_name The kernel name
   *
   * @return a copy of the cl::Kernel object
   */
  inline cl::Kernel get_kernel(const char* kernel_name) {
    // Compile the kernel group and return the kernel
    if (!kernel_info[kernel_name].exists) {
      compile_kernel_group(kernel_name);
    }
    return kernels[kernel_name];
  }

  // FIXME:(Steve/Dan) should probably be deleted before merge
  void debug(std::ostream& s) {
    s << "inside opencl_context" << std::endl;
    s << " * platform_name_: " << platform_name_ << std::endl;
  }
  /**
   * Initializes the OpenCL context. This is made with a static local singleton
   * design so that only one context is available.
   */
  static opencl_context& getInstance() {
    static opencl_context instance;
    return instance;
  }

  /**
   * Returns the description of the OpenCL platform and device that is used.
   * Devices will be a GPU and Platforms are a specific OpenCL implimenation
   * such as AMD SDK's or Nvidia's OpenCL implimentation.
   */
  inline std::string description() const {
    std::ostringstream msg;
    msg << "Platform ID: " << OPENCL_DEVICE_ID << "\n";
    msg << "Platform Name: " << platform_.getInfo<CL_PLATFORM_NAME>() << "\n";
    msg << "Platform Vendor: " << platform_.getInfo<CL_PLATFORM_VENDOR>()
        << "\n";
    msg << "\tDevice " << OPENCL_DEVICE_ID << ": "
        << "\n";
    msg << "\t\tDevice Name: " << device_.getInfo<CL_DEVICE_NAME>() << "\n";
    msg << "\t\tDevice Type: " << device_.getInfo<CL_DEVICE_TYPE>() << "\n";
    msg << "\t\tDevice Vendor: " << device_.getInfo<CL_DEVICE_VENDOR>() << "\n";
    msg << "\t\tDevice Max Compute Units: "
        << device_.getInfo<CL_DEVICE_MAX_COMPUTE_UNITS>() << "\n";
    msg << "\t\tDevice Global Memory: "
        << device_.getInfo<CL_DEVICE_GLOBAL_MEM_SIZE>() << "\n";
    msg << "\t\tDevice Max Clock Frequency: "
        << device_.getInfo<CL_DEVICE_MAX_CLOCK_FREQUENCY>() << "\n";
    msg << "\t\tDevice Max Allocateable Memory: "
        << device_.getInfo<CL_DEVICE_MAX_MEM_ALLOC_SIZE>() << "\n";
    msg << "\t\tDevice Local Memory: "
        << device_.getInfo<CL_DEVICE_LOCAL_MEM_SIZE>() << "\n";
    msg << "\t\tDevice Available: " << device_.getInfo<CL_DEVICE_AVAILABLE>()
        << "\n";
    return msg.str();
  }

  /**
   * Returns the description of the OpenCL platforms and devices that
   * are available. Devices will be a GPU and Platforms are a specific OpenCL
   * implimenation such as AMD SDK's or Nvidia's OpenCL implimentation.
   */
  inline std::string capabilities() const {
    std::vector<cl::Platform> all_platforms;
    cl::Platform::get(&all_platforms);
    std::ostringstream msg;
    int platform_id = 0;
    int device_id = 0;

    msg << "Number of Platforms: " << all_platforms.size() << "\n";
    for (auto plat_iter : all_platforms) {
      cl::Platform platform(plat_iter);

      msg << "Platform ID: " << platform_id++ << "\n";
      msg << "Platform Name: " << platform.getInfo<CL_PLATFORM_NAME>() << "\n";
      msg << "Platform Vendor: " << platform.getInfo<CL_PLATFORM_VENDOR>()
          << "\n";

      std::vector<cl::Device> all_devices;
      platform.getDevices(CL_DEVICE_TYPE_GPU, &all_devices);

      for (auto device_iter : all_devices) {
        cl::Device device(device_iter);

        msg << "\tDevice " << device_id++ << ": "
            << "\n";
        msg << "\t\tDevice Name: " << device.getInfo<CL_DEVICE_NAME>() << "\n";
        msg << "\t\tDevice Type: " << device.getInfo<CL_DEVICE_TYPE>() << "\n";
        msg << "\t\tDevice Vendor: " << device.getInfo<CL_DEVICE_VENDOR>()
            << "\n";
        msg << "\t\tDevice Max Compute Units: "
            << device.getInfo<CL_DEVICE_MAX_COMPUTE_UNITS>() << "\n";
        msg << "\t\tDevice Global Memory: "
            << device.getInfo<CL_DEVICE_GLOBAL_MEM_SIZE>() << "\n";
        msg << "\t\tDevice Max Clock Frequency: "
            << device.getInfo<CL_DEVICE_MAX_CLOCK_FREQUENCY>() << "\n";
        msg << "\t\tDevice Max Allocateable Memory: "
            << device.getInfo<CL_DEVICE_MAX_MEM_ALLOC_SIZE>() << "\n";
        msg << "\t\tDevice Local Memory: "
            << device.getInfo<CL_DEVICE_LOCAL_MEM_SIZE>() << "\n";
        msg << "\t\tDevice Available: " << device.getInfo<CL_DEVICE_AVAILABLE>()
            << "\n";
      }
    }
    return msg.str();
  }

  /**
   * Returns the reference to the OpenCL context. The OpenCL context manages
   * objects such as the device, memory, command queue, program, and kernel
   * objects. For stan, there should only be one context, queue, device, and
   * program with multiple kernels.
   */
  inline cl::Context& context() { return context_; }
  /**
   * Returns the reference to the active OpenCL command queue for the device.
   * One command queue will exist per device where
   * kernels are placed on the command queue and by default executed in order.
   */
  inline cl::CommandQueue& queue() { return command_queue_; }
  /**
   * Returns the maximum workgroup size defined by CL_DEVICE_MAX_WORK_GROUP_SIZE
   * for the device in the context. This is the maximum product of work group
   * dimensions for a particular device. IE a max workgoup of 256 would allow
   * work groups of sizes (16,16), (128,2), (8, 32), etc.
   */
  inline int max_workgroup_size() { return max_workgroup_size_; }

  /**
   * Returns a vector containing the OpenCL device used to create the context
   */
  inline std::vector<cl::Device> device() { return {device_}; }

  /**
   * Returns a vector containing the OpenCL platform used to create the context
   */
  inline std::vector<cl::Platform> platform() { return {platform_}; }
};

static opencl_context opencl_context
    = stan::math::opencl_context::getInstance();

}  // namespace math
}  // namespace stan

#endif
#endif
<commit_msg>Fix spelling<commit_after>#ifndef STAN_MATH_GPU_OPENCL_CONTEXT_HPP
#define STAN_MATH_GPU_OPENCL_CONTEXT_HPP
#ifdef STAN_OPENCL
#define __CL_ENABLE_EXCEPTIONS

#include <stan/math/prim/arr/err/check_opencl.hpp>
#include <stan/math/prim/scal/err/system_error.hpp>
#include <CL/cl.hpp>
#include <cmath>
#include <fstream>
#include <map>
#include <vector>
#include <system_error>
#include <cerrno>

#define DEVICE_FILTER CL_DEVICE_TYPE_GPU
#ifndef OPENCL_DEVICE_ID
#define OPENCL_DEVICE_ID 0
#endif
#ifndef OPENCL_PLATFORM_ID
#define OPENCL_PLATFORM_ID 0
#endif

/**
 *  @file stan/math/gpu/opencl_context.hpp
 *  @brief Initialization for OpenCL:
 *    1. create context
 *    2. Find OpenCL platforms and devices available
 *    3. set up command queue
 *    4. initialize kernel groups
 */

namespace stan {
namespace math {

/**
 * The opencl_context class represents the OpenCL context.
 *
 * See the OpenCL specification glossary for a list of terms:
 * https://www.khronos.org/registry/OpenCL/specs/opencl-1.2.pdf.
 * The context includes the set of devices available on the host, command
 * queues, manages kernels.
 *
 * This is designed so there's only one instance running on the host.
 *
 * Some design decisions that may need to be addressed later:
 * - we are assuming a single OpenCL platform. We may want to run on multiple
 * platforms simulatenously
 * - we are assuming a single OpenCL device. We may want to run on multiple
 * devices simulatenously
 */
class opencl_context {
 private:
  cl::Context context_;  // Manages the the device, queue, platform, memory,etc.
  cl::CommandQueue command_queue_;       // job queue for device, one per device
  std::vector<cl::Platform> platforms_;  // Vector of available platforms
  cl::Platform platform_;                // The platform for compiling kernels
  std::string platform_name_;  // The platform such as NVIDIA OpenCL or AMD SDK
  std::vector<cl::Device> devices_;  // All available GPU devices
  cl::Device device_;                    // The selected GPU device
  std::string device_name_;              // The name of the GPU
  size_t max_workgroup_size_;  // The maximum size of a block of workers on GPU
  /** Holds meta information about a kernel.
   * @param exists a bool to identify whether a kernel has been compiled.
   * @param group The name of the compilation group for the kernel.
   * @param code The source code for the kernel.
   */
  struct kernel_meta_info {
    bool exists;
    const char* group;
    const char* raw_code;
  };
  /**
   * Map of a kernel name (first) and it's meta information (second).
   */
  typedef std::map<const char*, kernel_meta_info> map_kernel_info;
  /**
   * map holding compiled kernels.
   */
  typedef std::map<const char*, cl::Kernel> map_kernel;
  map_kernel_info kernel_info; // The meta kernel info
  map_kernel kernels; // The compiled kernels

  /**
   * Construct the opencl_context by initializing the
   * OpenCL context, devices, command queues, and kernel
   * groups.
   *
   * This constructor does the following:
   * 1. Gets the available platforms and selects the platform
   *  with id OPENCL_PLATFORM_ID.
   * 2. Gets the available devices and selects the device with id
   *  OPENCL_DEVICE_ID.
   * 3. Creates the OpenCL context with the device.
   * 4. Creates the OpenCL command queue for the selected device.
   * 5. Initializes the kernel groups by filling the  kernel_info
   *  map.
   * @throw std::system_error if an OpenCL error occurs.
   */
  opencl_context() {
    try {
      // platform
      cl::Platform::get(&platforms_);
      platform_ = platforms_[OPENCL_PLATFORM_ID];
      platform_name_ = platform_.getInfo<CL_PLATFORM_NAME>();
      platform_.getDevices(DEVICE_FILTER, &devices_);
      if (devices_.size() == 0) {
        system_error("OpenCL Initialization", "[Device]", -1,
                     "CL_DEVICE_NOT_FOUND");
      }
      device_ = devices_[OPENCL_DEVICE_ID];
      // context and queue
      context_ = cl::Context(device_);
      command_queue_ = cl::CommandQueue(context_, device_,
                                        CL_QUEUE_PROFILING_ENABLE, nullptr);
      // setup kernel groups
      init_kernel_groups();
      device_.getInfo<size_t>(CL_DEVICE_MAX_WORK_GROUP_SIZE,
                              &max_workgroup_size_);

    } catch (const cl::Error& e) {
      check_ocl_error("opencl_context", e.what(), e.err());
    }
  }
  /**
   * Initializes the  kernel_info  where each kernel is mapped to
   * a logical flag to mark if the kernel was already compiled,
   * the name of the kernel group, and the OpenCL kernel sources.
   */
  inline void init_kernel_groups() {
    kernel_info["dummy"] = {
        false, "timing", "__kernel void dummy(__global const int* foo) { };"};
    kernel_info["dummy2"] = {
        false, "timing", "__kernel void dummy2(__global const int* foo) { };"};
  }

  /**
   * Compiles all the kernels in the specified group. The side effect of this
   *  method places all compiled kernels for a group inside of  kernels
   *  .
   *
   * @param kernel_name[in] The kernel name.
   *
   * @throw std::system_error if there are compilation errors
   * when compiling the specified kernel group's source code.
   */
  inline void compile_kernel_group(const char* kernel_name) {
    char temp[100];
    int local = 32;
    int gpu_local_max = sqrt(max_workgroup_size());
    if (gpu_local_max < local)
      local = gpu_local_max;
    snprintf(temp, sizeof(temp), "-D TS=%d -D TS1=%d -D TS2=%d ", local, local,
             local);
    std::string kernel_source = "";
    const char* kernel_group = kernel_info[kernel_name].group;
    for (auto kern : kernel_info) {
      if (strcmp(kern.second.group, kernel_group) == 0) {
        kernel_source += kern.second.raw_code;
      }
    }

    try {
      cl::Program::Sources source(
          1,
          std::make_pair(kernel_source.c_str(), strlen(kernel_source.c_str())));
      cl::Program program_ = cl::Program(context_ , source);
      program_.build({device_}, temp);

      cl_int err = CL_SUCCESS;
      // Iterate over the kernel list and get all the kernels from this group
      // and mark them as compiled.
      for (auto kern : kernel_info) {
        if (strcmp(kern.second.group, kernel_group) == 0) {
          kernels[(kern.first)] = cl::Kernel(program_, kern.first, &err);
          kern.second.exists = true;
        }
      }
    } catch (const cl::Error& e) {
      check_ocl_error("Kernel Compilation", e.what(), e.err());
    }
  }

 public:

  /**
   * Returns the kernel specified in kernel_name.
   * If the kernel has not yet been compiled, the kernel group is compiled
   * first.
   *
   * @brief Passing the name of a kernel compiles all kernels in the same group
   * as the selected kernel.
   * OpenCL kernels are compiled JIT, instead of compiling each kernel
   * individually this function will compile all kernels
   * in a predefined group. Groupings are made such that kernels commonly
   * called with one another will be compiled at the same time. For example,
   * An arithmetic group of kernels compiled together could contain the kernels
   * for  add() ,  subtract() ,
   * and  multiply() . This function will only return the kernel
   * which was called, but when a user asks for a kernel within the group those
   * kernels will already be compiled.
   *
   * @param[in] kernel_name The kernel name
   *
   * @return a copy of the cl::Kernel object
   */
  inline cl::Kernel get_kernel(const char* kernel_name) {
    // Compile the kernel group and return the kernel
    if (!kernel_info[kernel_name].exists) {
      compile_kernel_group(kernel_name);
    }
    return kernels[kernel_name];
  }

  // FIXME:(Steve/Dan) should probably be deleted before merge
  void debug(std::ostream& s) {
    s << "inside opencl_context" << std::endl;
    s << " * platform_name_: " << platform_name_ << std::endl;
  }
  /**
   * Initializes the OpenCL context. This is made with a static local singleton
   * design so that only one context is available.
   */
  static opencl_context& getInstance() {
    static opencl_context instance;
    return instance;
  }

  /**
   * Returns the description of the OpenCL platform and device that is used.
   * Devices will be a GPU and Platforms are a specific OpenCL implimenation
   * such as AMD SDK's or Nvidia's OpenCL implimentation.
   */
  inline std::string description() const {
    std::ostringstream msg;
    msg << "Platform ID: " << OPENCL_DEVICE_ID << "\n";
    msg << "Platform Name: " << platform_.getInfo<CL_PLATFORM_NAME>() << "\n";
    msg << "Platform Vendor: " << platform_.getInfo<CL_PLATFORM_VENDOR>()
        << "\n";
    msg << "\tDevice " << OPENCL_DEVICE_ID << ": "
        << "\n";
    msg << "\t\tDevice Name: " << device_.getInfo<CL_DEVICE_NAME>() << "\n";
    msg << "\t\tDevice Type: " << device_.getInfo<CL_DEVICE_TYPE>() << "\n";
    msg << "\t\tDevice Vendor: " << device_.getInfo<CL_DEVICE_VENDOR>() << "\n";
    msg << "\t\tDevice Max Compute Units: "
        << device_.getInfo<CL_DEVICE_MAX_COMPUTE_UNITS>() << "\n";
    msg << "\t\tDevice Global Memory: "
        << device_.getInfo<CL_DEVICE_GLOBAL_MEM_SIZE>() << "\n";
    msg << "\t\tDevice Max Clock Frequency: "
        << device_.getInfo<CL_DEVICE_MAX_CLOCK_FREQUENCY>() << "\n";
    msg << "\t\tDevice Max Allocateable Memory: "
        << device_.getInfo<CL_DEVICE_MAX_MEM_ALLOC_SIZE>() << "\n";
    msg << "\t\tDevice Local Memory: "
        << device_.getInfo<CL_DEVICE_LOCAL_MEM_SIZE>() << "\n";
    msg << "\t\tDevice Available: " << device_.getInfo<CL_DEVICE_AVAILABLE>()
        << "\n";
    return msg.str();
  }

  /**
   * Returns the description of the OpenCL platforms and devices that
   * are available. Devices will be a GPU and Platforms are a specific OpenCL
   * implimenation such as AMD SDK's or Nvidia's OpenCL implimentation.
   */
  inline std::string capabilities() const {
    std::vector<cl::Platform> all_platforms;
    cl::Platform::get(&all_platforms);
    std::ostringstream msg;
    int platform_id = 0;
    int device_id = 0;

    msg << "Number of Platforms: " << all_platforms.size() << "\n";
    for (auto plat_iter : all_platforms) {
      cl::Platform platform(plat_iter);

      msg << "Platform ID: " << platform_id++ << "\n";
      msg << "Platform Name: " << platform.getInfo<CL_PLATFORM_NAME>() << "\n";
      msg << "Platform Vendor: " << platform.getInfo<CL_PLATFORM_VENDOR>()
          << "\n";

      std::vector<cl::Device> all_devices;
      platform.getDevices(CL_DEVICE_TYPE_GPU, &all_devices);

      for (auto device_iter : all_devices) {
        cl::Device device(device_iter);

        msg << "\tDevice " << device_id++ << ": "
            << "\n";
        msg << "\t\tDevice Name: " << device.getInfo<CL_DEVICE_NAME>() << "\n";
        msg << "\t\tDevice Type: " << device.getInfo<CL_DEVICE_TYPE>() << "\n";
        msg << "\t\tDevice Vendor: " << device.getInfo<CL_DEVICE_VENDOR>()
            << "\n";
        msg << "\t\tDevice Max Compute Units: "
            << device.getInfo<CL_DEVICE_MAX_COMPUTE_UNITS>() << "\n";
        msg << "\t\tDevice Global Memory: "
            << device.getInfo<CL_DEVICE_GLOBAL_MEM_SIZE>() << "\n";
        msg << "\t\tDevice Max Clock Frequency: "
            << device.getInfo<CL_DEVICE_MAX_CLOCK_FREQUENCY>() << "\n";
        msg << "\t\tDevice Max Allocateable Memory: "
            << device.getInfo<CL_DEVICE_MAX_MEM_ALLOC_SIZE>() << "\n";
        msg << "\t\tDevice Local Memory: "
            << device.getInfo<CL_DEVICE_LOCAL_MEM_SIZE>() << "\n";
        msg << "\t\tDevice Available: " << device.getInfo<CL_DEVICE_AVAILABLE>()
            << "\n";
      }
    }
    return msg.str();
  }

  /**
   * Returns the reference to the OpenCL context. The OpenCL context manages
   * objects such as the device, memory, command queue, program, and kernel
   * objects. For stan, there should only be one context, queue, device, and
   * program with multiple kernels.
   */
  inline cl::Context& context() { return context_; }
  /**
   * Returns the reference to the active OpenCL command queue for the device.
   * One command queue will exist per device where
   * kernels are placed on the command queue and by default executed in order.
   */
  inline cl::CommandQueue& queue() { return command_queue_; }
  /**
   * Returns the maximum workgroup size defined by CL_DEVICE_MAX_WORK_GROUP_SIZE
   * for the device in the context. This is the maximum product of work group
   * dimensions for a particular device. IE a max workgoup of 256 would allow
   * work groups of sizes (16,16), (128,2), (8, 32), etc.
   */
  inline int max_workgroup_size() { return max_workgroup_size_; }

  /**
   * Returns a vector containing the OpenCL device used to create the context
   */
  inline std::vector<cl::Device> device() { return {device_}; }

  /**
   * Returns a vector containing the OpenCL platform used to create the context
   */
  inline std::vector<cl::Platform> platform() { return {platform_}; }
};

static opencl_context opencl_context
    = stan::math::opencl_context::getInstance();

}  // namespace math
}  // namespace stan

#endif
#endif
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2008-2016 the MRtrix3 contributors
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/
 *
 * MRtrix is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 *
 * For more details, see www.mrtrix.org
 *
 */

#include "command.h"
#include "image.h"
#include <Eigen/Dense>
#include <Eigen/SVD>

#define DEFAULT_SIZE 5

using namespace MR;
using namespace App;

void usage ()
{
  DESCRIPTION
  + "denoise DWI data and estimate the noise level based on the optimal threshold for PCA.";

  AUTHOR = "Daan Christiaens (daan.christiaens@kuleuven.be) & Jelle Veraart (jelle.veraart@nyumc.org) & J-Donald Tournier (jdtournier.gmail.com)";

  ARGUMENTS
  + Argument ("dwi", "the input diffusion-weighted image.").type_image_in ()

  + Argument ("out", "the output denoised DWI image.").type_image_out ();

  OPTIONS
  + Option ("size", "set the window size of the denoising filter. (default = " + str(DEFAULT_SIZE) + ")")
    + Argument ("window").type_integer (0, 50)

  + Option ("noise", "the output noise map.")
    + Argument ("level").type_image_out();

}

typedef float value_type;

template <class ImageType>
class DenoisingFunctor
{
public:
  DenoisingFunctor (ImageType& dwi, int size)
    : extent(size/2),
      m(dwi.size(3)),
      n(size*size*size),
      X(m,n), Xm(m),
      pos{0, 0, 0}
  { }

  void operator () (ImageType& dwi, ImageType& out)
  {
    // Load data in local window
    load_data(dwi);
    // Centre data
    Xm = X.rowwise().mean();
    X.colwise() -= Xm;
    // Compute SVD
    Eigen::JacobiSVD<Eigen::MatrixXd> svd (X, Eigen::ComputeThinU | Eigen::ComputeThinV);
    Eigen::VectorXd s = svd.singularValues();
    // Simply threshold at 90% variance for now
    double thres = 0.90 * s.squaredNorm();
    double cumsum = 0.0;
    for (size_t i = 0; i < n; ++i) {
      if (cumsum <= thres)
        cumsum += s[i] * s[i];
      else
        s[i] = 0.0;
    }
    // Restore DWI data
    X = svd.matrixU() * s.asDiagonal() * svd.matrixV().adjoint();
    X.colwise() += Xm;
    // Store output
    assign_pos_of(dwi).to(out);
    out.row(3) = X.col(n/2).template cast<value_type>();
  }

  void load_data (ImageType& dwi)
  {
    pos[0] = dwi.index(0); pos[1] = dwi.index(1); pos[2] = dwi.index(2);
    X.setZero();
    ssize_t k = 0;
    for (dwi.index(2) = pos[2]-extent; dwi.index(2) <= pos[2]+extent; ++dwi.index(2))
      for (dwi.index(1) = pos[1]-extent; dwi.index(1) <= pos[1]+extent; ++dwi.index(1))
        for (dwi.index(0) = pos[0]-extent; dwi.index(0) <= pos[0]+extent; ++dwi.index(0), ++k)
          if (! is_out_of_bounds(dwi))
            X.col(k) = dwi.row(3).template cast<double>();
    // reset image position
    dwi.index(0) = pos[0];
    dwi.index(1) = pos[1];
    dwi.index(2) = pos[2];
  }

private:
  int extent;
  size_t m, n;
  Eigen::MatrixXd X;
  Eigen::VectorXd Xm;
  ssize_t pos[3];

};

void run ()
{
  auto dwi_in = Image<value_type>::open (argument[0]).with_direct_io(3);

  auto header = Header (dwi_in);
  header.datatype() = DataType::Float32;
  auto dwi_out = Image<value_type>::create (argument[1], header);

  int extent = get_option_value("size", DEFAULT_SIZE);

  DenoisingFunctor< Image<value_type> > func (dwi_in, extent);

  ThreadedLoop ("running MP-PCA denoising", dwi_in, 0, 3)
    .run (func, dwi_in, dwi_out);

}

<commit_msg>Switch to single-precision floats.<commit_after>/*
 * Copyright (c) 2008-2016 the MRtrix3 contributors
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/
 *
 * MRtrix is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 *
 * For more details, see www.mrtrix.org
 *
 */

#include "command.h"
#include "image.h"
#include <Eigen/Dense>
#include <Eigen/SVD>

#define DEFAULT_SIZE 5

using namespace MR;
using namespace App;

void usage ()
{
  DESCRIPTION
  + "denoise DWI data and estimate the noise level based on the optimal threshold for PCA.";

  AUTHOR = "Daan Christiaens (daan.christiaens@kuleuven.be) & Jelle Veraart (jelle.veraart@nyumc.org) & J-Donald Tournier (jdtournier.gmail.com)";

  ARGUMENTS
  + Argument ("dwi", "the input diffusion-weighted image.").type_image_in ()

  + Argument ("out", "the output denoised DWI image.").type_image_out ();

  OPTIONS
  + Option ("size", "set the window size of the denoising filter. (default = " + str(DEFAULT_SIZE) + ")")
    + Argument ("window").type_integer (0, 50)

  + Option ("noise", "the output noise map.")
    + Argument ("level").type_image_out();

}

typedef float value_type;

template <class ImageType>
class DenoisingFunctor
{
public:
  DenoisingFunctor (ImageType& dwi, int size)
    : extent(size/2),
      m(dwi.size(3)),
      n(size*size*size),
      X(m,n), Xm(m),
      pos{0, 0, 0}
  { }

  void operator () (ImageType& dwi, ImageType& out)
  {
    // Load data in local window
    load_data(dwi);
    // Centre data
    Xm = X.rowwise().mean();
    X.colwise() -= Xm;
    // Compute SVD
    Eigen::JacobiSVD<Eigen::MatrixXf> svd (X, Eigen::ComputeThinU | Eigen::ComputeThinV);
    Eigen::VectorXf s = svd.singularValues();
    // Simply threshold at 90% variance for now
    double thres = 0.90 * s.squaredNorm();
    double cumsum = 0.0;
    for (size_t i = 0; i < n; ++i) {
      if (cumsum <= thres)
        cumsum += s[i] * s[i];
      else
        s[i] = 0.0;
    }
    // Restore DWI data
    X = svd.matrixU() * s.asDiagonal() * svd.matrixV().adjoint();
    X.colwise() += Xm;
    // Store output
    assign_pos_of(dwi).to(out);
    out.row(3) = X.col(n/2).template cast<value_type>();
  }

  void load_data (ImageType& dwi)
  {
    pos[0] = dwi.index(0); pos[1] = dwi.index(1); pos[2] = dwi.index(2);
    X.setZero();
    ssize_t k = 0;
    for (dwi.index(2) = pos[2]-extent; dwi.index(2) <= pos[2]+extent; ++dwi.index(2))
      for (dwi.index(1) = pos[1]-extent; dwi.index(1) <= pos[1]+extent; ++dwi.index(1))
        for (dwi.index(0) = pos[0]-extent; dwi.index(0) <= pos[0]+extent; ++dwi.index(0), ++k)
          if (! is_out_of_bounds(dwi))
            X.col(k) = dwi.row(3).template cast<float>();
    // reset image position
    dwi.index(0) = pos[0];
    dwi.index(1) = pos[1];
    dwi.index(2) = pos[2];
  }

private:
  int extent;
  size_t m, n;
  Eigen::MatrixXf X;
  Eigen::VectorXf Xm;
  ssize_t pos[3];

};

void run ()
{
  auto dwi_in = Image<value_type>::open (argument[0]).with_direct_io(3);

  auto header = Header (dwi_in);
  header.datatype() = DataType::Float32;
  auto dwi_out = Image<value_type>::create (argument[1], header);

  int extent = get_option_value("size", DEFAULT_SIZE);

  DenoisingFunctor< Image<value_type> > func (dwi_in, extent);

  ThreadedLoop ("running MP-PCA denoising", dwi_in, 0, 3)
    .run (func, dwi_in, dwi_out);

}

<|endoftext|>


<commit_before>/*
 *   CrissCross
 *   A multi-purpose cross-platform library.
 *
 *   A product of Uplink Laboratories.
 *
 *   (c) 2006-2010 Steven Noonan.
 *   Licensed under the New BSD License.
 *
 */

#include "header.h"

using namespace CrissCross::Data;
using namespace CrissCross::IO;
using namespace CrissCross::System;
using namespace std;

Console *console = NULL;

typedef unsigned long ktype_t;
const size_t MaxSearches = 100000;

#define XORSwap(x,y) { (x) = (x) ^ (y); (y) = (y) ^ (x); (x) = (x) ^ (y); }

void shuffleElements(DArray<ktype_t> *_array)
{
	ktype_t temporary;
	size_t randomNum, last, size = _array->used();
	DArray<ktype_t> &array = *_array;

	for (last = size; last > 1; last--)
	{
		randomNum = RandomNumber() % last;
		temporary = array[randomNum];
		array[randomNum] = array[last - 1];
		array[last - 1] = temporary;
	}
}

template <class T>
void TestTree(T _tree, DArray<ktype_t> *dataset, unsigned long _size)
{
	console->Write("%10lu ", _size);

	// fill tree
	Stopwatch sw;
	sw.Start();
	for (size_t i = 0; i < _size; i++) {
		ktype_t item = dataset->get(i);
		_tree->insert(item, item);
	}
	sw.Stop();
	console->Write("%9.5lfs ", sw.Elapsed());

	DArray<ktype_t> searchItems;

	// create valid item list
	searchItems.empty();
	while (searchItems.used() < MaxSearches) {
		unsigned long idx = RandomNumber() % _size;
		searchItems.insert(dataset->get(idx));
	}

	// successful searches
	sw.Start();
	for (size_t i = 0; i < MaxSearches; i++) {
		_tree->find(searchItems[i], 0);
	}
	sw.Stop();
	console->Write("%9.5lfs ", sw.Elapsed());

	// create mixed item list
	searchItems.empty();
	while (searchItems.used() < MaxSearches) {
		unsigned long idx;

		idx = RandomNumber() % _size;
		searchItems.insert(dataset->get(idx));

		idx = _size + (RandomNumber() % _size);
		searchItems.insert(dataset->get(idx));
	}

	// mixed success searches
	sw.Start();
	for (size_t i = 0; i < MaxSearches; i++) {
		_tree->find(searchItems[i], 0);
	}
	sw.Stop();
	console->Write("%9.5lfs ", sw.Elapsed());

	// create invalid item list
	searchItems.empty();
	while (searchItems.used() < MaxSearches) {
		unsigned long idx = _size + (RandomNumber() % _size);
		searchItems.insert(dataset->get(idx));
	}

	// invalid searches
	sw.Start();
	for (size_t i = 0; i < MaxSearches; i++) {
		_tree->find(searchItems[i], 0);
	}
	sw.Stop();
	console->Write("%9.5lfs ", sw.Elapsed());

	// empty tree
	sw.Start();
	_tree->empty();
	sw.Stop();
	console->WriteLine("%9.5lfs", sw.Elapsed());
}

int main(int argc, char * *argv)
{
	console = new Console();

	/* Begin your application here. */

	SeedRandom();
	Stopwatch sw;
	size_t sizes [] = {
		50000,
		100000,
		500000,
		1000000,
		5000000,
		10000000,
		0 };
	size_t biggest = 0;

	// Locate the last element in the sizes list.
	for (size_t *p = sizes; *p != 0; p++) {
		biggest = max(biggest, *p);
	}

	DArray<ktype_t> *dataset = new DArray<ktype_t>(biggest*2);
	console->Write("Building data set of %lu items... ", biggest * 2);
	sw.Start();
	size_t i = 0;
	while (dataset->used() < biggest * 2) {
		dataset->insert(i++);
	}
	shuffleElements(dataset);
	sw.Stop();
	console->WriteLine("%8.5lfs", sw.Elapsed());

	console->WriteLine();
	console->WriteLine("Testing AVLTree...");
	console->WriteLine("%10s %10s %10s %10s %10s %10s", "size", "add", "srch+", "srch", "srch-", "empty");
	AVLTree<ktype_t, char> *avltree = new AVLTree<ktype_t, char>();
	for (size_t *p = sizes; *p != 0; p++) {
		TestTree<AVLTree<ktype_t, char> *> (avltree, dataset, *p);
	}
	console->WriteLine("AVLTree tests complete.");
	delete avltree;
	avltree = NULL;

	console->WriteLine();
	console->WriteLine("Testing RedBlackTree...");
	console->WriteLine("%10s %10s %10s %10s %10s %10s", "size", "add", "srch+", "srch", "srch-", "empty");
	RedBlackTree<ktype_t, char> *rbtree = new RedBlackTree<ktype_t, char>();
	for (size_t *p = sizes; *p != 0; p++) {
		TestTree<RedBlackTree<ktype_t, char> *> (rbtree, dataset, *p);
	}
	console->WriteLine("RedBlackTree tests complete.");
	delete rbtree;
	rbtree = NULL;

	console->WriteLine();
	console->WriteLine("Testing SplayTree...");
	console->WriteLine("%10s %10s %10s %10s %10s %10s", "size", "add", "srch+", "srch", "srch-", "empty");
	SplayTree<ktype_t, char> *splaytree = new SplayTree<ktype_t, char>();
	for (size_t *p = sizes; *p != 0; p++) {
		TestTree<SplayTree<ktype_t, char> *> (splaytree, dataset, *p);
	}
	console->WriteLine("SplayTree tests complete.");
	delete splaytree;
	splaytree = NULL;

	console->WriteLine();
	console->WriteLine("Testing STree...");
	console->WriteLine("%10s %10s %10s %10s %10s %10s", "size", "add", "srch+", "srch", "srch-", "empty");
	STree<ktype_t, char> *stree = new STree<ktype_t, char>();
	for (size_t *p = sizes; *p != 0; p++) {
		TestTree<STree<ktype_t, char> *> (stree, dataset, *p);
	}
	console->WriteLine("STree tests complete.");
	delete stree;
	stree = NULL;

#ifdef ENABLE_STLTREE
	console->WriteLine();
	console->WriteLine("Testing STLTree...");
	console->WriteLine("%10s %10s %10s %10s %10s %10s", "size", "add", "srch+", "srch", "srch-", "empty");
	STLTree<ktype_t, char> *stltree = new STLTree<ktype_t, char>();
	for (size_t *p = sizes; *p != 0; p++) {
		TestTree<STLTree<ktype_t, char> *> (stltree, dataset, *p);
	}
	console->WriteLine("STLTree tests complete.");
	delete stltree;
	stltree = NULL;
#endif

	delete dataset;
	console->WriteLine();

	/* End your application here. */

#ifdef TARGET_OS_WINDOWS
	system("pause");
#endif

	delete console;
	return 0;
}
<commit_msg>TreeBenchmark: improve accuracy of results<commit_after>/*
 *   CrissCross
 *   A multi-purpose cross-platform library.
 *
 *   A product of Uplink Laboratories.
 *
 *   (c) 2006-2010 Steven Noonan.
 *   Licensed under the New BSD License.
 *
 */

#include "header.h"

#include <cmath>

using namespace CrissCross::Data;
using namespace CrissCross::IO;
using namespace CrissCross::System;
using namespace std;

Console *console = NULL;

typedef unsigned long ktype_t;

#define XORSwap(x,y) { (x) = (x) ^ (y); (y) = (y) ^ (x); (x) = (x) ^ (y); }

void shuffleElements(ktype_t *_array, size_t size)
{
	ktype_t temporary;
	size_t randomNum, last;

	for (last = size; last > 1; last--)
	{
		randomNum = RandomNumber() % last;
		temporary = _array[randomNum];
		_array[randomNum] = _array[last - 1];
		_array[last - 1] = temporary;
	}
}

template <class T>
void RunTestcase(T _tree, unsigned long _size, bool _ordered_insert)
{
	console->Write("%10lu ", _size);

	unsigned long realsize = _size * 2;

	ktype_t *elems = NULL;
	if (!_ordered_insert) {
		elems = new ktype_t[_size + 1];
		for (size_t i = 1; i < _size + 1; i++) {
			elems[i] = 2*i;
		}
		elems[_size] = 0;
		shuffleElements(elems, _size);
	}

	// fill tree
	Stopwatch sw;
	sw.Start();
	if (_ordered_insert) {
		for (size_t i = 0; i < _size; i++) {
			_tree->insert(2 * i, 1);
		}
	} else {
		for (ktype_t *p = elems; *p; p++) {
			_tree->insert(*p, 1);
		}
	}
	sw.Stop();
	console->Write("%9.5lfs ", sw.Elapsed());
	delete [] elems;
	elems = NULL;

	// successful searches
	sw.Start();
	for (size_t i = 0; i < _size; i++) {
		_tree->find((2 * RandomNumber()) % realsize, 0);
	}
	sw.Stop();
	console->Write("%9.5lfs ", sw.Elapsed());

	// mixed success searches
	sw.Start();
	for (size_t i = 0; i < _size; i++) {
		_tree->find(RandomNumber() % realsize, 0);
	}
	sw.Stop();
	console->Write("%9.5lfs ", sw.Elapsed());

	// invalid searches
	sw.Start();
	for (size_t i = 0; i < _size; i++) {
		_tree->find((1 + 2 * RandomNumber()) % realsize, 0);
	}
	sw.Stop();
	console->Write("%9.5lfs ", sw.Elapsed());

	// empty tree
	sw.Start();
	_tree->empty();
	sw.Stop();
	console->WriteLine("%9.5lfs", sw.Elapsed());
}

template <class T>
void Test(const char *_name, size_t *sizes)
{
	T *tree;
	console->WriteLine("Testing %s...", _name);
	console->WriteLine();
	console->WriteLine("Dataset: Random");
	console->WriteLine("%10s %10s %10s %10s %10s %10s", "size", "add", "srch+", "srch", "srch-", "empty");
	tree = new T();
	for (size_t *p = sizes; *p != 0; p++) {
		RunTestcase<T *> (tree, *p, false);
	}
	delete tree;
	tree = NULL;
	console->WriteLine();
	console->WriteLine("Dataset: Ordered");
	console->WriteLine("%10s %10s %10s %10s %10s %10s", "size", "add", "srch+", "srch", "srch-", "empty");
	tree = new T();
	for (size_t *p = sizes; *p != 0; p++) {
		RunTestcase<T *> (tree, *p, true);
	}
	delete tree;
	tree = NULL;
	console->WriteLine();
	console->WriteLine("%s tests complete.", _name);
	console->WriteLine();
	console->WriteLine();
}

int main(int argc, char * *argv)
{
	console = new Console();

	/* Begin your application here. */

	SeedRandom();

	const size_t count = 11;
	size_t *sizes = new size_t[count + 1];
	for(size_t i = 0; i < count; i++) {
		sizes[i] = (size_t)pow(2.0,i+10.0);
	}
	sizes[count] = 0;

	Test< AVLTree<ktype_t, char> >("AVLTree", sizes);
	Test< RedBlackTree<ktype_t, char> >("RedBlackTree", sizes);
	Test< SplayTree<ktype_t, char> >("SplayTree", sizes);
//	Test< STree<ktype_t, char> >("STree", sizes);
#ifdef ENABLE_STLTREE
	Test< STLTree<ktype_t, char> >("STLTree", sizes);
#endif

	console->WriteLine();

	/* End your application here. */

#ifdef TARGET_OS_WINDOWS
	system("pause");
#endif

	delete console;
	return 0;
}
<|endoftext|>


<commit_before>/////////////////////////////////////////////////////////////////////////
//
//   Copyright (c) 2002 Stanislav Shwartsman
//          Written by Stanislav Shwartsman <gate@fidonet.org.il>
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2 of the License, or (at your option) any later version.
//
//  This library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//  Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with this library; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
//

#define NEED_CPU_REG_SHORTCUTS 1
#include "bochs.h"
#define LOG_THIS BX_CPU_THIS_PTR

#if BX_SUPPORT_3DNOW

void BX_CPU_C::PFPNACC_PqQq(bxInstruction_c *i)
{
  BX_PANIC(("PFPNACC_PqQq: 3DNow! instruction still not implemented"));
}

void BX_CPU_C::PI2FW_PqQq(bxInstruction_c *i)
{
  BX_PANIC(("PI2FW_PqQq: 3DNow! instruction still not implemented"));
}

void BX_CPU_C::PI2FD_PqQq(bxInstruction_c *i)
{
  BX_PANIC(("PI2FD_PqQq: 3DNow! instruction still not implemented"));
}

void BX_CPU_C::PF2IW_PqQq(bxInstruction_c *i)
{
  BX_PANIC(("PF2IW_PqQq: 3DNow! instruction still not implemented"));
}

void BX_CPU_C::PF2ID_PqQq(bxInstruction_c *i)
{
  BX_PANIC(("PF2ID_PqQq: 3DNow! instruction still not implemented"));
}

void BX_CPU_C::PFNACC_PqQq(bxInstruction_c *i)
{
  BX_PANIC(("PFNACC_PqQq: 3DNow! instruction still not implemented"));
}

void BX_CPU_C::PFCMPGE_PqQq(bxInstruction_c *i)
{
  BX_PANIC(("PFCMPGE_PqQq: 3DNow! instruction still not implemented"));
}

void BX_CPU_C::PFMIN_PqQq(bxInstruction_c *i)
{
  BX_PANIC(("PFMIN_PqQq: 3DNow! instruction still not implemented"));
}

void BX_CPU_C::PFRCP_PqQq(bxInstruction_c *i)
{
  BX_PANIC(("PFRCP_PqQq: 3DNow! instruction still not implemented"));
}

void BX_CPU_C::PFRSQRT_PqQq(bxInstruction_c *i)
{
  BX_PANIC(("PFRSQRT_PqQq: 3DNow! instruction still not implemented"));
}

void BX_CPU_C::PFSUB_PqQq(bxInstruction_c *i)
{
  BX_PANIC(("PFSUB_PqQq: 3DNow! instruction still not implemented"));
}

void BX_CPU_C::PFADD_PqQq(bxInstruction_c *i)
{
  BX_PANIC(("PFADD_PqQq: 3DNow! instruction still not implemented"));
}

void BX_CPU_C::PFCMPGT_PqQq(bxInstruction_c *i)
{
  BX_PANIC(("PFCMPGT_PqQq: 3DNow! instruction still not implemented"));
}

void BX_CPU_C::PFMAX_PqQq(bxInstruction_c *i)
{
  BX_PANIC(("PFMAX_PqQq: 3DNow! instruction still not implemented"));
}

void BX_CPU_C::PFRCPIT1_PqQq(bxInstruction_c *i)
{
  BX_PANIC(("PFRCPIT1_PqQq: 3DNow! instruction still not implemented"));
}

void BX_CPU_C::PFRSQIT1_PqQq(bxInstruction_c *i)
{
  BX_PANIC(("PFRSQIT1_PqQq: 3DNow! instruction still not implemented"));
}

void BX_CPU_C::PFSUBR_PqQq(bxInstruction_c *i)
{
  BX_PANIC(("PFSUBR_PqQq: 3DNow! instruction still not implemented"));
}

void BX_CPU_C::PFACC_PqQq(bxInstruction_c *i)
{
  BX_PANIC(("PFACC_PqQq: 3DNow! instruction still not implemented"));
}

void BX_CPU_C::PFCMPEQ_PqQq(bxInstruction_c *i)
{
  BX_PANIC(("PFCMPEQ_PqQq: 3DNow! instruction still not implemented"));
}

void BX_CPU_C::PFMUL_PqQq(bxInstruction_c *i)
{
  BX_PANIC(("PFMUL_PqQq: 3DNow! instruction still not implemented"));
}

void BX_CPU_C::PFRCPIT2_PqQq(bxInstruction_c *i)
{
  BX_PANIC(("PFRCPIT2_PqQq: 3DNow! instruction still not implemented"));
}

/* 0F 0F /r B7 */
void BX_CPU_C::PMULHRW_PqQq(bxInstruction_c *i)
{
  BX_CPU_THIS_PTR prepareMMX();

  BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn()), op2, result;

  /* op2 is a register or memory reference */
  if (i->modC0()) {
    op2 = BX_READ_MMX_REG(i->rm());
  }
  else {
    /* pointer, segment address pair */
    read_virtual_qword(i->seg(), RMAddr(i), (Bit64u *) &op2);
  }

  Bit32s product1 = Bit32s(MMXSW0(op1)) * Bit32s(MMXSW0(op2)) + 0x8000;
  Bit32s product2 = Bit32s(MMXSW1(op1)) * Bit32s(MMXSW1(op2)) + 0x8000;
  Bit32s product3 = Bit32s(MMXSW2(op1)) * Bit32s(MMXSW2(op2)) + 0x8000;
  Bit32s product4 = Bit32s(MMXSW3(op1)) * Bit32s(MMXSW3(op2)) + 0x8000;

  MMXUW0(result) = Bit16u(product1 >> 16);
  MMXUW1(result) = Bit16u(product2 >> 16);
  MMXUW2(result) = Bit16u(product3 >> 16);
  MMXUW3(result) = Bit16u(product4 >> 16);

  /* now write result back to destination */
  BX_WRITE_MMX_REG(i->nnn(), result);
}

/* 0F 0F /r BB */
void BX_CPU_C::PSWAPD_PqQq(bxInstruction_c *i)
{
  BX_CPU_THIS_PTR prepareMMX();

  BxPackedMmxRegister result, op;

  /* op is a register or memory reference */
  if (i->modC0()) {
    op = BX_READ_MMX_REG(i->rm());
  }
  else {
    /* pointer, segment address pair */
    read_virtual_qword(i->seg(), RMAddr(i), (Bit64u *) &op);
  }

  MMXUD0(result) = MMXUD1(op);
  MMXUD1(result) = MMXUD0(op);

  /* now write result back to destination */
  BX_WRITE_MMX_REG(i->nnn(), result);
}

#endif
<commit_msg>Implement a few 3DNOW instructions<commit_after>/////////////////////////////////////////////////////////////////////////
//
//   Copyright (c) 2002 Stanislav Shwartsman
//          Written by Stanislav Shwartsman <gate@fidonet.org.il>
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2 of the License, or (at your option) any later version.
//
//  This library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//  Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with this library; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
//

#define NEED_CPU_REG_SHORTCUTS 1
#include "bochs.h"
#define LOG_THIS BX_CPU_THIS_PTR

#if BX_SUPPORT_3DNOW

#include "softfloat.h"

static void prepare_softfloat_status_word
	(softfloat_status_word_t &status_word, int rounding_mode)
{
  status.float_detect_tininess = float_tininess_before_rounding;
  status.float_exception_flags = 0; // clear exceptions before execution
  status.float_nan_handling_mode = float_first_operand_nan;
  status.float_rounding_mode = rounding_mode;
  status.flush_underflow_to_zero = 0;
}

void BX_CPU_C::PFPNACC_PqQq(bxInstruction_c *i)
{
  BX_PANIC(("PFPNACC_PqQq: 3DNow! instruction still not implemented"));
}

/* 0F 0F /r 0C */
void BX_CPU_C::PI2FW_PqQq(bxInstruction_c *i)
{
  BxPackedMmxRegister result, op;

  /* op is a register or memory reference */
  if (i->modC0()) {
    op = BX_READ_MMX_REG(i->rm());
  }
  else {
    /* pointer, segment address pair */
    read_virtual_qword(i->seg(), RMAddr(i), (Bit64u *) &op);
  }

  softfloat_status_word_t status_word;
  prepare_softfloat_status_word(status_word, float_round_to_zero);

  MMXUD0(result) =
        int32_to_float32((Bit32s)(MMXSW0(op)), status_word);
  MMXUD1(result) =
        int32_to_float32((Bit32s)(MMXSW2(op)), status_word);

  /* now write result back to destination */
  BX_WRITE_MMX_REG(i->nnn(), result);
}

/* 0F 0F /r 0D */
void BX_CPU_C::PI2FD_PqQq(bxInstruction_c *i)
{
  BxPackedMmxRegister result, op;

  /* op is a register or memory reference */
  if (i->modC0()) {
    op = BX_READ_MMX_REG(i->rm());
  }
  else {
    /* pointer, segment address pair */
    read_virtual_qword(i->seg(), RMAddr(i), (Bit64u *) &op);
  }

  softfloat_status_word_t status_word;
  prepare_softfloat_status_word(status_word, float_round_to_zero);

  MMXUD0(result) =
        int32_to_float32(MMXSD0(op), status_word);
  MMXUD1(result) =
        int32_to_float32(MMXSD1(op), status_word);

  /* now write result back to destination */
  BX_WRITE_MMX_REG(i->nnn(), result);
}

void BX_CPU_C::PF2IW_PqQq(bxInstruction_c *i)
{
  BX_PANIC(("PF2IW_PqQq: 3DNow! instruction still not implemented"));
}

/* 0F 0F /r 1D */
void BX_CPU_C::PF2ID_PqQq(bxInstruction_c *i)
{
  BxPackedMmxRegister result, op;

  /* op is a register or memory reference */
  if (i->modC0()) {
    op = BX_READ_MMX_REG(i->rm());
  }
  else {
    /* pointer, segment address pair */
    read_virtual_qword(i->seg(), RMAddr(i), (Bit64u *) &op);
  }

  softfloat_status_word_t status_word;
  prepare_softfloat_status_word(status_word, float_round_to_zero);

  MMXSD0(result) =
        float32_to_int32_round_to_zero(MMXUD0(op), status_word);
  MMXSD1(result) =
        float32_to_int32_round_to_zero(MMXUD1(op), status_word);

  /* now write result back to destination */
  BX_WRITE_MMX_REG(i->nnn(), result);
}

void BX_CPU_C::PFNACC_PqQq(bxInstruction_c *i)
{
  BX_PANIC(("PFNACC_PqQq: 3DNow! instruction still not implemented"));
}

void BX_CPU_C::PFCMPGE_PqQq(bxInstruction_c *i)
{
  BX_PANIC(("PFCMPGE_PqQq: 3DNow! instruction still not implemented"));
}

void BX_CPU_C::PFMIN_PqQq(bxInstruction_c *i)
{
  BX_PANIC(("PFMIN_PqQq: 3DNow! instruction still not implemented"));
}

void BX_CPU_C::PFRCP_PqQq(bxInstruction_c *i)
{
  BX_PANIC(("PFRCP_PqQq: 3DNow! instruction still not implemented"));
}

void BX_CPU_C::PFRSQRT_PqQq(bxInstruction_c *i)
{
  BX_PANIC(("PFRSQRT_PqQq: 3DNow! instruction still not implemented"));
}

void BX_CPU_C::PFSUB_PqQq(bxInstruction_c *i)
{
  BX_PANIC(("PFSUB_PqQq: 3DNow! instruction still not implemented"));
}

void BX_CPU_C::PFADD_PqQq(bxInstruction_c *i)
{
  BX_PANIC(("PFADD_PqQq: 3DNow! instruction still not implemented"));
}

void BX_CPU_C::PFCMPGT_PqQq(bxInstruction_c *i)
{
  BX_PANIC(("PFCMPGT_PqQq: 3DNow! instruction still not implemented"));
}

void BX_CPU_C::PFMAX_PqQq(bxInstruction_c *i)
{
  BX_PANIC(("PFMAX_PqQq: 3DNow! instruction still not implemented"));
}

void BX_CPU_C::PFRCPIT1_PqQq(bxInstruction_c *i)
{
  BX_PANIC(("PFRCPIT1_PqQq: 3DNow! instruction still not implemented"));
}

void BX_CPU_C::PFRSQIT1_PqQq(bxInstruction_c *i)
{
  BX_PANIC(("PFRSQIT1_PqQq: 3DNow! instruction still not implemented"));
}

void BX_CPU_C::PFSUBR_PqQq(bxInstruction_c *i)
{
  BX_PANIC(("PFSUBR_PqQq: 3DNow! instruction still not implemented"));
}

void BX_CPU_C::PFACC_PqQq(bxInstruction_c *i)
{
  BX_PANIC(("PFACC_PqQq: 3DNow! instruction still not implemented"));
}

void BX_CPU_C::PFCMPEQ_PqQq(bxInstruction_c *i)
{
  BX_PANIC(("PFCMPEQ_PqQq: 3DNow! instruction still not implemented"));
}

void BX_CPU_C::PFMUL_PqQq(bxInstruction_c *i)
{
  BX_PANIC(("PFMUL_PqQq: 3DNow! instruction still not implemented"));
}

void BX_CPU_C::PFRCPIT2_PqQq(bxInstruction_c *i)
{
  BX_PANIC(("PFRCPIT2_PqQq: 3DNow! instruction still not implemented"));
}

/* 0F 0F /r B7 */
void BX_CPU_C::PMULHRW_PqQq(bxInstruction_c *i)
{
  BX_CPU_THIS_PTR prepareMMX();

  BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn()), op2, result;

  /* op2 is a register or memory reference */
  if (i->modC0()) {
    op2 = BX_READ_MMX_REG(i->rm());
  }
  else {
    /* pointer, segment address pair */
    read_virtual_qword(i->seg(), RMAddr(i), (Bit64u *) &op2);
  }

  Bit32s product1 = Bit32s(MMXSW0(op1)) * Bit32s(MMXSW0(op2)) + 0x8000;
  Bit32s product2 = Bit32s(MMXSW1(op1)) * Bit32s(MMXSW1(op2)) + 0x8000;
  Bit32s product3 = Bit32s(MMXSW2(op1)) * Bit32s(MMXSW2(op2)) + 0x8000;
  Bit32s product4 = Bit32s(MMXSW3(op1)) * Bit32s(MMXSW3(op2)) + 0x8000;

  MMXUW0(result) = Bit16u(product1 >> 16);
  MMXUW1(result) = Bit16u(product2 >> 16);
  MMXUW2(result) = Bit16u(product3 >> 16);
  MMXUW3(result) = Bit16u(product4 >> 16);

  /* now write result back to destination */
  BX_WRITE_MMX_REG(i->nnn(), result);
}

/* 0F 0F /r BB */
void BX_CPU_C::PSWAPD_PqQq(bxInstruction_c *i)
{
  BX_CPU_THIS_PTR prepareMMX();

  BxPackedMmxRegister result, op;

  /* op is a register or memory reference */
  if (i->modC0()) {
    op = BX_READ_MMX_REG(i->rm());
  }
  else {
    /* pointer, segment address pair */
    read_virtual_qword(i->seg(), RMAddr(i), (Bit64u *) &op);
  }

  MMXUD0(result) = MMXUD1(op);
  MMXUD1(result) = MMXUD0(op);

  /* now write result back to destination */
  BX_WRITE_MMX_REG(i->nnn(), result);
}

#endif
<|endoftext|>


<commit_before>#include "XXX/kernel.h"
#include "XXX/rawsocket_protocol.h"
#include "XXX/wamp_connector.h"
#include "XXX/wamp_session.h"
#include "XXX/websocket_protocol.h"

#include <memory>
#include <iostream>

using namespace XXX;

void rpc(wamp_invocation& invoke)
{
  invoke.yield( { jalson::json_array({"hello", "world"}) ,{} } );
}

int main(int, char**)
{
  try {

    std::unique_ptr<kernel> the_kernel( new XXX::kernel({}, logger::nolog() ));
    the_kernel->start();

    // Attempt to make a socket connection & build a wamp_session
    auto wconn = wamp_connector::create( the_kernel.get(),
                                         "127.0.0.1", "55555",
                                         false );

    auto connect_status = wconn->completion_future().wait_for(std::chrono::milliseconds(100));

    if (connect_status == std::future_status::timeout)
      throw std::runtime_error("time-out during network connect");

    std::promise<void> promise_on_close;

    std::shared_ptr<wamp_session> session = wconn->create_session(
      [&promise_on_close](XXX::session_handle, bool is_open){
        if (!is_open)
          promise_on_close.set_value();
      });

    // Logon to a WAMP realm, and wait for session to be deemed open
    client_credentials credentials;
    credentials.realm="default_realm";
    credentials.authid="peter";
    credentials.authmethods = {"wampcra"};
    credentials.secret_fn = []() -> std::string { return "secret2"; };

    auto session_open_fut = session->initiate_hello(credentials);

    if (session_open_fut.wait_for(std::chrono::milliseconds(5000)) == std::future_status::timeout)
      throw std::runtime_error("time-out during session logon");

    // Session is now open, register an RPC
    session->provide("inline", jalson::json_object(), rpc);

    // Wait until we get disconnected
    promise_on_close.get_future().wait();

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

<commit_msg>upgrade to recent interface changes<commit_after>#include "XXX/kernel.h"
#include "XXX/rawsocket_protocol.h"
#include "XXX/wamp_connector.h"
#include "XXX/wamp_session.h"
#include "XXX/websocket_protocol.h"

#include <memory>
#include <iostream>

using namespace XXX;

void rpc(wamp_invocation& invoke)
{
  invoke.yield( { jalson::json_array({"hello", "world"}) ,{} } );
}

int main(int, char**)
{
  try {

    std::unique_ptr<kernel> the_kernel( new XXX::kernel({}, logger::nolog() ));

    // Attempt to make a socket connection & build a wamp_session
    auto wconn = wamp_connector::create( the_kernel.get(),
                                         "127.0.0.1", "55555",
                                         false );

    auto connect_status = wconn->completion_future().wait_for(std::chrono::milliseconds(100));

    if (connect_status == std::future_status::timeout)
      throw std::runtime_error("time-out during network connect");

    std::promise<void> promise_on_close;

    std::shared_ptr<wamp_session> session = wconn->create_session<rawsocket_protocol>(
      [&promise_on_close](XXX::session_handle, bool is_open){
        if (!is_open)
          promise_on_close.set_value();
      });

    // Logon to a WAMP realm, and wait for session to be deemed open
    client_credentials credentials;
    credentials.realm="default_realm";
    credentials.authid="peter";
    credentials.authmethods = {"wampcra"};
    credentials.secret_fn = []() -> std::string { return "secret2"; };

    auto session_open_fut = session->initiate_hello(credentials);

    if (session_open_fut.wait_for(std::chrono::milliseconds(5000)) == std::future_status::timeout)
      throw std::runtime_error("time-out during session logon");

    // Session is now open, register an RPC
    session->provide("inline", jalson::json_object(), rpc);

    // Wait until we get disconnected
    promise_on_close.get_future().wait();

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

<|endoftext|>


<commit_before>#include "packet.h"

#include <string.h>
#include <iostream>
#include <cstdlib>

  //Constructor
  Packet::Packet () {
	sequenceNum = 0;
	checkSum = 0;
	ackNack = 0;
        dataBuff[512];
  }
  Packet::Packet (int sn, const char db[505]){
    sequenceNum = sn % 32;
    strcpy(dataBuff, db);
    checkSum = generateCheckSum();
    ackNack =0;
  }
  //Setter Methods
  void Packet::setSequenceNum(int sn){
     sequenceNum = sn;
  }

  void Packet::setCheckSum(int cs){
     checkSum = cs;
  }

  void Packet::setAckNack(int an){
     ackNack = an;
  }

  void Packet::loadDataBuffer(char* data){
    strcpy(dataBuff, data);
  }
  char* Packet::getDataBuffer() {
    return dataBuff;
  }
  //Attach header to the data array
  char* Packet::str(){
	std::cout << "sequenceNum in packet.str(): " << sequenceNum << std::endl;
    std::string tempStr(dataBuff);
    std::string packetString;
    std::string csStr;
	std::string sns;

	std::cout << "sequenceNum in packet.str(): " << sequenceNum << std::endl;
	if (tempStr[0] == '\0') return "\0";

	std::cout << "sequenceNum in packet.str(): " << sequenceNum << std::endl;
    csStr = std::to_string((long long int)checkSum);
    while(csStr.length() < 5) csStr += '0';

	std::cout << "sequenceNum in packet.str(): " << sequenceNum << std::endl;

	sns = std::to_string((long long int)sequenceNum);
	if(sns.length() < 2) sns.insert(0, 1, '0');

    packetString = sns + csStr + std::to_string((long long int)ackNack) + tempStr;

	std::cout << "packetString: " << packetString << std::endl;

    strcpy(packet, packetString.c_str());
    return packet;
  }
  //Getter Methods
  int Packet::getSequenceNum(){
    return sequenceNum;
  }

  int Packet::getCheckSum(){
    return checkSum;
  }

  int Packet::getAckNack(){
    return ackNack;
  }
  bool Packet::chksm() {
    return (checkSum) == generateCheckSum();
  }
  int Packet::generateCheckSum() {
    int cs = 0;
    if(dataBuff == NULL){
      return -1;
    }

    for(int x = 0; x < sizeof(dataBuff); x++) {
      if(dataBuff[x] == '\0') {
        x = sizeof(dataBuff);
        break;
      }
      cs += dataBuff[x];
    }

    if(cs <= 9999) cs *= 10;

    if(cs > 0) return cs;
    return -1;
  }
<commit_msg>Kind of? Let's remove some testing text...<commit_after>#include "packet.h"

#include <string.h>
#include <iostream>
#include <cstdlib>

  //Constructor
  Packet::Packet () {
	sequenceNum = 0;
	checkSum = 0;
	ackNack = 0;
        dataBuff[512];
  }
  Packet::Packet (int sn, const char db[505]){
    sequenceNum = sn % 32;
    strcpy(dataBuff, db);
    checkSum = generateCheckSum();
    ackNack =0;
  }
  //Setter Methods
  void Packet::setSequenceNum(int sn){
     sequenceNum = sn;
  }

  void Packet::setCheckSum(int cs){
     checkSum = cs;
  }

  void Packet::setAckNack(int an){
     ackNack = an;
  }

  void Packet::loadDataBuffer(char* data){
    strcpy(dataBuff, data);
  }
  char* Packet::getDataBuffer() {
    return dataBuff;
  }
  //Attach header to the data array
  char* Packet::str(){
    std::string tempStr(dataBuff);
    std::string packetString;
    std::string csStr;
	std::string sns;

	if (tempStr[0] == '\0') return "\0";

    csStr = std::to_string((long long int)checkSum);
    while(csStr.length() < 5) csStr += '0';

	sns = std::to_string((long long int)sequenceNum);
	if(sns.length() < 2) sns.insert(0, 1, '0');

    packetString = sns + csStr + std::to_string((long long int)ackNack) + tempStr;

    strcpy(packet, packetString.c_str());
    return packet;
  }
  //Getter Methods
  int Packet::getSequenceNum(){
    return sequenceNum;
  }

  int Packet::getCheckSum(){
    return checkSum;
  }

  int Packet::getAckNack(){
    return ackNack;
  }
  bool Packet::chksm() {
    return (checkSum) == generateCheckSum();
  }
  int Packet::generateCheckSum() {
    int cs = 0;
    if(dataBuff == NULL){
      return -1;
    }

    for(int x = 0; x < sizeof(dataBuff); x++) {
      if(dataBuff[x] == '\0') {
        x = sizeof(dataBuff);
        break;
      }
      cs += dataBuff[x];
    }

    if(cs <= 9999) cs *= 10;

    if(cs > 0) return cs;
    return -1;
  }
<|endoftext|>


<commit_before>#include <iostream>

int
sumMultiples(){
	int z = 0;
	for (int i = 1; i <= 1000; i++) {
		if ((i % 3 == 0) || (i % 5 == 0)) {
			z = i + z;
			std::cout << z << std::endl;
		}
	}
	return 0;
}

int
main() {
	char w;
	int z = 0;

	sumMultiples();

	std::cin >> w;
	return 0;
};<commit_msg>Update helloworld.cpp<commit_after>#include <iostream>

int
sumMultiples(){
	int z = 0;
	for (int i = 1; i <= 1000; i++) {
		if ((i % 3 == 0) || (i % 5 == 0)) {
			z = i + z;
			std::cout << z << std::endl;
		}
	}
	return 0;
}

int
main() {
	char w;
	int z = 0;

	sumMultiples();

	std::cin >> w; //auf Windows programmiert, Konsole soll sich nicht schließen
	return 0;
};
<|endoftext|>