<commit_before>// Copyright 2012, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//   * Redistributions of source code must retain the above copyright
//     notice, this list of conditions and the following disclaimer.
//   * Redistributions in binary form must reproduce the above
//     copyright notice, this list of conditions and the following disclaimer
//     in the documentation and/or other materials provided with the
//     distribution.
//   * Neither the name of Google Inc. nor the names of its
//     contributors may be used to endorse or promote products derived from
//     this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// -----------------------------------------------------------------------------
//
//
/// \file
/// Provides an environment for variables and their values, either primitive
/// or Factory-constructible objects.
/// \author dbikel@google.com (Dan Bikel)

#ifndef RERANKER_ENVIRONMENT_IMPL_H_
#define RERANKER_ENVIRONMENT_IMPL_H_

#include <sstream>
#include <string>
#include <tr1/unordered_map>
#include <tr1/unordered_set>
#include <typeinfo>

#include "var-map.H"

namespace reranker {

using std::ostringstream;
using std::string;
using std::tr1::unordered_map;
using std::tr1::unordered_set;

/// Provides a set of named variables and their types, as well as the values
/// for those variable.
///
/// N.B.: Primitive values are stored as strings, and are converted on demand
/// to a concrete primitive type, one of <tt>{bool,int,double,string}</tt>.
/// Because of this, this class only considers variables to have one of
/// four types (even if their concrete types are more specific):
///

///
 primitive
///
 vector of a primitive type
///
 \link reranker::Factory Factory\endlink-constructible type
///
 vector of a \link reranker::Factory Factory\endlink-constructible type
///

///
/// \see Interpreter
class EnvironmentImpl : public Environment {
 public:
  /// Constructs a new, empty environment.
  ///
  /// \param debug the debug level; if greater than 0, various debugging
  ///              messages will be output to <tt>std::cerr</tt>
  EnvironmentImpl(int debug = 0);

  /// Destroys this environment.
  virtual ~EnvironmentImpl() {
    for (unordered_map<string, VarMapBase *>::iterator it = var_map_.begin();
         it != var_map_.end(); ++it) {
      delete it->second;
    }
  }

  /// Returns whether the specified variable has been defined in this
  /// environment.
  virtual bool Defined(const string &varname) const {
    unordered_map<string, string>::const_iterator it = types_.find(varname);
    return it != types_.end();
  }

  /// Sets the specified variable to the value obtained from the following
  /// tokens available from the specified token stream.
  virtual void ReadAndSet(const string &varname, StreamTokenizer &st);

  virtual const string &GetType(const string &varname) const {
    unordered_map<string, string>::const_iterator type_it =
        types_.find(varname);
    if (type_it == types_.end()) {
      // Error or warning.
    }
    return type_it->second;
  }

  virtual VarMapBase *GetVarMap(const string &varname) {
    return GetVarMapForType(GetType(varname));
  }

  /// Retrieves the VarMap instance for the specified type.
  virtual VarMapBase *GetVarMapForType(const string &type) {
    string lookup_type = type;
    // First, check if this is a concrete Factory-constructible type.
    // If so, map to its abstract type name.
    unordered_map<string, string>::const_iterator factory_type_it =
        concrete_to_factory_type_.find(type);
    if (factory_type_it != concrete_to_factory_type_.end()) {
      lookup_type = factory_type_it->second;
    }

    unordered_map<string, VarMapBase *>::const_iterator var_map_it =
        var_map_.find(lookup_type);
    if (var_map_it == var_map_.end()) {
      // Error.
    }
    return var_map_it->second;
  }

  /// \copydoc reranker::Environment::Copy
  virtual Environment *Copy() const {
    EnvironmentImpl *new_env = new EnvironmentImpl(*this);
    // Now go through and create copies of each VarMap.
    for (unordered_map<string, VarMapBase *>::iterator new_env_var_map_it =
             new_env->var_map_.begin();
         new_env_var_map_it != new_env->var_map_.end(); ++new_env_var_map_it) {
      cerr << "Creating copy of VarMap<" << new_env_var_map_it->second->Name()
           << ">" << endl;
      new_env_var_map_it->second = new_env_var_map_it->second->Copy(new_env);
    }
    return new_env;
  }

  /// Retrieves the value of the variable with the specified name and puts
  /// into into the object pointed to by the <tt>value</tt> parameter.
  ///
  /// \param      varname the name of the variable whose value is to be
  ///             retrieved
  /// \param[out] value a pointer to the object whose value is to be set
  /// \return whether the specified variable exists and its value was
  ///         successfully set by this method
  template<typename T>
  bool Get(const string &varname, T *value) const;

 private:
  /// Infer the type based on the next token and its token type.
  string InferType(const string &varname,
                   const StreamTokenizer &st, bool is_vector,
                   bool *is_object_type);

  /// A map from all variable names to their types.
  unordered_map<string, string> types_;

  /// A map from type name strings (as returned by the \link TypeName \endlink
  /// method) to VarMap instances for those types.
  unordered_map<string, VarMapBase *> var_map_;

  /// A map from concrete Factory-constructible type names to their abstract
  /// Factory type names.
  unordered_map<string, string> concrete_to_factory_type_;

  int debug_;
};

template<typename T>
bool
EnvironmentImpl::Get(const string &varname, T *value) const {
  unordered_map<string, string>::const_iterator type_it =
      types_.find(varname);
  if (type_it == types_.end()) {
    if (debug_ >= 1) {
      ostringstream err_ss;
      err_ss << "Environment::Get: error: no value for variable "
             << varname;
      cerr << err_ss.str() << endl;
    }
    return false;
  }

  // Now that we have the type, look up the VarMap.
  const string &type = type_it->second;
  unordered_map<string, VarMapBase*>::const_iterator var_map_it =
      var_map_.find(type);

  if (var_map_it == var_map_.end()) {
    ostringstream err_ss;
    err_ss << "Environment::Get: error: types_ and var_map_ data members "
           << "are out of sync";
    throw std::runtime_error(err_ss.str());
  }

  // Do a dynamic_cast down to the type-specific VarMap.
  VarMapBase *var_map = var_map_it->second;
  VarMap<T> *typed_var_map = dynamic_cast<VarMap<T> *>(var_map);

  if (typed_var_map == NULL) {
    ostringstream err_ss;
    err_ss << "Environment::Get: error: no value for variable "
           << varname << " of type " << typeid(*value).name()
           << "; perhaps you meant " << type << "?";
    cerr << err_ss.str() << endl;
    return false;
  }
  bool success = typed_var_map->Get(varname, value);
  if (!success) {
    ostringstream err_ss;
    err_ss << "Environment::Get: error: no value for variable "
           << varname << " of type " << typeid(*value).name()
           << "; types_ and var_map_ data members are out of sync";
    throw std::runtime_error(err_ss.str());
  }
  return success;
  }

}  // namespace reranker

#endif
<commit_msg>Removed debugging code.<commit_after>// Copyright 2012, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//   * Redistributions of source code must retain the above copyright
//     notice, this list of conditions and the following disclaimer.
//   * Redistributions in binary form must reproduce the above
//     copyright notice, this list of conditions and the following disclaimer
//     in the documentation and/or other materials provided with the
//     distribution.
//   * Neither the name of Google Inc. nor the names of its
//     contributors may be used to endorse or promote products derived from
//     this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// -----------------------------------------------------------------------------
//
//
/// \file
/// Provides an environment for variables and their values, either primitive
/// or Factory-constructible objects.
/// \author dbikel@google.com (Dan Bikel)

#ifndef RERANKER_ENVIRONMENT_IMPL_H_
#define RERANKER_ENVIRONMENT_IMPL_H_

#include <sstream>
#include <string>
#include <tr1/unordered_map>
#include <tr1/unordered_set>
#include <typeinfo>

#include "var-map.H"

namespace reranker {

using std::ostringstream;
using std::string;
using std::tr1::unordered_map;
using std::tr1::unordered_set;

/// Provides a set of named variables and their types, as well as the values
/// for those variable.
///
/// N.B.: Primitive values are stored as strings, and are converted on demand
/// to a concrete primitive type, one of <tt>{bool,int,double,string}</tt>.
/// Because of this, this class only considers variables to have one of
/// four types (even if their concrete types are more specific):
///

///
 primitive
///
 vector of a primitive type
///
 \link reranker::Factory Factory\endlink-constructible type
///
 vector of a \link reranker::Factory Factory\endlink-constructible type
///

///
/// \see Interpreter
class EnvironmentImpl : public Environment {
 public:
  /// Constructs a new, empty environment.
  ///
  /// \param debug the debug level; if greater than 0, various debugging
  ///              messages will be output to <tt>std::cerr</tt>
  EnvironmentImpl(int debug = 0);

  /// Destroys this environment.
  virtual ~EnvironmentImpl() {
    for (unordered_map<string, VarMapBase *>::iterator it = var_map_.begin();
         it != var_map_.end(); ++it) {
      delete it->second;
    }
  }

  /// Returns whether the specified variable has been defined in this
  /// environment.
  virtual bool Defined(const string &varname) const {
    unordered_map<string, string>::const_iterator it = types_.find(varname);
    return it != types_.end();
  }

  /// Sets the specified variable to the value obtained from the following
  /// tokens available from the specified token stream.
  virtual void ReadAndSet(const string &varname, StreamTokenizer &st);

  virtual const string &GetType(const string &varname) const {
    unordered_map<string, string>::const_iterator type_it =
        types_.find(varname);
    if (type_it == types_.end()) {
      // Error or warning.
    }
    return type_it->second;
  }

  virtual VarMapBase *GetVarMap(const string &varname) {
    return GetVarMapForType(GetType(varname));
  }

  /// Retrieves the VarMap instance for the specified type.
  virtual VarMapBase *GetVarMapForType(const string &type) {
    string lookup_type = type;
    // First, check if this is a concrete Factory-constructible type.
    // If so, map to its abstract type name.
    unordered_map<string, string>::const_iterator factory_type_it =
        concrete_to_factory_type_.find(type);
    if (factory_type_it != concrete_to_factory_type_.end()) {
      lookup_type = factory_type_it->second;
    }

    unordered_map<string, VarMapBase *>::const_iterator var_map_it =
        var_map_.find(lookup_type);
    if (var_map_it == var_map_.end()) {
      // Error.
    }
    return var_map_it->second;
  }

  /// \copydoc reranker::Environment::Copy
  virtual Environment *Copy() const {
    EnvironmentImpl *new_env = new EnvironmentImpl(*this);
    // Now go through and create copies of each VarMap.
    for (unordered_map<string, VarMapBase *>::iterator new_env_var_map_it =
             new_env->var_map_.begin();
         new_env_var_map_it != new_env->var_map_.end(); ++new_env_var_map_it) {
      new_env_var_map_it->second = new_env_var_map_it->second->Copy(new_env);
    }
    return new_env;
  }

  /// Retrieves the value of the variable with the specified name and puts
  /// into into the object pointed to by the <tt>value</tt> parameter.
  ///
  /// \param      varname the name of the variable whose value is to be
  ///             retrieved
  /// \param[out] value a pointer to the object whose value is to be set
  /// \return whether the specified variable exists and its value was
  ///         successfully set by this method
  template<typename T>
  bool Get(const string &varname, T *value) const;

 private:
  /// Infer the type based on the next token and its token type.
  string InferType(const string &varname,
                   const StreamTokenizer &st, bool is_vector,
                   bool *is_object_type);

  /// A map from all variable names to their types.
  unordered_map<string, string> types_;

  /// A map from type name strings (as returned by the \link TypeName \endlink
  /// method) to VarMap instances for those types.
  unordered_map<string, VarMapBase *> var_map_;

  /// A map from concrete Factory-constructible type names to their abstract
  /// Factory type names.
  unordered_map<string, string> concrete_to_factory_type_;

  int debug_;
};

template<typename T>
bool
EnvironmentImpl::Get(const string &varname, T *value) const {
  unordered_map<string, string>::const_iterator type_it =
      types_.find(varname);
  if (type_it == types_.end()) {
    if (debug_ >= 1) {
      ostringstream err_ss;
      err_ss << "Environment::Get: error: no value for variable "
             << varname;
      cerr << err_ss.str() << endl;
    }
    return false;
  }

  // Now that we have the type, look up the VarMap.
  const string &type = type_it->second;
  unordered_map<string, VarMapBase*>::const_iterator var_map_it =
      var_map_.find(type);

  if (var_map_it == var_map_.end()) {
    ostringstream err_ss;
    err_ss << "Environment::Get: error: types_ and var_map_ data members "
           << "are out of sync";
    throw std::runtime_error(err_ss.str());
  }

  // Do a dynamic_cast down to the type-specific VarMap.
  VarMapBase *var_map = var_map_it->second;
  VarMap<T> *typed_var_map = dynamic_cast<VarMap<T> *>(var_map);

  if (typed_var_map == NULL) {
    ostringstream err_ss;
    err_ss << "Environment::Get: error: no value for variable "
           << varname << " of type " << typeid(*value).name()
           << "; perhaps you meant " << type << "?";
    cerr << err_ss.str() << endl;
    return false;
  }
  bool success = typed_var_map->Get(varname, value);
  if (!success) {
    ostringstream err_ss;
    err_ss << "Environment::Get: error: no value for variable "
           << varname << " of type " << typeid(*value).name()
           << "; types_ and var_map_ data members are out of sync";
    throw std::runtime_error(err_ss.str());
  }
  return success;
  }

}  // namespace reranker

#endif
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (directui@nokia.com)
**
** This file is part of meegotouch-controlpanelapplets.
**
** If you have questions regarding the use of this file, please contact
** Nokia at directui@nokia.com.
**
** This library is free software; you can redistribute it and/or
** modify it under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation
** and appearing in the file LICENSE.LGPL included in the packaging
** of this file.
**
****************************************************************************/
#include "resetwidget.h"

#include <MContainer>
#include <MLayout>
#include <MBanner>
#include <MApplication>
#include <MHelpButton>
#include <QGraphicsLinearLayout>
#include <MLinearLayoutPolicy>
#include <MButton>
#include <MDialog>
#include <MMessageBox>
#include <MSeparator>
#include <MStylableWidget>

#undef DEBUG
#include "../debug.h"

#define qtTrIdShort(id) qtTrId(id).split(QChar(0x9c)).last()

ResetWidget::ResetWidget (
        ResetBusinessLogic     *resetBusinessLogic,
        QGraphicsWidget        *parent) :
    DcpWidget (parent),
    m_ResetBusinessLogic (resetBusinessLogic),
    m_currentPlan (None)
{
    createContent();

    connect (resetBusinessLogic, SIGNAL (gotAccess ()),
             this, SLOT (doTheWork ()));
}

ResetWidget::~ResetWidget ()
{
}

void
ResetWidget::createContent ()
{
    MLayout             *layout;
    MLinearLayoutPolicy *policy;
    MButton             *restoreButton;
    MButton             *clearButton;
    MSeparator            *spacer;

    /*
     *
     */
    layout = new MLayout;
    policy = new MLinearLayoutPolicy (layout, Qt::Vertical);
    policy->setContentsMargins (0., 0., 0., 0.);
    policy->setSpacing (0.);

    /*
     *
     */
    spacer = new MSeparator;
    // Using this one instead of "CommonSpacer", margins look even.
    spacer->setStyleName ("CommonLargeSpacer");
    policy->addItem (spacer);

    /*
     * The first button.
     */
    //% "Restore original settings"
    restoreButton = new MButton (qtTrId("qtn_rset_restore"));
    restoreButton->setStyleName ("CommonSingleButtonInverted");
    restoreButton->setObjectName ("ResetAppletRFSButton");
    connect (restoreButton, SIGNAL(clicked()),
            this, SLOT(restoreActivated()));

    /*
     * The second button.
     */
    //% "Clear device"
    clearButton = new MButton (qtTrId("qtn_rset_clear"));
    clearButton->setStyleName ("CommonSingleButtonInverted");
    clearButton->setObjectName ("ResetAppletCUDButton");
    connect (clearButton, SIGNAL(clicked()),
            this, SLOT(clearActivated()));

    addButtonContainer (policy, restoreButton, clearButton);
    policy->addStretch();
    /*
     *
     */
    layout->setPolicy (policy);
    setLayout (layout);
}

MHelpButton *
ResetWidget::createHelpButton (const QString &link)
{
    MHelpButton *helpButton = new MHelpButton (link);
    helpButton->setViewType (MButton::iconType);
    helpButton->setIconID ("icon-s-description-inverse");
    helpButton->setStyleName ("CommonRightIcon");
    return helpButton;
}

void
ResetWidget::addButtonContainer (
            MLinearLayoutPolicy *mainLayout,
            MButton             *button1,
            MButton             *button2)
{
    MSeparator          *spacer;
    QGraphicsLinearLayout *layout =
        new QGraphicsLinearLayout (Qt::Vertical);
    layout->setContentsMargins (0,0,0,0);
    layout->setSpacing (0);

    /*
     * One spacer
     */
    spacer = new MSeparator;
    spacer->setStyleName ("CommonSpacer");

    /*
     * Button 1 layout
     */
    QGraphicsLinearLayout *button1layout =
        new QGraphicsLinearLayout (Qt::Horizontal);
    button1layout->setContentsMargins (0,0,0,0);
    button1layout->setSpacing (0);

    MStylableWidget *imgSpacer1 = new MStylableWidget;
    imgSpacer1->setStyleName ("CommonLeftIcon");
    button1layout->addItem (imgSpacer1);

    button1layout->addStretch ();

    button1layout->addItem (button1);
    button1layout->setAlignment (button1, Qt::AlignCenter);

    button1layout->addStretch ();

    MHelpButton *hp1 = createHelpButton ("IDUG_MEEGO_SETT_RESTORE.html");
    button1layout->addItem (hp1);
    button1layout->setAlignment (hp1, Qt::AlignVCenter);

    layout->addItem (button1layout);
    layout->setAlignment (button1layout, Qt::AlignCenter);

    layout->addItem (spacer);

    /*
     * Button 2 layout
     */
    QGraphicsLinearLayout *button2layout =
        new QGraphicsLinearLayout (Qt::Horizontal);
    button2layout->setContentsMargins (0,0,0,0);
    button2layout->setSpacing (0);

    MStylableWidget *imgSpacer2 = new MStylableWidget;
    imgSpacer2->setStyleName ("CommonLeftIcon");
    button2layout->addItem (imgSpacer2);
    button2layout->addStretch ();

    button2layout->addItem (button2);
    button2layout->setAlignment (button2, Qt::AlignCenter);

    button2layout->addStretch ();
    MHelpButton *hp2 = createHelpButton ("IDUG_MEEGO_SETT_CLEARDEVICE.html");
    button2layout->addItem (hp2);
    button2layout->setAlignment (hp2, Qt::AlignVCenter);

    layout->addItem (button2layout);
    layout->setAlignment (button2layout, Qt::AlignCenter);

    /*
     *
     */
    mainLayout->addItem (layout);
    mainLayout->setStretchFactor (layout, 0);
}

void
ResetWidget::restoreActivated ()
{
    MDialog   *dialog;

    if (m_ResetBusinessLogic->isUsbConnected ())
    {
        showMassStorageWarning ();
        return;
    }

    //% "Restore original settings?"
    QString question = qtTrId ("qtn_rset_restore_query");
    // It is a bit ugly, but translations contains \n stuffs:
    question.replace ("\\n", "
");
    question.replace ("\n", "
");

    //% "Restore original settings?"
    dialog = new MMessageBox (qtTrId ("qtn_rset_restore_query_title"),
                              question, M::YesButton | M::NoButton);
    connect (dialog, SIGNAL (accepted ()), SLOT (restoreConfirmed ()));

    dialog->appear (MApplication::instance ()->activeWindow (),
                    MSceneWindow::DestroyWhenDone);
}

void
ResetWidget::restoreConfirmed ()
{
    SYS_DEBUG ("user choosen yes");
    m_currentPlan = ResetSettings;
    m_ResetBusinessLogic->getAccess ();
}

void
ResetWidget::clearActivated ()
{
    MDialog   *dialog;

    if (m_ResetBusinessLogic->isUsbConnected ())
    {
        showMassStorageWarning ();
        return;
    }

    //% "Clear all user data and restore original settings?"
    QString    question = qtTrId("qtn_rset_clear_query");
    question.replace ("\\n", "
");
    question.replace ("\n", "
");

    //% "Clear all data?"
    dialog = new MMessageBox (qtTrId ("qtn_rset_clear_query_title"),
                              question, M::YesButton | M::NoButton);
    connect (dialog, SIGNAL (accepted ()), SLOT (clearConfirmed ()));

    dialog->appear (MApplication::instance ()->activeWindow (),
                    MSceneWindow::DestroyWhenDone);
}

void
ResetWidget::clearConfirmed ()
{
    SYS_DEBUG ("user choosen yes");
    m_currentPlan = ClearData;
    m_ResetBusinessLogic->getAccess ();
}

void
ResetWidget::doTheWork ()
{
    switch (m_currentPlan)
    {
        case ResetSettings:
            m_ResetBusinessLogic->performRestoreSettings();
            break;
        case ClearData:
            m_ResetBusinessLogic->performClearData();
            break;
        default:
            SYS_WARNING ("Got access, but no plan ?!");
            break;
    }
    m_currentPlan = None;
}

void
ResetWidget::showMassStorageWarning ()
{
    SYS_DEBUG ("");
    infoBanner = new MBanner;
    infoBanner->setStyleName ("InformationBanner");
    infoBanner->setObjectName ("InfoBanner");

    //% "Device resets are not possible while USB is connected in mass storage mode."
    infoBanner->setTitle (qtTrId ("qtn_rset_not_possible"));

    infoBanner->appear (MApplication::instance ()->activeWindow (),
                        MSceneWindow::DestroyWhenDone);
}

<commit_msg>ResetApplet: remove an unneeded include<commit_after>/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (directui@nokia.com)
**
** This file is part of meegotouch-controlpanelapplets.
**
** If you have questions regarding the use of this file, please contact
** Nokia at directui@nokia.com.
**
** This library is free software; you can redistribute it and/or
** modify it under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation
** and appearing in the file LICENSE.LGPL included in the packaging
** of this file.
**
****************************************************************************/
#include "resetwidget.h"

#include <MLayout>
#include <MBanner>
#include <MApplication>
#include <MHelpButton>
#include <QGraphicsLinearLayout>
#include <MLinearLayoutPolicy>
#include <MButton>
#include <MDialog>
#include <MMessageBox>
#include <MSeparator>
#include <MStylableWidget>

#undef DEBUG
#include "../debug.h"

#define qtTrIdShort(id) qtTrId(id).split(QChar(0x9c)).last()

ResetWidget::ResetWidget (
        ResetBusinessLogic     *resetBusinessLogic,
        QGraphicsWidget        *parent) :
    DcpWidget (parent),
    m_ResetBusinessLogic (resetBusinessLogic),
    m_currentPlan (None)
{
    createContent();

    connect (resetBusinessLogic, SIGNAL (gotAccess ()),
             this, SLOT (doTheWork ()));
}

ResetWidget::~ResetWidget ()
{
}

void
ResetWidget::createContent ()
{
    MLayout             *layout;
    MLinearLayoutPolicy *policy;
    MButton             *restoreButton;
    MButton             *clearButton;
    MSeparator          *spacer;

    /*
     *
     */
    layout = new MLayout;
    policy = new MLinearLayoutPolicy (layout, Qt::Vertical);
    policy->setContentsMargins (0., 0., 0., 0.);
    policy->setSpacing (0.);

    /*
     *
     */
    spacer = new MSeparator;
    // Using this one instead of "CommonSpacer", margins look even.
    spacer->setStyleName ("CommonLargeSpacer");
    policy->addItem (spacer);

    /*
     * The first button.
     */
    //% "Restore original settings"
    restoreButton = new MButton (qtTrId("qtn_rset_restore"));
    restoreButton->setStyleName ("CommonSingleButtonInverted");
    restoreButton->setObjectName ("ResetAppletRFSButton");
    connect (restoreButton, SIGNAL(clicked()),
            this, SLOT(restoreActivated()));

    /*
     * The second button.
     */
    //% "Clear device"
    clearButton = new MButton (qtTrId("qtn_rset_clear"));
    clearButton->setStyleName ("CommonSingleButtonInverted");
    clearButton->setObjectName ("ResetAppletCUDButton");
    connect (clearButton, SIGNAL(clicked()),
            this, SLOT(clearActivated()));

    addButtonContainer (policy, restoreButton, clearButton);
    policy->addStretch();
    /*
     *
     */
    layout->setPolicy (policy);
    setLayout (layout);
}

MHelpButton *
ResetWidget::createHelpButton (const QString &link)
{
    MHelpButton *helpButton = new MHelpButton (link);
    helpButton->setViewType (MButton::iconType);
    helpButton->setIconID ("icon-s-description-inverse");
    helpButton->setStyleName ("CommonRightIcon");
    return helpButton;
}

void
ResetWidget::addButtonContainer (
            MLinearLayoutPolicy *mainLayout,
            MButton             *button1,
            MButton             *button2)
{
    MSeparator          *spacer;
    QGraphicsLinearLayout *layout =
        new QGraphicsLinearLayout (Qt::Vertical);
    layout->setContentsMargins (0,0,0,0);
    layout->setSpacing (0);

    /*
     * One spacer
     */
    spacer = new MSeparator;
    spacer->setStyleName ("CommonSpacer");

    /*
     * Button 1 layout
     */
    QGraphicsLinearLayout *button1layout =
        new QGraphicsLinearLayout (Qt::Horizontal);
    button1layout->setContentsMargins (0,0,0,0);
    button1layout->setSpacing (0);

    MStylableWidget *imgSpacer1 = new MStylableWidget;
    imgSpacer1->setStyleName ("CommonLeftIcon");
    button1layout->addItem (imgSpacer1);

    button1layout->addStretch ();

    button1layout->addItem (button1);
    button1layout->setAlignment (button1, Qt::AlignCenter);

    button1layout->addStretch ();

    MHelpButton *hp1 = createHelpButton ("IDUG_MEEGO_SETT_RESTORE.html");
    button1layout->addItem (hp1);
    button1layout->setAlignment (hp1, Qt::AlignVCenter);

    layout->addItem (button1layout);
    layout->setAlignment (button1layout, Qt::AlignCenter);

    layout->addItem (spacer);

    /*
     * Button 2 layout
     */
    QGraphicsLinearLayout *button2layout =
        new QGraphicsLinearLayout (Qt::Horizontal);
    button2layout->setContentsMargins (0,0,0,0);
    button2layout->setSpacing (0);

    MStylableWidget *imgSpacer2 = new MStylableWidget;
    imgSpacer2->setStyleName ("CommonLeftIcon");
    button2layout->addItem (imgSpacer2);
    button2layout->addStretch ();

    button2layout->addItem (button2);
    button2layout->setAlignment (button2, Qt::AlignCenter);

    button2layout->addStretch ();
    MHelpButton *hp2 = createHelpButton ("IDUG_MEEGO_SETT_CLEARDEVICE.html");
    button2layout->addItem (hp2);
    button2layout->setAlignment (hp2, Qt::AlignVCenter);

    layout->addItem (button2layout);
    layout->setAlignment (button2layout, Qt::AlignCenter);

    /*
     *
     */
    mainLayout->addItem (layout);
    mainLayout->setStretchFactor (layout, 0);
}

void
ResetWidget::restoreActivated ()
{
    MDialog   *dialog;

    if (m_ResetBusinessLogic->isUsbConnected ())
    {
        showMassStorageWarning ();
        return;
    }

    //% "Restore original settings?"
    QString question = qtTrId ("qtn_rset_restore_query");
    // It is a bit ugly, but translations contains \n stuffs:
    question.replace ("\\n", "
");
    question.replace ("\n", "
");

    //% "Restore original settings?"
    dialog = new MMessageBox (qtTrId ("qtn_rset_restore_query_title"),
                              question, M::YesButton | M::NoButton);
    connect (dialog, SIGNAL (accepted ()), SLOT (restoreConfirmed ()));

    dialog->appear (MApplication::instance ()->activeWindow (),
                    MSceneWindow::DestroyWhenDone);
}

void
ResetWidget::restoreConfirmed ()
{
    SYS_DEBUG ("user choosen yes");
    m_currentPlan = ResetSettings;
    m_ResetBusinessLogic->getAccess ();
}

void
ResetWidget::clearActivated ()
{
    MDialog   *dialog;

    if (m_ResetBusinessLogic->isUsbConnected ())
    {
        showMassStorageWarning ();
        return;
    }

    //% "Clear all user data and restore original settings?"
    QString    question = qtTrId("qtn_rset_clear_query");
    question.replace ("\\n", "
");
    question.replace ("\n", "
");

    //% "Clear all data?"
    dialog = new MMessageBox (qtTrId ("qtn_rset_clear_query_title"),
                              question, M::YesButton | M::NoButton);
    connect (dialog, SIGNAL (accepted ()), SLOT (clearConfirmed ()));

    dialog->appear (MApplication::instance ()->activeWindow (),
                    MSceneWindow::DestroyWhenDone);
}

void
ResetWidget::clearConfirmed ()
{
    SYS_DEBUG ("user choosen yes");
    m_currentPlan = ClearData;
    m_ResetBusinessLogic->getAccess ();
}

void
ResetWidget::doTheWork ()
{
    switch (m_currentPlan)
    {
        case ResetSettings:
            m_ResetBusinessLogic->performRestoreSettings();
            break;
        case ClearData:
            m_ResetBusinessLogic->performClearData();
            break;
        default:
            SYS_WARNING ("Got access, but no plan ?!");
            break;
    }
    m_currentPlan = None;
}

void
ResetWidget::showMassStorageWarning ()
{
    SYS_DEBUG ("");
    infoBanner = new MBanner;
    infoBanner->setStyleName ("InformationBanner");
    infoBanner->setObjectName ("InfoBanner");

    //% "Device resets are not possible while USB is connected in mass storage mode."
    infoBanner->setTitle (qtTrId ("qtn_rset_not_possible"));

    infoBanner->appear (MApplication::instance ()->activeWindow (),
                        MSceneWindow::DestroyWhenDone);
}

<|endoftext|>


<commit_before>#include "gen.h"
#include <set>
#include <cassert>
#include <cstring>
#include <cstdio>
#include <time.h>
#include <unistd.h>
#include <pthread.h>
#include <algorithm>
#include <vector>
#ifdef __clang__
#include "omp.h"
#else
#include <omp.h>
#endif

const weight_t MAX_WEIGHT = 1.0;

//
// Global data
//
vid_t vertexCount;
eid_t edgesCount;
eid_t *edgesIds;
Edge *edges;
bool *isCoolEdge;
int threadsCount;
int iterationNumber;
vid_t *rev;
vid_t *que;

//
// BFS-reorder specific variable
//
bool *componentEnd;

//
// Edge comparators
//
bool EdgeDestCmp::operator()(const Edge& a, const Edge& b) const {
    if (a.dest != b.dest) return a.dest < b.dest;
    return a.weight < b.weight;
}

bool EdgeWeightCmp::operator()(const Edge& a, const Edge& b) const {
    return a.weight < b.weight;
}

//
// Reorder functions
//
void doReorderBfs() {
    stickThisThreadToCore(0);

    //componentEnd = new bool[vertexCount]();
    bool *visit = new bool[vertexCount]();
    que = static_cast<vid_t*>(malloc(sizeof(vid_t) * vertexCount));
    rev = static_cast<vid_t*>(malloc(sizeof(vid_t) * vertexCount));
    memset(que, 0xc0, sizeof(vid_t) * vertexCount);

    Eo(vertexDegree(0));

    std::vector<pev> largeVertexes;
    for (vid_t v = 0; v < vertexCount; ++v) if (vertexDegree(v) > 99) {
        visit[v] = true;
        //que[v] = v;
        largeVertexes.push_back(pev(vertexDegree(v), v));
    }
    sort(largeVertexes.begin(), largeVertexes.end());
    const vid_t threadOffset = vertexCount / threadsCount;
    for (vid_t i = 0; i < largeVertexes.size(); i += threadsCount) {
        const vid_t from = i;
        const vid_t to = std::min<vid_t>(largeVertexes.size(), i + threadsCount);
        std::random_shuffle(largeVertexes.begin() + from, largeVertexes.begin() + to);
    }
    for (vid_t i = 0; i < largeVertexes.size(); ++i) {
        int toThread = i % threadsCount;
        vid_t toPos = i / threadsCount;
        vid_t pos = toThread * threadOffset + toPos;
        assert(que[pos] < 0);
        assert(pos < vertexCount);
        que[pos] = largeVertexes[i].second;
    }

    vid_t fr = 0, bc = 0;
    for (vid_t i = 0; i < vertexCount; ++i) if (!visit[i]) {
        while (bc < vertexCount && que[bc] >= 0) ++bc;
        que[bc++] = i;
        visit[i] = true;
        while (fr < bc) {
            const vid_t v = que[fr++];
            for (eid_t e = edgesIds[v]; e < edgesIds[v + 1]; ++e) {
                const vid_t u = edges[e].dest;
                if (visit[u]) continue;
                visit[u] = true;
                while (bc < vertexCount && que[bc] >= 0) ++bc;
                que[bc++] = u;
            }
        }
        //componentEnd[bc - 1] = true;
    }
    while (bc < vertexCount && que[bc] >= 0) ++bc;
    E(largeVertexes.size()); Eo(double(largeVertexes.size()) / vertexCount);
    E(fr); E(bc); Eo(vertexCount);
    assert(bc == vertexCount);
    delete[] visit;

#pragma omp parallel for
    for (vid_t i = 0; i < vertexCount; ++i)
        rev[que[i]] = i;

    eid_t *nextEdgesIds = static_cast<eid_t*>(malloc(sizeof(eid_t) * (vertexCount + 1)));
    Edge *nextEdges = static_cast<Edge*>(malloc(sizeof(Edge) * edgesCount));
    eid_t *sumEdges = new eid_t[threadsCount];
    memset(sumEdges, 0, sizeof(eid_t) * threadsCount);
    nextEdgesIds[0] = 0;
    for (int i = 0; i < threadsCount; ++i) {
        stickThisThreadToCore(i);
        const vid_t vertexBegin = int64_t(vertexCount) * (i + 0) / threadsCount;
        const vid_t vertexEnd   = int64_t(vertexCount) * (i + 1) / threadsCount;
        for (vid_t v = vertexBegin; v < vertexEnd; ++v) {
            const vid_t nextv = que[v];
            nextEdgesIds[v + 1] = nextEdgesIds[v] + edgesIds[nextv + 1] - edgesIds[nextv];
            sumEdges[i] += edgesIds[nextv + 1] - edgesIds[nextv];
        }
    }
    std::sort(sumEdges, sumEdges + threadsCount);
    double disbalanceFactor = double(sumEdges[threadsCount - 1]) / sumEdges[0];
    E(sumEdges[0]); E(sumEdges[threadsCount - 1]);Eo(disbalanceFactor);
    if (disbalanceFactor > 1.5 && false) {
        free(nextEdges);
        free(nextEdgesIds);
        goto clean;
    }
#pragma omp parallel
    {
        const int i = omp_get_thread_num();
        stickThisThreadToCore(i);
        const vid_t vertexBegin = int64_t(vertexCount) * i / threadsCount;
        const vid_t vertexEnd   = int64_t(vertexCount) * (i + 1) / threadsCount;
        for (vid_t v = vertexBegin; v < vertexEnd; ++v) {
            const vid_t nextv = que[v];
            for (eid_t e = edgesIds[nextv]; e < edgesIds[nextv + 1]; ++e) {
                nextEdges[nextEdgesIds[v] + e - edgesIds[nextv]] = edges[e];
                nextEdges[nextEdgesIds[v] + e - edgesIds[nextv]].dest = rev[edges[e].dest];
            }
        }
    }

    free(edges);
    free(edgesIds);
    edges = nextEdges;
    edgesIds = nextEdgesIds;
clean:
    //free(que);
    //free(rev);
    delete[] sumEdges;
}

void doReorderSimple() {
    stickThisThreadToCore(0);

    bool *visit = new bool[vertexCount]();
    que = static_cast<vid_t*>(malloc(sizeof(vid_t) * vertexCount));
    rev = static_cast<vid_t*>(malloc(sizeof(vid_t) * vertexCount));
    vid_t pos = 0;
    for (vid_t v = 0; v < vertexCount; ++v) if (!visit[v]) {
        visit[v] = true;
        que[pos++] = v;
        for (eid_t e = edgesIds[v]; e < edgesIds[v + 1]; ++e) {
            const vid_t u = edges[e].dest;
            if (visit[u]) continue;
            visit[u] = true;
            que[pos++] = u;
        }
    }
    assert(pos == vertexCount);
    delete[] visit;

#pragma omp parallel for
    for (vid_t i = 0; i < vertexCount; ++i)
        rev[que[i]] = i;

    eid_t *nextEdgesIds = static_cast<eid_t*>(malloc(sizeof(eid_t) * (vertexCount + 1)));
    Edge *nextEdges = static_cast<Edge*>(malloc(sizeof(Edge) * edgesCount));
    nextEdgesIds[0] = 0;
    for (int i = 0; i < threadsCount; ++i) {
        stickThisThreadToCore(i);
        const vid_t vertexBegin = int64_t(vertexCount) * (i + 0) / threadsCount;
        const vid_t vertexEnd   = int64_t(vertexCount) * (i + 1) / threadsCount;
        for (vid_t v = vertexBegin; v < vertexEnd; ++v) {
            const vid_t nextv = que[v];
            nextEdgesIds[v + 1] = nextEdgesIds[v] + edgesIds[nextv + 1] - edgesIds[nextv];
        }
    }
#pragma omp parallel
    {
        const int i = omp_get_thread_num();
        stickThisThreadToCore(i);
        const vid_t vertexBegin = int64_t(vertexCount) * i / threadsCount;
        const vid_t vertexEnd   = int64_t(vertexCount) * (i + 1) / threadsCount;
        for (vid_t v = vertexBegin; v < vertexEnd; ++v) {
            const vid_t nextv = que[v];
            for (eid_t e = edgesIds[nextv]; e < edgesIds[nextv + 1]; ++e) {
                nextEdges[nextEdgesIds[v] + e - edgesIds[nextv]] = edges[e];
                nextEdges[nextEdgesIds[v] + e - edgesIds[nextv]].dest = rev[edges[e].dest];
            }
        }
    }
    free(que);
    //free(rev);
    free(edges);
    free(edgesIds);
    edges = nextEdges;
    edgesIds = nextEdgesIds;
}

//
// Read input data
//
void readAll(char *filename) {
    iterationNumber = 0;
#pragma omp parallel
    {
#pragma omp master
        {
            threadsCount = omp_get_num_threads();
        }
    }
    Eo(threadsCount);

    FILE *f = fopen(filename, "rb");
    assert(f);

    fread(&vertexCount, sizeof(vid_t), 1, f);
    fread(&edgesCount, sizeof(eid_t), 1, f);

    // NUMA-specific part
    // Each core allocate memory and read data, which will processed on this core
    edgesIds = (eid_t*)malloc(sizeof(eid_t) * (vertexCount + 1));
    edges = (Edge*)malloc(sizeof(Edge) * (edgesCount));

    for (int i = 0; i < threadsCount; ++i) {
        stickThisThreadToCore(i);
        const int vertexBegin = int64_t(vertexCount + 1) * i / threadsCount;
        const int vertexEnd   = int64_t(vertexCount + 1) * (i + 1) / threadsCount;
        fread(edgesIds + vertexBegin, sizeof(eid_t), vertexEnd - vertexBegin, f);
    }

    for (int i = 0; i < threadsCount; ++i) {
        stickThisThreadToCore(i);
        const int vertexBegin = int64_t(vertexCount) * i / threadsCount;
        const int vertexEnd   = int64_t(vertexCount) * (i + 1) / threadsCount;
        const int edgeBegin   = edgesIds[vertexBegin];
        const int edgeEnd     = edgesIds[vertexEnd];
        fread(edges + edgeBegin, sizeof(Edge), edgeEnd - edgeBegin, f);
    }
    fclose(f);
}

void convertAll(graph_t *G) {
    iterationNumber = 0;
#pragma omp parallel
    {
#pragma omp master
        {
            threadsCount = omp_get_num_threads();
        }
    }

    //std::set<weight_t> allWeight;

    // TODO NUMA
    vertexCount = G->n;
    edgesCount = G->m;
    edgesIds = (eid_t*)malloc(sizeof(eid_t) * (vertexCount + 1));
    edges = (Edge*)malloc(sizeof(Edge) * (edgesCount));
#pragma omp parallel
    {
        stickThisThreadToCore(omp_get_thread_num());
#pragma omp for
        for (vid_t i = 0; i <= vertexCount; ++i)
            edgesIds[i] = static_cast<eid_t>(G->rowsIndices[i]);
#pragma omp for
        for (vid_t v = 0; v < vertexCount; ++v)
            for (eid_t e = edgesIds[v]; e < edgesIds[v + 1]; ++e) {
                edges[e].dest = G->endV[e];
                edges[e].weight = G->weights[e];
                edges[e].origOffset = e - edgesIds[v];
            }
    }
    //Eo(allWeight.size());
}

//
// Timer functions
//
int64_t currentNanoTime() {
    timespec ts;
    clock_gettime(CLOCK_MONOTONIC, &ts);
    return int64_t(ts.tv_sec) * int64_t(1e9) + ts.tv_nsec;
}

RDTSC::RDTSC() {
    double t1, t2;
    t1 = get();
    sleep(1);
    t2 = get();
    oneSecond = (t2 - t1);
}

double RDTSC::get() {
    unsigned int time_edx, time_eax;

#ifdef ON_JSCC
    unsigned a, d;
    asm volatile("rdtsc" : "=a" (a), "=d" (d));
    return ((unsigned long long)a) | (((unsigned long long)d) << 32);
#endif

    asm volatile (  "rdtscp\n\t"
            "mov %%edx, %0\n\t"
            "mov %%eax, %1\n\t"
            //                    "cpuid\n\t"
            : "=r"(time_edx), "=r"(time_eax) ::
            "%rax", "%rbx", "%rcx", "%rdx");

    return (double)(((unsigned long long)time_edx) << 32 | (unsigned long long)time_eax);
}

void RDTSC::start(int timerId) {
    timers[timerId][0] = get();
}

double RDTSC::end(int timerId) {
    double res = (get() - timers[timerId][0]) / oneSecond;
    return res;
}

RDTSC rdtsc;

int stickThisThreadToCore(int coreId) {
    const int num_cores = sysconf(_SC_NPROCESSORS_ONLN);
#ifdef ON_HOME
    coreId *= 2;
    coreId += 1;
#endif /* ON_HOME */
#ifdef USE_HYPERTHREADING
    int hardwareCoreId = coreId / 2;
    int htOffset = num_cores / 2;
    coreId = hardwareCoreId + htOffset * (coreId % 2);
#endif /* USE_HYPERTHREADING */
    if (coreId >= num_cores) return 0;

    cpu_set_t cpuset;
    CPU_ZERO(&cpuset);
    CPU_SET(coreId, &cpuset);

    pthread_t current_thread = pthread_self();
    return pthread_setaffinity_np(current_thread, sizeof(cpu_set_t), &cpuset);
}
<commit_msg>Improve reorder.<commit_after>#include "gen.h"
#include <set>
#include <cassert>
#include <cstring>
#include <cstdio>
#include <time.h>
#include <unistd.h>
#include <pthread.h>
#include <algorithm>
#include <vector>
#ifdef __clang__
#include "omp.h"
#else
#include <omp.h>
#endif

const weight_t MAX_WEIGHT = 1.0;

//
// Global data
//
vid_t vertexCount;
eid_t edgesCount;
eid_t *edgesIds;
Edge *edges;
bool *isCoolEdge;
int threadsCount;
int iterationNumber;
vid_t *rev;
vid_t *que;

//
// BFS-reorder specific variable
//
bool *componentEnd;

//
// Edge comparators
//
bool EdgeDestCmp::operator()(const Edge& a, const Edge& b) const {
    if (a.dest != b.dest) return a.dest < b.dest;
    return a.weight < b.weight;
}

bool EdgeWeightCmp::operator()(const Edge& a, const Edge& b) const {
    return a.weight < b.weight;
}

//
// Reorder functions
//
void doReorderBfs() {
    stickThisThreadToCore(0);

    //componentEnd = new bool[vertexCount]();
    bool *visit = new bool[vertexCount]();
    que = static_cast<vid_t*>(malloc(sizeof(vid_t) * vertexCount));
    rev = static_cast<vid_t*>(malloc(sizeof(vid_t) * vertexCount));
    memset(que, 0xc0, sizeof(vid_t) * vertexCount);

    Eo(vertexDegree(0)); // TODO read below
    std::vector<pev> largeVertexes;
#if 1
    for (vid_t v = 0; v < vertexCount; ++v) if (vertexDegree(v) > 99) {
        visit[v] = true;
        //que[v] = v;
        largeVertexes.push_back(pev(vertexDegree(v), v));
    }
    sort(largeVertexes.begin(), largeVertexes.end());
    const vid_t threadOffset = vertexCount / threadsCount;
    for (vid_t i = 0; i < largeVertexes.size(); i += threadsCount) {
        const vid_t from = i;
        const vid_t to = std::min<vid_t>(largeVertexes.size(), i + threadsCount);
        std::random_shuffle(largeVertexes.begin() + from, largeVertexes.begin() + to);
    }
    for (vid_t i = 0; i < largeVertexes.size(); ++i) {
        int toThread = i % threadsCount + 1;
        vid_t toPos = i / threadsCount;
        vid_t pos = toThread * threadOffset - 1 - toPos;
        assert(que[pos] < 0);
        assert(pos < vertexCount);
        que[pos] = largeVertexes[i].second;
    }
#endif

    std::vector<vid_t> vertexByDegree(vertexCount, 0);
    std::iota(vertexByDegree.begin(), vertexByDegree.end(), 0);
    std::sort(vertexByDegree.begin(), vertexByDegree.end(), [&](vid_t a, vid_t b) {
            return vertexDegree(a) < vertexDegree(b);
            });

    vid_t fr = 0, bc = 0;
    for (vid_t ii = 0; ii < vertexCount; ++ii) { // start from vertex with lower degree
        vid_t i = vertexByDegree[ii];
        if (visit[i]) continue;
        while (bc < vertexCount && que[bc] >= 0) ++bc;
        que[bc++] = i;
        visit[i] = true;
        while (fr < bc) {
            const vid_t v = que[fr++];
            for (eid_t e = edgesIds[v]; e < edgesIds[v + 1]; ++e) {
                const vid_t u = edges[e].dest;
                if (visit[u]) continue;
                visit[u] = true;
                while (bc < vertexCount && que[bc] >= 0) ++bc;
                que[bc++] = u;
            }
        }
        //componentEnd[bc - 1] = true;
    }
    while (bc < vertexCount && que[bc] >= 0) ++bc;
    E(largeVertexes.size()); Eo(double(largeVertexes.size()) / vertexCount);
    E(fr); E(bc); Eo(vertexCount);
    assert(bc == vertexCount);
    delete[] visit;

#pragma omp parallel for
    for (vid_t i = 0; i < vertexCount; ++i)
        rev[que[i]] = i;

    eid_t *nextEdgesIds = static_cast<eid_t*>(malloc(sizeof(eid_t) * (vertexCount + 1)));
    Edge *nextEdges = static_cast<Edge*>(malloc(sizeof(Edge) * edgesCount));
    eid_t *sumEdges = new eid_t[threadsCount];
    memset(sumEdges, 0, sizeof(eid_t) * threadsCount);
    nextEdgesIds[0] = 0;
    for (int i = 0; i < threadsCount; ++i) {
        stickThisThreadToCore(i);
        const vid_t vertexBegin = int64_t(vertexCount) * (i + 0) / threadsCount;
        const vid_t vertexEnd   = int64_t(vertexCount) * (i + 1) / threadsCount;
        for (vid_t v = vertexBegin; v < vertexEnd; ++v) {
            const vid_t nextv = que[v];
            nextEdgesIds[v + 1] = nextEdgesIds[v] + edgesIds[nextv + 1] - edgesIds[nextv];
            sumEdges[i] += edgesIds[nextv + 1] - edgesIds[nextv];
        }
    }
    std::sort(sumEdges, sumEdges + threadsCount);
    double disbalanceFactor = double(sumEdges[threadsCount - 1]) / sumEdges[0];
    E(sumEdges[0]); E(sumEdges[threadsCount - 1]);Eo(disbalanceFactor);
    if (disbalanceFactor > 1.5 && false) {
        free(nextEdges);
        free(nextEdgesIds);
        goto clean;
    }
#pragma omp parallel
    {
        const int i = omp_get_thread_num();
        stickThisThreadToCore(i);
        const vid_t vertexBegin = int64_t(vertexCount) * i / threadsCount;
        const vid_t vertexEnd   = int64_t(vertexCount) * (i + 1) / threadsCount;
        for (vid_t v = vertexBegin; v < vertexEnd; ++v) {
            const vid_t nextv = que[v];
            for (eid_t e = edgesIds[nextv]; e < edgesIds[nextv + 1]; ++e) {
                nextEdges[nextEdgesIds[v] + e - edgesIds[nextv]] = edges[e];
                nextEdges[nextEdgesIds[v] + e - edgesIds[nextv]].dest = rev[edges[e].dest];
            }
        }
    }

    free(edges);
    free(edgesIds);
    edges = nextEdges;
    edgesIds = nextEdgesIds;
clean:
    //free(que);
    //free(rev);
    delete[] sumEdges;
}

void doReorderSimple() {
    stickThisThreadToCore(0);

    bool *visit = new bool[vertexCount]();
    que = static_cast<vid_t*>(malloc(sizeof(vid_t) * vertexCount));
    rev = static_cast<vid_t*>(malloc(sizeof(vid_t) * vertexCount));
    vid_t pos = 0;
    for (vid_t v = 0; v < vertexCount; ++v) if (!visit[v]) {
        visit[v] = true;
        que[pos++] = v;
        for (eid_t e = edgesIds[v]; e < edgesIds[v + 1]; ++e) {
            const vid_t u = edges[e].dest;
            if (visit[u]) continue;
            visit[u] = true;
            que[pos++] = u;
        }
    }
    assert(pos == vertexCount);
    delete[] visit;

#pragma omp parallel for
    for (vid_t i = 0; i < vertexCount; ++i)
        rev[que[i]] = i;

    eid_t *nextEdgesIds = static_cast<eid_t*>(malloc(sizeof(eid_t) * (vertexCount + 1)));
    Edge *nextEdges = static_cast<Edge*>(malloc(sizeof(Edge) * edgesCount));
    nextEdgesIds[0] = 0;
    for (int i = 0; i < threadsCount; ++i) {
        stickThisThreadToCore(i);
        const vid_t vertexBegin = int64_t(vertexCount) * (i + 0) / threadsCount;
        const vid_t vertexEnd   = int64_t(vertexCount) * (i + 1) / threadsCount;
        for (vid_t v = vertexBegin; v < vertexEnd; ++v) {
            const vid_t nextv = que[v];
            nextEdgesIds[v + 1] = nextEdgesIds[v] + edgesIds[nextv + 1] - edgesIds[nextv];
        }
    }
#pragma omp parallel
    {
        const int i = omp_get_thread_num();
        stickThisThreadToCore(i);
        const vid_t vertexBegin = int64_t(vertexCount) * i / threadsCount;
        const vid_t vertexEnd   = int64_t(vertexCount) * (i + 1) / threadsCount;
        for (vid_t v = vertexBegin; v < vertexEnd; ++v) {
            const vid_t nextv = que[v];
            for (eid_t e = edgesIds[nextv]; e < edgesIds[nextv + 1]; ++e) {
                nextEdges[nextEdgesIds[v] + e - edgesIds[nextv]] = edges[e];
                nextEdges[nextEdgesIds[v] + e - edgesIds[nextv]].dest = rev[edges[e].dest];
            }
        }
    }
    free(que);
    //free(rev);
    free(edges);
    free(edgesIds);
    edges = nextEdges;
    edgesIds = nextEdgesIds;
}

//
// Read input data
//
void readAll(char *filename) {
    iterationNumber = 0;
#pragma omp parallel
    {
#pragma omp master
        {
            threadsCount = omp_get_num_threads();
        }
    }
    Eo(threadsCount);

    FILE *f = fopen(filename, "rb");
    assert(f);

    fread(&vertexCount, sizeof(vid_t), 1, f);
    fread(&edgesCount, sizeof(eid_t), 1, f);

    // NUMA-specific part
    // Each core allocate memory and read data, which will processed on this core
    edgesIds = (eid_t*)malloc(sizeof(eid_t) * (vertexCount + 1));
    edges = (Edge*)malloc(sizeof(Edge) * (edgesCount));

    for (int i = 0; i < threadsCount; ++i) {
        stickThisThreadToCore(i);
        const int vertexBegin = int64_t(vertexCount + 1) * i / threadsCount;
        const int vertexEnd   = int64_t(vertexCount + 1) * (i + 1) / threadsCount;
        fread(edgesIds + vertexBegin, sizeof(eid_t), vertexEnd - vertexBegin, f);
    }

    for (int i = 0; i < threadsCount; ++i) {
        stickThisThreadToCore(i);
        const int vertexBegin = int64_t(vertexCount) * i / threadsCount;
        const int vertexEnd   = int64_t(vertexCount) * (i + 1) / threadsCount;
        const int edgeBegin   = edgesIds[vertexBegin];
        const int edgeEnd     = edgesIds[vertexEnd];
        fread(edges + edgeBegin, sizeof(Edge), edgeEnd - edgeBegin, f);
    }
    fclose(f);
}

void convertAll(graph_t *G) {
    iterationNumber = 0;
#pragma omp parallel
    {
#pragma omp master
        {
            threadsCount = omp_get_num_threads();
        }
    }

    //std::set<weight_t> allWeight;

    // TODO NUMA
    vertexCount = G->n;
    edgesCount = G->m;
    edgesIds = (eid_t*)malloc(sizeof(eid_t) * (vertexCount + 1));
    edges = (Edge*)malloc(sizeof(Edge) * (edgesCount));
#pragma omp parallel
    {
        stickThisThreadToCore(omp_get_thread_num());
#pragma omp for
        for (vid_t i = 0; i <= vertexCount; ++i)
            edgesIds[i] = static_cast<eid_t>(G->rowsIndices[i]);
#pragma omp for
        for (vid_t v = 0; v < vertexCount; ++v)
            for (eid_t e = edgesIds[v]; e < edgesIds[v + 1]; ++e) {
                edges[e].dest = G->endV[e];
                edges[e].weight = G->weights[e];
                edges[e].origOffset = e - edgesIds[v];
            }
    }
    //Eo(allWeight.size());
}

//
// Timer functions
//
int64_t currentNanoTime() {
    timespec ts;
    clock_gettime(CLOCK_MONOTONIC, &ts);
    return int64_t(ts.tv_sec) * int64_t(1e9) + ts.tv_nsec;
}

RDTSC::RDTSC() {
    double t1, t2;
    t1 = get();
    sleep(1);
    t2 = get();
    oneSecond = (t2 - t1);
}

double RDTSC::get() {
    unsigned int time_edx, time_eax;

#ifdef ON_JSCC
    unsigned a, d;
    asm volatile("rdtsc" : "=a" (a), "=d" (d));
    return ((unsigned long long)a) | (((unsigned long long)d) << 32);
#endif

    asm volatile (  "rdtscp\n\t"
            "mov %%edx, %0\n\t"
            "mov %%eax, %1\n\t"
            //                    "cpuid\n\t"
            : "=r"(time_edx), "=r"(time_eax) ::
            "%rax", "%rbx", "%rcx", "%rdx");

    return (double)(((unsigned long long)time_edx) << 32 | (unsigned long long)time_eax);
}

void RDTSC::start(int timerId) {
    timers[timerId][0] = get();
}

double RDTSC::end(int timerId) {
    double res = (get() - timers[timerId][0]) / oneSecond;
    return res;
}

RDTSC rdtsc;

int stickThisThreadToCore(int coreId) {
    const int num_cores = sysconf(_SC_NPROCESSORS_ONLN);
#ifdef ON_HOME
    coreId *= 2;
    coreId += 1;
#endif /* ON_HOME */
#ifdef USE_HYPERTHREADING
    int hardwareCoreId = coreId / 2;
    int htOffset = num_cores / 2;
    coreId = hardwareCoreId + htOffset * (coreId % 2);
#endif /* USE_HYPERTHREADING */
    if (coreId >= num_cores) return 0;

    cpu_set_t cpuset;
    CPU_ZERO(&cpuset);
    CPU_SET(coreId, &cpuset);

    pthread_t current_thread = pthread_self();
    return pthread_setaffinity_np(current_thread, sizeof(cpu_set_t), &cpuset);
}
<|endoftext|>


<commit_before>/*
 *  Copyright (c) 2013 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 "rtc_base/flags.h"
#include "rtc_base/logging.h"
#include "rtc_base/thread.h"
#include "system_wrappers/include/field_trial_default.h"
#include "system_wrappers/include/metrics_default.h"
#include "test/field_trial.h"
#include "test/gmock.h"
#include "test/gtest.h"
#include "test/testsupport/fileutils.h"
#include "test/testsupport/perf_test.h"

#if defined(WEBRTC_IOS)
#include "test/ios/test_support.h"

DEFINE_string(NSTreatUnknownArgumentsAsOpen,
              "",
              "Intentionally ignored flag intended for iOS simulator.");
DEFINE_string(ApplePersistenceIgnoreState,
              "",
              "Intentionally ignored flag intended for iOS simulator.");
DEFINE_bool(
    save_chartjson_result,
    false,
    "Store the perf results in Documents/perf_result.json in the format "
    "described by "
    "https://github.com/catapult-project/catapult/blob/master/dashboard/docs/"
    "data-format.md.");

#else

DEFINE_string(isolated_script_test_output,
              "",
              "Intentionally ignored flag intended for Chromium.");

DEFINE_string(
    isolated_script_test_perf_output,
    "",
    "Path where the perf results should be stored in the JSON format described "
    "by "
    "https://github.com/catapult-project/catapult/blob/master/dashboard/docs/"
    "data-format.md.");

#endif

DEFINE_bool(logs, false, "print logs to stderr");

DEFINE_string(
    force_fieldtrials,
    "",
    "Field trials control experimental feature code which can be forced. "
    "E.g. running with --force_fieldtrials=WebRTC-FooFeature/Enable/"
    " will assign the group Enable to field trial WebRTC-FooFeature.");

DEFINE_bool(help, false, "Print this message.");

int main(int argc, char* argv[]) {
  ::testing::InitGoogleMock(&argc, argv);

  // Default to LS_INFO, even for release builds to provide better test logging.
  // TODO(pbos): Consider adding a command-line override.
  if (rtc::LogMessage::GetLogToDebug() > rtc::LS_INFO)
    rtc::LogMessage::LogToDebug(rtc::LS_INFO);

  if (rtc::FlagList::SetFlagsFromCommandLine(&argc, argv, false)) {
    return 1;
  }
  if (FLAG_help) {
    rtc::FlagList::Print(nullptr, false);
    return 0;
  }

  webrtc::test::SetExecutablePath(argv[0]);
  webrtc::test::ValidateFieldTrialsStringOrDie(FLAG_force_fieldtrials);
  // InitFieldTrialsFromString stores the char*, so the char array must outlive
  // the application.
  webrtc::field_trial::InitFieldTrialsFromString(FLAG_force_fieldtrials);
  webrtc::metrics::Enable();

  rtc::LogMessage::SetLogToStderr(FLAG_logs);

  // Ensure that main thread gets wrapped as an rtc::Thread.
  // TODO(bugs.webrt.org/9714): It might be better to avoid wrapping the main
  // thread, or leave it to individual tests that need it. But as long as we
  // have automatic thread wrapping, we need this to avoid that some other
  // random thread (which one depending on which tests are run) gets
  // automatically wrapped.
  rtc::ThreadManager::Instance()->WrapCurrentThread();
  RTC_CHECK(rtc::Thread::Current());

#if defined(WEBRTC_IOS)

  rtc::test::InitTestSuite(RUN_ALL_TESTS, argc, argv,
                           FLAG_save_chartjson_result);
  rtc::test::RunTestsFromIOSApp();

#else

  int exit_code = RUN_ALL_TESTS();

  std::string chartjson_result_file = FLAG_isolated_script_test_perf_output;
  if (!chartjson_result_file.empty()) {
    webrtc::test::WritePerfResults(chartjson_result_file);
  }

  return exit_code;

#endif
}
<commit_msg>Make webrtc_perf_tests output an empty result output.json<commit_after>/*
 *  Copyright (c) 2013 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 <fstream>

#include "rtc_base/flags.h"
#include "rtc_base/logging.h"
#include "rtc_base/thread.h"
#include "system_wrappers/include/field_trial_default.h"
#include "system_wrappers/include/metrics_default.h"
#include "test/field_trial.h"
#include "test/gmock.h"
#include "test/gtest.h"
#include "test/testsupport/fileutils.h"
#include "test/testsupport/perf_test.h"

#if defined(WEBRTC_IOS)
#include "test/ios/test_support.h"

DEFINE_string(NSTreatUnknownArgumentsAsOpen,
              "",
              "Intentionally ignored flag intended for iOS simulator.");
DEFINE_string(ApplePersistenceIgnoreState,
              "",
              "Intentionally ignored flag intended for iOS simulator.");
DEFINE_bool(
    save_chartjson_result,
    false,
    "Store the perf results in Documents/perf_result.json in the format "
    "described by "
    "https://github.com/catapult-project/catapult/blob/master/dashboard/docs/"
    "data-format.md.");

#else

DEFINE_string(
    isolated_script_test_output,
    "",
    "Path to output an empty JSON file which Chromium infra requires.");

DEFINE_string(
    isolated_script_test_perf_output,
    "",
    "Path where the perf results should be stored in the JSON format described "
    "by "
    "https://github.com/catapult-project/catapult/blob/master/dashboard/docs/"
    "data-format.md.");

#endif

DEFINE_bool(logs, false, "print logs to stderr");

DEFINE_string(
    force_fieldtrials,
    "",
    "Field trials control experimental feature code which can be forced. "
    "E.g. running with --force_fieldtrials=WebRTC-FooFeature/Enable/"
    " will assign the group Enable to field trial WebRTC-FooFeature.");

DEFINE_bool(help, false, "Print this message.");

int main(int argc, char* argv[]) {
  ::testing::InitGoogleMock(&argc, argv);

  // Default to LS_INFO, even for release builds to provide better test logging.
  // TODO(pbos): Consider adding a command-line override.
  if (rtc::LogMessage::GetLogToDebug() > rtc::LS_INFO)
    rtc::LogMessage::LogToDebug(rtc::LS_INFO);

  if (rtc::FlagList::SetFlagsFromCommandLine(&argc, argv, false)) {
    return 1;
  }
  if (FLAG_help) {
    rtc::FlagList::Print(nullptr, false);
    return 0;
  }

  webrtc::test::SetExecutablePath(argv[0]);
  webrtc::test::ValidateFieldTrialsStringOrDie(FLAG_force_fieldtrials);
  // InitFieldTrialsFromString stores the char*, so the char array must outlive
  // the application.
  webrtc::field_trial::InitFieldTrialsFromString(FLAG_force_fieldtrials);
  webrtc::metrics::Enable();

  rtc::LogMessage::SetLogToStderr(FLAG_logs);

  // Ensure that main thread gets wrapped as an rtc::Thread.
  // TODO(bugs.webrt.org/9714): It might be better to avoid wrapping the main
  // thread, or leave it to individual tests that need it. But as long as we
  // have automatic thread wrapping, we need this to avoid that some other
  // random thread (which one depending on which tests are run) gets
  // automatically wrapped.
  rtc::ThreadManager::Instance()->WrapCurrentThread();
  RTC_CHECK(rtc::Thread::Current());

#if defined(WEBRTC_IOS)

  rtc::test::InitTestSuite(RUN_ALL_TESTS, argc, argv,
                           FLAG_save_chartjson_result);
  rtc::test::RunTestsFromIOSApp();

#else

  int exit_code = RUN_ALL_TESTS();

  std::string chartjson_result_file = FLAG_isolated_script_test_perf_output;
  if (!chartjson_result_file.empty()) {
    webrtc::test::WritePerfResults(chartjson_result_file);
  }

  std::string result_filename = FLAG_isolated_script_test_output;
  if (!result_filename.empty()) {
    std::ofstream result_file(result_filename);
    result_file << "{\"version\": 3}";
    result_file.close();
  }

  return exit_code;

#endif
}
<|endoftext|>


<commit_before>#ifdef __cplusplus
extern "C" {
#endif

#include <stdio.h>
#include "QuickSort.h"
#include "MergeSort.h"
#include "HeapSort.h"
#include "SelectionSort.h"
#include "InsertionSort.h"
#include "Utils.h"

#ifdef __cplusplus
}
#endif

#include "gtest/gtest.h"

int list1[] = {1};
int list2[] = {1,2};
int ulist2[] = {2,1};
int list3[] = {1,2,3};
int ulist3[] = {3,1,2};

int isSorted(int *A, int size) {
  int i;
  for (i = 0; i < size - 1; i++)
    if (A[i] > A[i + 1])
      return 0;

  return 1;
}

int *copyList(int *A, int size) {
  int *list = (int *)malloc(size * sizeof(int));
  for (int i = 0; i < size; i++)
    list[i] = A[i];

  return list;
}

void printList(int *A, int size) {
  for (int i = 0; i < size; i++)
    printf("%d ", A[i]);

  printf("\n");
}

TEST(QUICKSORT, SORT1) {
  int *list = copyList(list1, 1);
  quickSort(list, 0, 0);
  ASSERT_EQ(1, isSorted(list, 1));
  free(list);
}

TEST(QUICKSORT, SORT2) {
  int *list = copyList(list2, 2);
  quickSort(list, 0, 1);
  ASSERT_EQ(1, isSorted(list, 2));
  free(list);
}

TEST(QUICKSORT, SORT3) {
  int *list = copyList(list3, 3);
  quickSort(list, 0, 2);
  ASSERT_EQ(1, isSorted(list, 3));
  free(list);
}

TEST(QUICKSORT, SORT10K) {
  int size = 10000;
  int *list = createIntArray(size);
  quickSort(list, 0, size - 1);
  ASSERT_EQ(1, isSorted(list, size));
  free(list);
}

TEST(QUICKSORT, SORT1M) {
  int size = 1000000;
  int *list = createIntArray(size);
  quickSort(list, 0, size - 1);
  ASSERT_EQ(1, isSorted(list, size));
  free(list);
}

// - other sorting algos
// - sorted array tsting
<commit_msg>Add tests for sorting algos<commit_after>#ifdef __cplusplus
extern "C" {
#endif

#include <stdio.h>
#include "QuickSort.h"
#include "MergeSort.h"
#include "HeapSort.h"
#include "SelectionSort.h"
#include "InsertionSort.h"
#include "Utils.h"

#ifdef __cplusplus
}
#endif

#include "gtest/gtest.h"

int list1[] = {1};
int list2[] = {1,2};
int ulist2[] = {2,1};
int list3[] = {1,2,3};
int ulist3[] = {3,1,2};

int isSorted(int *A, int size) {
  int i;
  for (i = 0; i < size - 1; i++)
    if (A[i] > A[i + 1])
      return 0;

  return 1;
}

int *copyList(int *A, int size) {
  int *list = (int *)malloc(size * sizeof(int));
  for (int i = 0; i < size; i++)
    list[i] = A[i];

  return list;
}

void printList(int *A, int size) {
  for (int i = 0; i < size; i++)
    printf("%d ", A[i]);

  printf("\n");
}

// QuickSort

TEST(QUICKSORT, SORT1) {
  int *list = copyList(list1, 1);
  quickSort(list, 0, 0);
  ASSERT_EQ(1, isSorted(list, 1));
  free(list);
}

TEST(QUICKSORT, SORT2) {
  int *list = copyList(list2, 2);
  quickSort(list, 0, 1);
  ASSERT_EQ(1, isSorted(list, 2));
  free(list);
}

TEST(QUICKSORT, SORT3) {
  int *list = copyList(list3, 3);
  quickSort(list, 0, 2);
  ASSERT_EQ(1, isSorted(list, 3));
  free(list);
}

TEST(QUICKSORT, SORT10K) {
  int size = 10000;
  int *list = createIntArray(size);
  quickSort(list, 0, size - 1);
  ASSERT_EQ(1, isSorted(list, size));
  free(list);
}

TEST(QUICKSORT, SORT50K) {
  int size = 50000;
  int *list = createIntArray(size);
  quickSort(list, 0, size - 1);
  ASSERT_EQ(1, isSorted(list, size));
  free(list);
}

// MergeSort

TEST(MERGESORT, SORT1) {
  int *list = copyList(list1, 1);
  mergeSortA(list, 0, 0);
  ASSERT_EQ(1, isSorted(list, 1));
  free(list);
}

TEST(MERGESORT, SORT2) {
  int *list = copyList(list2, 2);
  mergeSortA(list, 0, 1);
  ASSERT_EQ(1, isSorted(list, 2));
  free(list);
}

TEST(MERGESORT, SORT3) {
  int *list = copyList(list3, 3);
  mergeSortA(list, 0, 2);
  ASSERT_EQ(1, isSorted(list, 3));
  free(list);
}

TEST(MERGESORT, SORT10K) {
  int size = 10000;
  int *list = createIntArray(size);
  mergeSortA(list, 0, size - 1);
  ASSERT_EQ(1, isSorted(list, size));
  free(list);
}

TEST(MERGESORT, SORT50K) {
  int size = 50000;
  int *list = createIntArray(size);
  mergeSortA(list, 0, size - 1);
  ASSERT_EQ(1, isSorted(list, size));
  free(list);
}

// HeapSort

TEST(HEAPSORT, SORT1) {
  int *list = copyList(list1, 1);
  heapSort(list, 0);
  ASSERT_EQ(1, isSorted(list, 1));
  free(list);
}

TEST(HEAPSORT, SORT2) {
  int *list = copyList(list2, 2);
  heapSort(list, 1);
  ASSERT_EQ(1, isSorted(list, 2));
  free(list);
}

TEST(HEAPSORT, SORT3) {
  int *list = copyList(list3, 3);
  heapSort(list, 2);
  ASSERT_EQ(1, isSorted(list, 3));
  free(list);
}

TEST(HEAPSORT, SORT10K) {
  int size = 10000;
  int *list = createIntArray(size);
  heapSort(list, size);
  ASSERT_EQ(1, isSorted(list, size));
  free(list);
}

TEST(HEAPSORT, SORT50K) {
  int size = 50000;
  int *list = createIntArray(size);
  heapSort(list, size);
  ASSERT_EQ(1, isSorted(list, size));
  free(list);
}

// InsertionSort

TEST(INSERTIONSORT, SORT1) {
  int *list = copyList(list1, 1);
  insertionSort(list, 0);
  ASSERT_EQ(1, isSorted(list, 1));
  free(list);
}

TEST(INSERTIONSORT, SORT2) {
  int *list = copyList(list2, 2);
  insertionSort(list, 1);
  ASSERT_EQ(1, isSorted(list, 2));
  free(list);
}

TEST(INSERTIONSORT, SORT3) {
  int *list = copyList(list3, 3);
  insertionSort(list, 2);
  ASSERT_EQ(1, isSorted(list, 3));
  free(list);
}

TEST(INSERTIONSORT, SORT10K) {
  int size = 10000;
  int *list = createIntArray(size);
  insertionSort(list, size);
  ASSERT_EQ(1, isSorted(list, size));
  free(list);
}

TEST(INSERTIONSORT, SORT50K) {
  int size = 50000;
  int *list = createIntArray(size);
  insertionSort(list, size);
  ASSERT_EQ(1, isSorted(list, size));
  free(list);
}

// SelectionSort

TEST(SELECTIONSORT, SORT1) {
  int *list = copyList(list1, 1);
  selectionSort(list, 0);
  ASSERT_EQ(1, isSorted(list, 1));
  free(list);
}

TEST(SELECTIONSORT, SORT2) {
  int *list = copyList(list2, 2);
  selectionSort(list, 1);
  ASSERT_EQ(1, isSorted(list, 2));
  free(list);
}

TEST(SELECTIONSORT, SORT3) {
  int *list = copyList(list3, 3);
  selectionSort(list, 2);
  ASSERT_EQ(1, isSorted(list, 3));
  free(list);
}

TEST(SELECTIONSORT, SORT10K) {
  int size = 10000;
  int *list = createIntArray(size);
  selectionSort(list, size);
  ASSERT_EQ(1, isSorted(list, size));
  free(list);
}

TEST(SELECTIONSORT, SORT50K) {
  int size = 50000;
  int *list = createIntArray(size);
  selectionSort(list, size);
  ASSERT_EQ(1, isSorted(list, size));
  free(list);
}

// - other sorting algos
// - sorted array tsting
<|endoftext|>


<commit_before>#ifndef DUNE_STUFF_LA_ALGORITHM_GRAMSCHMIDT_HH
#define DUNE_STUFF_LA_ALGORITHM_GRAMSCHMIDT_HH

#include <dune/common/exceptions.hh>
#include <dune/common/static_assert.hh>
#include <dune/common/typetraits.hh>

#include <dune/stuff/common/logging.hh>
#include <dune/stuff/common/color.hh>
#include <dune/stuff/la/container/interface.hh>
#include <dune/stuff/la/container/eigen.hh>
#include <dune/stuff/la/algorithm/normalize.hh>

namespace Dune {
namespace Stuff {
namespace LA {
namespace Algorithm {

template< class ContainerType >
void gramSchmidt(ContainerType& /*_columnVectors*/)
{
  dune_static_assert((Dune::AlwaysFalse< ContainerType >::value), "ERROR: not implemeneted for this ContainerType!");
}

//#if HAVE_EIGEN
template< class ElementType >
void gramSchmidt(Dune::Stuff::LA::Container::EigenDenseVector< ElementType >& /*_columnVectors*/)
{
  dune_static_assert((Dune::AlwaysFalse< ElementType >::value),
                     "ERROR: not implemeneted for EigenDenseVector, use normalize()!");
} // void normalize(Dune::Stuff::LA::Container::EigenDenseVector< ElementType >& _vector)

// from Eigen: src/eigen/test/umeyama.cpp
// they say one could use another orthogonalization of the rows, but I'm not sure about this
/*
      // this additional orthogonalization is not necessary in theory but should enhance
      // the numerical orthogonality of the matrix
      for (int row = 0; row < size; ++row)
      {
        typename MatrixType::RowXpr rowVec = Q.row(row);
        for (int prevRow = 0; prevRow < row; ++prevRow)
        {
          typename MatrixType::RowXpr prevRowVec = Q.row(prevRow);
          rowVec -= rowVec.dot(prevRowVec)*prevRowVec;
        }
        Q.row(row) = rowVec.normalized();
      }
*/

template< class ElementType >
void gramSchmidt(Dune::Stuff::LA::Container::EigenDenseMatrix< ElementType >& _columnVectors)
{
  // if this is an empty matrix, throw up
  if (_columnVectors.cols() == 0 || _columnVectors.rows() == 0)
    DUNE_THROW(Dune::MathError,
               "\nERROR: '_columnVectors' is empty!");
  else {
    // this is a matrix, check how to interpret it
    if (_columnVectors.rows() == 1) {
      // this is a row-vector, throw up
      DUNE_THROW(Dune::MathError,
                 "\nERROR: '_columnVectors' is a row-vector!");
    } else if (_columnVectors.cols() == 1) {
      // this is just one column-vector, normalize it
      Dune::Stuff::LA::Algorithm::normalize(_columnVectors);
    } else {
      // this is a set of column-vectors
      typedef typename Dune::Stuff::LA::Container::EigenDenseMatrix< ElementType >::size_type size_type;
      for (size_type ii = 0; ii < _columnVectors.cols(); ++ii) {
        // get the iith column
        typedef typename Dune::Stuff::LA::Container::EigenDenseMatrix< ElementType >::BackendType::ColXpr ColumnType;
        ColumnType iith_column = _columnVectors.backend().col(ii);
        // and orthonormalize it wrt all previous columns
        for (size_type jj = 0; jj < ii; ++ jj) {
          // therefore, get the jjth column,
          ColumnType jjth_column = _columnVectors.backend().col(jj);
          // project the iith column wrt to the jjth column
          iith_column -= iith_column.dot(jjth_column) * jjth_column;
        }
        // and finally normalize the iith column
        const ElementType norm = std::sqrt(iith_column.transpose() * iith_column);
        _columnVectors.backend().col(ii) = iith_column / norm;
      }
    } // this is a matrix, check how to interpret it
  } // if this is an empty matrix, throw up
} // void normalize(Dune::Stuff::LA::Container::EigenDenseMatrix< ElementType >& _matrix)

template< class ElementType >
void gramSchmidt(Dune::Stuff::LA::Container::EigenRowMajorSparseMatrix< ElementType >& /*_columnVectors*/)
{
  dune_static_assert((Dune::AlwaysFalse< ElementType >::value),
                     "ERROR: not implemeneted for EigenRowMajorSparseMatrix!");
}
//#endif // HAVE_EIGEN

template< class ScalarProductType, class ContainerType >
void gramSchmidt(const ScalarProductType& /*scalarProduct*/, ContainerType& /*_columnVectors*/)
{
  dune_static_assert((Dune::AlwaysFalse< ScalarProductType >::value || Dune::AlwaysFalse< ContainerType >::value),
                     "ERROR: not implemeneted for this ContainerType!");
}

template< class ElementType >
void gramSchmidt(const Dune::Stuff::LA::Container::EigenDenseMatrix< ElementType >& /*_scalarProduct*/,
                 Dune::Stuff::LA::Container::EigenDenseVector< ElementType >& /*_columnVectors*/)
{
  dune_static_assert((Dune::AlwaysFalse< ElementType >::value),
                     "ERROR: not implemeneted for EigenDenseVector, use normalize()!");
} // void normalize(Dune::Stuff::LA::Container::EigenDenseVector< ElementType >& _vector)

template< class ElementType >
void gramSchmidt(const Dune::Stuff::LA::Container::EigenRowMajorSparseMatrix< ElementType >& /*_scalarProduct*/,
                 Dune::Stuff::LA::Container::EigenDenseVector< ElementType >& /*_columnVectors*/)
{
  dune_static_assert((Dune::AlwaysFalse< ElementType >::value),
                     "ERROR: not implemeneted for EigenDenseVector, use normalize()!");
} // void normalize(Dune::Stuff::LA::Container::EigenDenseVector< ElementType >& _vector)

template< class ElementType >
void gramSchmidt(const Dune::Stuff::LA::Container::EigenDenseMatrix< ElementType >& _scalarProduct,
                 Dune::Stuff::LA::Container::EigenDenseMatrix< ElementType >& _columnVectors)
{
  // if this is an empty matrix, throw up
  if (_columnVectors.cols() == 0 || _columnVectors.rows() == 0)
    DUNE_THROW(Dune::MathError,
               "\nERROR: '_columnVectors' is empty!");
  else {
    // this is a matrix, check how to interpret it
    if (_columnVectors.rows() == 1) {
      // this is a row-vector, throw up
      DUNE_THROW(Dune::MathError,
                 "\nERROR: '_columnVectors' is a row-vector!");
    } else if (_columnVectors.cols() == 1) {
      // this is just one column-vector, normalize it
      Dune::Stuff::LA::Algorithm::normalize(_scalarProduct, _columnVectors);
    } else {
      // this is a set of column-vectors, check sizes
      assert(_columnVectors.rows() == _scalarProduct.rows());
      assert(_columnVectors.rows() == _scalarProduct.cols());
      typedef typename Dune::Stuff::LA::Container::EigenDenseMatrix< ElementType >::size_type size_type;
      for (size_type ii = 0; ii < _columnVectors.cols(); ++ii) {
        // get the iith column
        typedef typename Dune::Stuff::LA::Container::EigenDenseMatrix< ElementType >::BackendType::ColXpr ColumnType;
        ColumnType iith_column = _columnVectors.backend().col(ii);
        // and orthonormalize it wrt all previous columns
        for (size_type jj = 0; jj < ii; ++ jj) {
          // therefore, get the jjth column,
          ColumnType jjth_column = _columnVectors.backend().col(jj);
          // project the iith column wrt to the jjth column
          const ElementType factor = iith_column.transpose() * _scalarProduct.backend() * jjth_column;
          iith_column -= factor * jjth_column;
        }
        // and finally normalize the iith column
        const ElementType norm = std::sqrt(iith_column.transpose() * _scalarProduct.backend() * iith_column);
        _columnVectors.backend().col(ii) = iith_column / norm;
      }
    } // this is a matrix, check how to interpret it
  } // if this is an empty matrix, throw up
} // void normalize(Dune::Stuff::LA::Container::EigenDenseMatrix< ElementType >& _matrix)

} // namespace Algorithm
} // namespace LA
} // namespace Stuff
} // namespace Dune

#endif // DUNE_STUFF_LA_ALGORITHM_GRAMSCHMIDT_HH
<commit_msg>[la.algorithm.gramschmidt]<commit_after>#ifndef DUNE_STUFF_LA_ALGORITHM_GRAMSCHMIDT_HH
#define DUNE_STUFF_LA_ALGORITHM_GRAMSCHMIDT_HH

#include <dune/common/exceptions.hh>
#include <dune/common/static_assert.hh>
#include <dune/common/typetraits.hh>

#include <dune/stuff/common/logging.hh>
#include <dune/stuff/common/color.hh>
#include <dune/stuff/la/container/interface.hh>
#include <dune/stuff/la/container/eigen.hh>
#include <dune/stuff/la/algorithm/normalize.hh>

namespace Dune {
namespace Stuff {
namespace LA {
namespace Algorithm {

template< class ContainerType >
void gramSchmidt(ContainerType& /*_columnVectors*/)
{
  dune_static_assert((Dune::AlwaysFalse< ContainerType >::value), "ERROR: not implemeneted for this ContainerType!");
}

#if HAVE_EIGEN
template< class ElementType >
void gramSchmidt(Dune::Stuff::LA::Container::EigenDenseVector< ElementType >& /*_columnVectors*/)
{
  dune_static_assert((Dune::AlwaysFalse< ElementType >::value),
                     "ERROR: not implemeneted for EigenDenseVector, use normalize()!");
} // void normalize(Dune::Stuff::LA::Container::EigenDenseVector< ElementType >& _vector)

// from Eigen: src/eigen/test/umeyama.cpp
// they say one could use another orthogonalization of the rows, but I'm not sure about this
/*
      // this additional orthogonalization is not necessary in theory but should enhance
      // the numerical orthogonality of the matrix
      for (int row = 0; row < size; ++row)
      {
        typename MatrixType::RowXpr rowVec = Q.row(row);
        for (int prevRow = 0; prevRow < row; ++prevRow)
        {
          typename MatrixType::RowXpr prevRowVec = Q.row(prevRow);
          rowVec -= rowVec.dot(prevRowVec)*prevRowVec;
        }
        Q.row(row) = rowVec.normalized();
      }
*/

template< class ElementType >
void gramSchmidt(Dune::Stuff::LA::Container::EigenDenseMatrix< ElementType >& _columnVectors)
{
  // if this is an empty matrix, throw up
  if (_columnVectors.cols() == 0 || _columnVectors.rows() == 0)
    DUNE_THROW(Dune::MathError,
               "\nERROR: '_columnVectors' is empty!");
  else {
    // this is a matrix, check how to interpret it
    if (_columnVectors.rows() == 1) {
      // this is a row-vector, throw up
      DUNE_THROW(Dune::MathError,
                 "\nERROR: '_columnVectors' is a row-vector!");
    } else if (_columnVectors.cols() == 1) {
      // this is just one column-vector, normalize it
      Dune::Stuff::LA::Algorithm::normalize(_columnVectors);
    } else {
      // this is a set of column-vectors
      typedef typename Dune::Stuff::LA::Container::EigenDenseMatrix< ElementType >::size_type size_type;
      for (size_type ii = 0; ii < _columnVectors.cols(); ++ii) {
        // get the iith column
        typedef typename Dune::Stuff::LA::Container::EigenDenseMatrix< ElementType >::BackendType::ColXpr ColumnType;
        ColumnType iith_column = _columnVectors.backend().col(ii);
        // and orthonormalize it wrt all previous columns
        for (size_type jj = 0; jj < ii; ++ jj) {
          // therefore, get the jjth column,
          ColumnType jjth_column = _columnVectors.backend().col(jj);
          // project the iith column wrt to the jjth column
          iith_column -= iith_column.dot(jjth_column) * jjth_column;
        }
        // and finally normalize the iith column
        const ElementType norm = std::sqrt(iith_column.transpose() * iith_column);
        _columnVectors.backend().col(ii) = iith_column / norm;
      }
    } // this is a matrix, check how to interpret it
  } // if this is an empty matrix, throw up
} // void normalize(Dune::Stuff::LA::Container::EigenDenseMatrix< ElementType >& _matrix)

template< class ElementType >
void gramSchmidt(Dune::Stuff::LA::Container::EigenRowMajorSparseMatrix< ElementType >& /*_columnVectors*/)
{
  dune_static_assert((Dune::AlwaysFalse< ElementType >::value),
                     "ERROR: not implemeneted for EigenRowMajorSparseMatrix!");
}
#endif // HAVE_EIGEN

template< class ScalarProductType, class ContainerType >
void gramSchmidt(const ScalarProductType& /*scalarProduct*/, ContainerType& /*_columnVectors*/)
{
  dune_static_assert((Dune::AlwaysFalse< ScalarProductType >::value || Dune::AlwaysFalse< ContainerType >::value),
                     "ERROR: not implemeneted for this combination of ScalarProductType/ContainerType!");
}

#if HAVE_EIGEN
template< class ElementType >
void gramSchmidt(const Dune::Stuff::LA::Container::EigenDenseMatrix< ElementType >& /*_scalarProduct*/,
                 Dune::Stuff::LA::Container::EigenDenseVector< ElementType >& /*_columnVectors*/)
{
  dune_static_assert((Dune::AlwaysFalse< ElementType >::value),
                     "ERROR: not implemeneted for EigenDenseVector, use normalize()!");
} // void normalize(Dune::Stuff::LA::Container::EigenDenseVector< ElementType >& _vector)

template< class ElementType >
void gramSchmidt(const Dune::Stuff::LA::Container::EigenRowMajorSparseMatrix< ElementType >& /*_scalarProduct*/,
                 Dune::Stuff::LA::Container::EigenDenseVector< ElementType >& /*_columnVectors*/)
{
  dune_static_assert((Dune::AlwaysFalse< ElementType >::value),
                     "ERROR: not implemeneted for EigenDenseVector, use normalize()!");
} // void normalize(Dune::Stuff::LA::Container::EigenDenseVector< ElementType >& _vector)

template< class ElementType >
void gramSchmidt(const Dune::Stuff::LA::Container::EigenDenseMatrix< ElementType >& _scalarProduct,
                 Dune::Stuff::LA::Container::EigenDenseMatrix< ElementType >& _columnVectors)
{
  // if this is an empty matrix, throw up
  if (_columnVectors.cols() == 0 || _columnVectors.rows() == 0)
    DUNE_THROW(Dune::MathError,
               "\nERROR: '_columnVectors' is empty!");
  else {
    // this is a matrix, check how to interpret it
    if (_columnVectors.rows() == 1) {
      // this is a row-vector, throw up
      DUNE_THROW(Dune::MathError,
                 "\nERROR: '_columnVectors' is a row-vector!");
    } else if (_columnVectors.cols() == 1) {
      // this is just one column-vector, normalize it
      Dune::Stuff::LA::Algorithm::normalize(_scalarProduct, _columnVectors);
    } else {
      // this is a set of column-vectors, check sizes
      assert(_columnVectors.rows() == _scalarProduct.rows());
      assert(_columnVectors.rows() == _scalarProduct.cols());
      typedef typename Dune::Stuff::LA::Container::EigenDenseMatrix< ElementType >::size_type size_type;
      for (size_type ii = 0; ii < _columnVectors.cols(); ++ii) {
        // get the iith column
        typedef typename Dune::Stuff::LA::Container::EigenDenseMatrix< ElementType >::BackendType::ColXpr ColumnType;
        ColumnType iith_column = _columnVectors.backend().col(ii);
        // and orthonormalize it wrt all previous columns
        for (size_type jj = 0; jj < ii; ++ jj) {
          // therefore, get the jjth column,
          ColumnType jjth_column = _columnVectors.backend().col(jj);
          // project the iith column wrt to the jjth column
          const ElementType factor = iith_column.transpose() * _scalarProduct.backend() * jjth_column;
          iith_column -= factor * jjth_column;
        }
        // and finally normalize the iith column
        const ElementType norm = std::sqrt(iith_column.transpose() * _scalarProduct.backend() * iith_column);
        _columnVectors.backend().col(ii) = iith_column / norm;
      }
    } // this is a matrix, check how to interpret it
  } // if this is an empty matrix, throw up
} // void normalize(Dune::Stuff::LA::Container::EigenDenseMatrix< ElementType >& _matrix)
#endif // HAVE_EIGEN

template< class ScalarProductType, class BasisVectorsType, class ContainerType >
void gramSchmidt(const ScalarProductType& /*scalarProduct*/,
                 const BasisVectorsType& /*_columnBasisVectors*/,
                 ContainerType& /*_columnVectors*/)
{
  dune_static_assert((Dune::AlwaysFalse< ScalarProductType >::value || Dune::AlwaysFalse< ContainerType >::value),
                     "ERROR: not implemeneted for this combination of ScalarProductType/BasisVectorsType/ContainerType!");
}

#if HAVE_EIGEN
template< class ElementType >
bool gramSchmidt(const Dune::Stuff::LA::Container::EigenRowMajorSparseMatrix< ElementType >& _scalarProduct,
                 const Dune::Stuff::LA::Container::EigenDenseMatrix< ElementType >& _columnBasisVectors,
                 Dune::Stuff::LA::Container::EigenDenseVector< ElementType >& _vector,
                 const ElementType epsilon = 1e-10)
{
  // if this is an empty vector, throw up
  if (_vector.size() == 0)
    DUNE_THROW(Dune::MathError,
               "\nERROR: '_vector' is empty!");
  else {
    // check sizes
    assert(_scalarProduct.rows() == _vector.size());
    assert(_scalarProduct.cols() == _vector.size());
    assert(_columnBasisVectors.rows() == _vector.size());
    typedef typename Dune::Stuff::LA::Container::EigenDenseMatrix< ElementType >::size_type size_type;
    // orthonormalize _vector wrt all columns in _columnBasisVectors
    for (size_type jj = 0; jj < _columnBasisVectors.cols(); ++ jj) {
      // therefore, subtract its projection onto the jjth basis vector
      const ElementType factor = _vector.backend().transpose() * _scalarProduct.backend() * _columnBasisVectors.backend().col(jj);
      const ElementType norm = _columnBasisVectors.backend().col(jj).transpose() * _scalarProduct.backend() * _columnBasisVectors.backend().col(jj);
      _vector.backend() -= (factor/norm) * _columnBasisVectors.backend().col(jj);
    }
    // and normalize it
    const ElementType norm = std::sqrt(_vector.backend().transpose() * _scalarProduct.backend() * _vector.backend());
    if (norm < epsilon)
      return false;
    else {
      _vector.backend() /= norm;
      return true;
    }
  } // if this is an empty matrix, throw up
} // void normalize(Dune::Stuff::LA::Container::EigenDenseVector< ElementType >& _vector)
#endif // HAVE_EIGEN

} // namespace Algorithm
} // namespace LA
} // namespace Stuff
} // namespace Dune

#endif // DUNE_STUFF_LA_ALGORITHM_GRAMSCHMIDT_HH
<|endoftext|>


<commit_before>#ifndef unittest__hpp_
#define unittest__hpp_

/*! \file
 *  \brief A (very) simple unit test framework.
 */

#if defined(_MSC_VER)
#define NOMINMAX
#else
using std::isnan;
#endif

#include <vector>
#include <string>
#include <stdexcept>
#include <sstream>
#include <iostream>

class Failure
{
public:
  Failure(
      std::string const & test_suite_name,
      std::string const & test_case_name,
      std::string what)
    : test_suite_name_(test_suite_name)
    , test_case_name_(test_case_name)
    , what_(what)
  {
  }

  friend std::ostream & operator<<(std::ostream & out, Failure const & failure);

private:
  std::string test_suite_name_;
  std::string test_case_name_;
  std::string what_;
};

class Test_Result
{
public:
  void add_failure(Failure const & failure)
  {
    failures_.push_back(failure);
  }

  void add_error(Failure const & failure)
  {
    errors_.push_back(failure);
  }

  std::vector<Failure> const & failures() const
  {
    return failures_;
  }

  std::vector<Failure> const & errors() const
  {
    return errors_;
  }

private:
  std::vector<Failure> failures_;
  std::vector<Failure> errors_;
};

class Test_Case
{
public:
  typedef void (*Func)();

  Test_Case(
      std::string const & name,
      Func f)
    : name_(name)
    , f_(f)
  {
  }

  void run()
  {
    f_();
  }

  std::string const & name() const { return name_; }

  size_t size() const { return 1; }

private:
  std::string name_;
  Func f_;
};

class Test_Suite
{
public:
  Test_Suite(std::string const & name = "");

  void add_test_case(Test_Case const & test_case)
  {
    test_cases_.push_back(test_case);
  }

  void setup(void (*f)()) { setup_ = f; }
  void teardown(void (*f)()) { teardown_ = f; }

  void run(Test_Result & result);

  std::string const & name() const { return name_; }

  size_t size() const { return test_cases_.size(); }

private:
  std::string name_;

  typedef std::vector<Test_Case> Test_Cases;
  Test_Cases test_cases_;

  void (*setup_)();
  void (*teardown_)();
};

Test_Suite & test_suite();
void new_test_suite(std::string const & name);

class Assertion_Failed
  : public std::runtime_error
{
public:
  Assertion_Failed(std::string const & what)
    : std::runtime_error(what)
  {
  }
};

// TODO: not sure how to append __LINE__ correctly here
#define UNIQUE_SUITE_NAME(prefix, name) \
  prefix ## __ ## name \

#define TESTSUITE(name) \
  struct UNIQUE_SUITE_NAME(testsuite_append, name) \
  { \
    UNIQUE_SUITE_NAME(testsuite_append, name)() \
    { \
      new_test_suite(#name); \
    } \
  } UNIQUE_SUITE_NAME(testsuite_append__initializer, name)

#define TESTCASE(name) \
  static void UNIQUE_SUITE_NAME(test, name)(); \
  \
  namespace \
  { \
    struct UNIQUE_SUITE_NAME(test_append, name) \
    { \
      UNIQUE_SUITE_NAME(test_append, name)() \
      { \
        test_suite().add_test_case( \
            Test_Case(#name, & UNIQUE_SUITE_NAME(test, name))); \
      } \
    } UNIQUE_SUITE_NAME(test_append__initializer, name); \
  } \
  \
  static void UNIQUE_SUITE_NAME(test, name)()

#define TESTFIXTURE(name, type) \
  static void UNIQUE_SUITE_NAME(fixture ## __ ## name, type)(); \
  \
  namespace \
  { \
    struct UNIQUE_SUITE_NAME(fixture_append ## __ ## name, type) \
    { \
      UNIQUE_SUITE_NAME(fixture_append ## __ ## name, type)() \
      { \
        test_suite().type(UNIQUE_SUITE_NAME(fixture ## __ ## name, type)); \
      } \
    } UNIQUE_SUITE_NAME(fixture_append__initializer ## __ ## name, type); \
  } \
  \
  static void UNIQUE_SUITE_NAME(fixture ## __ ## name, type)()

#define SETUP(name) TESTFIXTURE(name, setup)

#define TEARDOWN(name) TESTFIXTURE(name, teardown)

template<typename RHS_T, typename LHS_T>
inline bool is_equal(RHS_T const & rhs, LHS_T const & lhs)
{
  return rhs == lhs;
}

inline bool is_equal(char const * lhs, char const * rhs)
{
  return std::string(lhs) == std::string(rhs);
}

inline bool is_equal(char * lhs, char const * rhs)
{
  return std::string(lhs) == std::string(rhs);
}

inline bool is_equal(char const * lhs, char * rhs)
{
  return std::string(lhs) == std::string(rhs);
}

template<typename T, typename U>
inline bool is_not_equal(T const & t, U const & u)
{
  return !is_equal(t, u);
}

extern size_t assertions;

template<typename T, typename U>
void assert_equal(
    T const & t,
    U const & u,
    std::string const & s_t,
    std::string const & s_u,
    std::string const & file,
    size_t line)
{
  if(!is_equal(t, u))
  {
    std::stringstream strm;
    strm << "Assertion failed: "
      << s_t << " != " << s_u
      << " (" << t << " != " << u << ")"
      << " at " << file << ":" << line;
    throw Assertion_Failed(strm.str());
  }
}

template<typename T, typename U>
void assert_not_equal(
    T const & t,
    U const & u,
    std::string const & s_t,
    std::string const & s_u,
    std::string const & file,
    size_t line)
{
  if(!is_not_equal(t, u))
  {
    std::stringstream strm;
    strm << "Assertion failed: "
      << s_t << " should != " << s_u
      << " (" << t << " should != " << u << ")"
      << " at " << file << ":" << line;
    throw Assertion_Failed(strm.str());
  }
}

#define ASSERT_EQUAL(x, y) \
  do \
  { \
    ++assertions; \
    assert_equal((x), (y), #x, #y, __FILE__, __LINE__); \
  } while(0)

#define ASSERT_NOT_EQUAL(x, y) \
  do \
  { \
    ++assertions; \
    assert_not_equal((x), (y), #x, #y, __FILE__, __LINE__); \
  } while(0)

#define ASSERT(x) \
  ASSERT_EQUAL(true, !!x);

#define ASSERT_EXCEPTION_CHECK(type, code, check_exception) \
  try \
  { \
    ++assertions; \
    code; \
    ASSERT(!"Expected exception"); \
  } \
  catch(type const & ex) \
  { \
    check_exception; \
  }

#define ASSERT_EXCEPTION(type, code) \
  ASSERT_EXCEPTION_CHECK(type, code, )

#endif

<commit_msg>Wrong syntax for isnan on linux. Builds on both win32 and linux platforms<commit_after>#ifndef unittest__hpp_
#define unittest__hpp_

/*! \file
 *  \brief A (very) simple unit test framework.
 */

#if defined(_MSC_VER)
#define NOMINMAX
#else
using namespace std;
#endif

#include <vector>
#include <string>
#include <stdexcept>
#include <sstream>
#include <iostream>

class Failure
{
public:
  Failure(
      std::string const & test_suite_name,
      std::string const & test_case_name,
      std::string what)
    : test_suite_name_(test_suite_name)
    , test_case_name_(test_case_name)
    , what_(what)
  {
  }

  friend std::ostream & operator<<(std::ostream & out, Failure const & failure);

private:
  std::string test_suite_name_;
  std::string test_case_name_;
  std::string what_;
};

class Test_Result
{
public:
  void add_failure(Failure const & failure)
  {
    failures_.push_back(failure);
  }

  void add_error(Failure const & failure)
  {
    errors_.push_back(failure);
  }

  std::vector<Failure> const & failures() const
  {
    return failures_;
  }

  std::vector<Failure> const & errors() const
  {
    return errors_;
  }

private:
  std::vector<Failure> failures_;
  std::vector<Failure> errors_;
};

class Test_Case
{
public:
  typedef void (*Func)();

  Test_Case(
      std::string const & name,
      Func f)
    : name_(name)
    , f_(f)
  {
  }

  void run()
  {
    f_();
  }

  std::string const & name() const { return name_; }

  size_t size() const { return 1; }

private:
  std::string name_;
  Func f_;
};

class Test_Suite
{
public:
  Test_Suite(std::string const & name = "");

  void add_test_case(Test_Case const & test_case)
  {
    test_cases_.push_back(test_case);
  }

  void setup(void (*f)()) { setup_ = f; }
  void teardown(void (*f)()) { teardown_ = f; }

  void run(Test_Result & result);

  std::string const & name() const { return name_; }

  size_t size() const { return test_cases_.size(); }

private:
  std::string name_;

  typedef std::vector<Test_Case> Test_Cases;
  Test_Cases test_cases_;

  void (*setup_)();
  void (*teardown_)();
};

Test_Suite & test_suite();
void new_test_suite(std::string const & name);

class Assertion_Failed
  : public std::runtime_error
{
public:
  Assertion_Failed(std::string const & what)
    : std::runtime_error(what)
  {
  }
};

// TODO: not sure how to append __LINE__ correctly here
#define UNIQUE_SUITE_NAME(prefix, name) \
  prefix ## __ ## name \

#define TESTSUITE(name) \
  struct UNIQUE_SUITE_NAME(testsuite_append, name) \
  { \
    UNIQUE_SUITE_NAME(testsuite_append, name)() \
    { \
      new_test_suite(#name); \
    } \
  } UNIQUE_SUITE_NAME(testsuite_append__initializer, name)

#define TESTCASE(name) \
  static void UNIQUE_SUITE_NAME(test, name)(); \
  \
  namespace \
  { \
    struct UNIQUE_SUITE_NAME(test_append, name) \
    { \
      UNIQUE_SUITE_NAME(test_append, name)() \
      { \
        test_suite().add_test_case( \
            Test_Case(#name, & UNIQUE_SUITE_NAME(test, name))); \
      } \
    } UNIQUE_SUITE_NAME(test_append__initializer, name); \
  } \
  \
  static void UNIQUE_SUITE_NAME(test, name)()

#define TESTFIXTURE(name, type) \
  static void UNIQUE_SUITE_NAME(fixture ## __ ## name, type)(); \
  \
  namespace \
  { \
    struct UNIQUE_SUITE_NAME(fixture_append ## __ ## name, type) \
    { \
      UNIQUE_SUITE_NAME(fixture_append ## __ ## name, type)() \
      { \
        test_suite().type(UNIQUE_SUITE_NAME(fixture ## __ ## name, type)); \
      } \
    } UNIQUE_SUITE_NAME(fixture_append__initializer ## __ ## name, type); \
  } \
  \
  static void UNIQUE_SUITE_NAME(fixture ## __ ## name, type)()

#define SETUP(name) TESTFIXTURE(name, setup)

#define TEARDOWN(name) TESTFIXTURE(name, teardown)

template<typename RHS_T, typename LHS_T>
inline bool is_equal(RHS_T const & rhs, LHS_T const & lhs)
{
  return rhs == lhs;
}

inline bool is_equal(char const * lhs, char const * rhs)
{
  return std::string(lhs) == std::string(rhs);
}

inline bool is_equal(char * lhs, char const * rhs)
{
  return std::string(lhs) == std::string(rhs);
}

inline bool is_equal(char const * lhs, char * rhs)
{
  return std::string(lhs) == std::string(rhs);
}

template<typename T, typename U>
inline bool is_not_equal(T const & t, U const & u)
{
  return !is_equal(t, u);
}

extern size_t assertions;

template<typename T, typename U>
void assert_equal(
    T const & t,
    U const & u,
    std::string const & s_t,
    std::string const & s_u,
    std::string const & file,
    size_t line)
{
  if(!is_equal(t, u))
  {
    std::stringstream strm;
    strm << "Assertion failed: "
      << s_t << " != " << s_u
      << " (" << t << " != " << u << ")"
      << " at " << file << ":" << line;
    throw Assertion_Failed(strm.str());
  }
}

template<typename T, typename U>
void assert_not_equal(
    T const & t,
    U const & u,
    std::string const & s_t,
    std::string const & s_u,
    std::string const & file,
    size_t line)
{
  if(!is_not_equal(t, u))
  {
    std::stringstream strm;
    strm << "Assertion failed: "
      << s_t << " should != " << s_u
      << " (" << t << " should != " << u << ")"
      << " at " << file << ":" << line;
    throw Assertion_Failed(strm.str());
  }
}

#define ASSERT_EQUAL(x, y) \
  do \
  { \
    ++assertions; \
    assert_equal((x), (y), #x, #y, __FILE__, __LINE__); \
  } while(0)

#define ASSERT_NOT_EQUAL(x, y) \
  do \
  { \
    ++assertions; \
    assert_not_equal((x), (y), #x, #y, __FILE__, __LINE__); \
  } while(0)

#define ASSERT(x) \
  ASSERT_EQUAL(true, !!x);

#define ASSERT_EXCEPTION_CHECK(type, code, check_exception) \
  try \
  { \
    ++assertions; \
    code; \
    ASSERT(!"Expected exception"); \
  } \
  catch(type const & ex) \
  { \
    check_exception; \
  }

#define ASSERT_EXCEPTION(type, code) \
  ASSERT_EXCEPTION_CHECK(type, code, )

#endif

<|endoftext|>