<commit_before>/*
   For more information, please see: http://software.sci.utah.edu

   The MIT License

   Copyright (c) 2008 Scientific Computing and Imaging Institute,
   University of Utah.

   Permission is hereby granted, free of charge, to any person obtaining a
   copy of this software and associated documentation files (the "Software"),
   to deal in the Software without restriction, including without limitation
   the rights to use, copy, modify, merge, publish, distribute, sublicense,
   and/or sell copies of the Software, and to permit persons to whom the
   Software is furnished to do so, subject to the following conditions:

   The above copyright notice and this permission notice shall be included
   in all copies or substantial portions of the Software.

   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
   THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
   DEALINGS IN THE SOFTWARE.
*/

//!    File   : RenderWindow.cpp
//!    Author : Jens Krueger
//!             SCI Institute
//!             University of Utah
//!    Date   : July 2008
//
//!    Copyright (C) 2008 SCI Institute

#include "RenderWindow.h"
#include "ImageVis3D.h"

#include <QtGui/QtGui>
#include <QtOpenGL/QtOpenGL>
#include <assert.h>

RenderWindow::RenderWindow(MasterController& masterController, QString dataset, unsigned int iCounter, QGLWidget* glShareWidget, QWidget* parent, Qt::WindowFlags flags) :
  QGLWidget(parent, glShareWidget, flags),
  m_Renderer((GPUSBVR*)masterController.RequestNewVolumerenderer(OPENGL_SBVR)),
  m_MasterController(masterController),
  m_iTimeSliceMSecsActive(500),
  m_iTimeSliceMSecsInActive(100),
  m_strDataset(dataset),
  m_vWinDim(0,0),
  m_MainWindow((MainWindow*)parent)
{
  m_strID = tr("[%1] %2").arg(iCounter).arg(m_strDataset);
  setWindowTitle(m_strID);

  m_Renderer->LoadDataset(m_strDataset.toStdString());

  this->setFocusPolicy(Qt::StrongFocus);
}

RenderWindow::~RenderWindow()
{
  Cleanup();
}

QSize RenderWindow::minimumSizeHint() const
{
  return QSize(50, 50);
}

QSize RenderWindow::sizeHint() const
{
  return QSize(400, 400);
}

void RenderWindow::initializeGL()
{
  static bool bFirstTime = true;
  if (bFirstTime) {
    int err = glewInit();
    if (err != GLEW_OK) {
      m_MasterController.DebugOut()->Error("RenderWindow::initializeGL", "Error initializing GLEW: %s",glewGetErrorString(err));
    } else {
      const GLubyte *vendor=glGetString(GL_VENDOR);
      const GLubyte *renderer=glGetString(GL_RENDERER);
      const GLubyte *version=glGetString(GL_VERSION);
      m_MasterController.DebugOut()->Message("RenderWindow::initializeGL", "Starting up GL! Running on a %s %s with OpenGL version %s",vendor, renderer, version);
    }

    bFirstTime = false;
  }

  if (m_Renderer != NULL) m_Renderer->Initialize();
}

void RenderWindow::paintGL()
{
  if (m_Renderer != NULL) {
    m_Renderer->Paint();
    if (isActiveWindow()) {
        m_MainWindow->SetRenderProgress(m_Renderer->GetFrameProgress(), m_Renderer->GetSubFrameProgress());
    }
  }
}

void RenderWindow::resizeGL(int width, int height)
{
  m_vWinDim = UINTVECTOR2((unsigned int)width, (unsigned int)height);
  if (m_Renderer != NULL) m_Renderer->Resize(UINTVECTOR2(width, height));
}

void RenderWindow::mousePressEvent(QMouseEvent *event)
{
  if (event->button() == Qt::RightButton) {
     // nothing todo yet
  }
  if (event->button() == Qt::LeftButton) {
    m_Renderer->Click(UINTVECTOR2(event->pos().x(), event->pos().y()));
  }
}

void RenderWindow::mouseReleaseEvent(QMouseEvent *event) {
  if (event->button() == Qt::LeftButton) {
    m_Renderer->Release(UINTVECTOR2(event->pos().x(), event->pos().y()));
  }
}

float scale(int max, float w) {
	if (w < 0) {
		return w-(((int)w/max)-1)*max;
	} else {
		return w-((int)w/max)*max;
	}
}

void RenderWindow::mouseMoveEvent(QMouseEvent *event)
{
  if (event->buttons() & Qt::LeftButton) {
    m_Renderer->Drag(UINTVECTOR2(event->x(), event->y()));
    updateGL();
  }
}

void RenderWindow::wheelEvent(QWheelEvent *event) {
  m_Renderer->Zoom(event->delta());
}

void RenderWindow::keyPressEvent ( QKeyEvent * event ) {
  QGLWidget::keyPressEvent(event);

  if (event->key() == Qt::Key_Space) {
    AbstrRenderer::EViewMode eMode = AbstrRenderer::EViewMode((int(m_Renderer->GetViewmode()) + 1) % int(AbstrRenderer::VM_INVALID));
    m_Renderer->SetViewmode(eMode);
    emit RenderWindowViewChanged(int(m_Renderer->GetViewmode()));
    updateGL();
  }

}

void RenderWindow::ToggleRenderWindowView2x2() {
  if (m_Renderer != NULL) {
    m_Renderer->SetViewmode(AbstrRenderer::VM_TWOBYTWO);
    emit RenderWindowViewChanged(int(m_Renderer->GetViewmode()));
    updateGL();
  }
}

void RenderWindow::ToggleRenderWindowViewSingle() {
  if (m_Renderer != NULL) {
    m_Renderer->SetViewmode(AbstrRenderer::VM_SINGLE);
    emit RenderWindowViewChanged(int(m_Renderer->GetViewmode()));
    updateGL();
  }
}

void RenderWindow::Cleanup() {
  if (m_Renderer == NULL) return;

  makeCurrent();
  m_Renderer->Cleanup();
  m_MasterController.ReleaseVolumerenderer(m_Renderer);
  m_Renderer = NULL;
}

void RenderWindow::closeEvent(QCloseEvent *event) {
  QGLWidget::closeEvent(event);

  emit WindowClosing(this);
}

void RenderWindow::focusInEvent ( QFocusEvent * event ) {
  // call superclass method
  QGLWidget::focusInEvent(event);
  m_Renderer->SetTimeSlice(m_iTimeSliceMSecsActive);

  if (event->gotFocus()) {
    emit WindowActive(this);
  }
}

void RenderWindow::focusOutEvent ( QFocusEvent * event ) {
  // call superclass method
  QGLWidget::focusOutEvent(event);
  m_Renderer->SetTimeSlice(m_iTimeSliceMSecsInActive);

  if (!event->gotFocus()) {
    emit WindowInActive(this);
  }
}

void RenderWindow::CheckForRedraw() {
  if (m_Renderer->CheckForRedraw()) {
    makeCurrent();
    update();
  }
}

void RenderWindow::SetBlendPrecision(AbstrRenderer::EBlendPrecision eBlendPrecisionMode) {
  makeCurrent();
  m_Renderer->SetBlendPrecision(eBlendPrecisionMode);
}

void RenderWindow::SetPerfMeasures(unsigned int iMinFramerate, unsigned int iLODDelay, unsigned int iActiveTS, unsigned int iInactiveTS) {
  makeCurrent();
  m_iTimeSliceMSecsActive   = iActiveTS;
  m_iTimeSliceMSecsInActive = iInactiveTS;
  m_Renderer->SetPerfMeasures(iMinFramerate, iLODDelay);
}
<commit_msg>fixed warning on linux<commit_after>/*
   For more information, please see: http://software.sci.utah.edu

   The MIT License

   Copyright (c) 2008 Scientific Computing and Imaging Institute,
   University of Utah.

   Permission is hereby granted, free of charge, to any person obtaining a
   copy of this software and associated documentation files (the "Software"),
   to deal in the Software without restriction, including without limitation
   the rights to use, copy, modify, merge, publish, distribute, sublicense,
   and/or sell copies of the Software, and to permit persons to whom the
   Software is furnished to do so, subject to the following conditions:

   The above copyright notice and this permission notice shall be included
   in all copies or substantial portions of the Software.

   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
   THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
   DEALINGS IN THE SOFTWARE.
*/

//!    File   : RenderWindow.cpp
//!    Author : Jens Krueger
//!             SCI Institute
//!             University of Utah
//!    Date   : July 2008
//
//!    Copyright (C) 2008 SCI Institute

#include "RenderWindow.h"
#include "ImageVis3D.h"

#include <QtGui/QtGui>
#include <QtOpenGL/QtOpenGL>
#include <assert.h>

RenderWindow::RenderWindow(MasterController& masterController, QString dataset, unsigned int iCounter, QGLWidget* glShareWidget, QWidget* parent, Qt::WindowFlags flags) :
  QGLWidget(parent, glShareWidget, flags),
  m_MainWindow((MainWindow*)parent),
  m_Renderer((GPUSBVR*)masterController.RequestNewVolumerenderer(OPENGL_SBVR)),
  m_MasterController(masterController),
  m_iTimeSliceMSecsActive(500),
  m_iTimeSliceMSecsInActive(100),
  m_strDataset(dataset),
  m_vWinDim(0,0)
{
  m_strID = tr("[%1] %2").arg(iCounter).arg(m_strDataset);
  setWindowTitle(m_strID);

  m_Renderer->LoadDataset(m_strDataset.toStdString());

  this->setFocusPolicy(Qt::StrongFocus);
}

RenderWindow::~RenderWindow()
{
  Cleanup();
}

QSize RenderWindow::minimumSizeHint() const
{
  return QSize(50, 50);
}

QSize RenderWindow::sizeHint() const
{
  return QSize(400, 400);
}

void RenderWindow::initializeGL()
{
  static bool bFirstTime = true;
  if (bFirstTime) {
    int err = glewInit();
    if (err != GLEW_OK) {
      m_MasterController.DebugOut()->Error("RenderWindow::initializeGL", "Error initializing GLEW: %s",glewGetErrorString(err));
    } else {
      const GLubyte *vendor=glGetString(GL_VENDOR);
      const GLubyte *renderer=glGetString(GL_RENDERER);
      const GLubyte *version=glGetString(GL_VERSION);
      m_MasterController.DebugOut()->Message("RenderWindow::initializeGL", "Starting up GL! Running on a %s %s with OpenGL version %s",vendor, renderer, version);
    }

    bFirstTime = false;
  }

  if (m_Renderer != NULL) m_Renderer->Initialize();
}

void RenderWindow::paintGL()
{
  if (m_Renderer != NULL) {
    m_Renderer->Paint();
    if (isActiveWindow()) {
        m_MainWindow->SetRenderProgress(m_Renderer->GetFrameProgress(), m_Renderer->GetSubFrameProgress());
    }
  }
}

void RenderWindow::resizeGL(int width, int height)
{
  m_vWinDim = UINTVECTOR2((unsigned int)width, (unsigned int)height);
  if (m_Renderer != NULL) m_Renderer->Resize(UINTVECTOR2(width, height));
}

void RenderWindow::mousePressEvent(QMouseEvent *event)
{
  if (event->button() == Qt::RightButton) {
     // nothing todo yet
  }
  if (event->button() == Qt::LeftButton) {
    m_Renderer->Click(UINTVECTOR2(event->pos().x(), event->pos().y()));
  }
}

void RenderWindow::mouseReleaseEvent(QMouseEvent *event) {
  if (event->button() == Qt::LeftButton) {
    m_Renderer->Release(UINTVECTOR2(event->pos().x(), event->pos().y()));
  }
}

float scale(int max, float w) {
	if (w < 0) {
		return w-(((int)w/max)-1)*max;
	} else {
		return w-((int)w/max)*max;
	}
}

void RenderWindow::mouseMoveEvent(QMouseEvent *event)
{
  if (event->buttons() & Qt::LeftButton) {
    m_Renderer->Drag(UINTVECTOR2(event->x(), event->y()));
    updateGL();
  }
}

void RenderWindow::wheelEvent(QWheelEvent *event) {
  m_Renderer->Zoom(event->delta());
}

void RenderWindow::keyPressEvent ( QKeyEvent * event ) {
  QGLWidget::keyPressEvent(event);

  if (event->key() == Qt::Key_Space) {
    AbstrRenderer::EViewMode eMode = AbstrRenderer::EViewMode((int(m_Renderer->GetViewmode()) + 1) % int(AbstrRenderer::VM_INVALID));
    m_Renderer->SetViewmode(eMode);
    emit RenderWindowViewChanged(int(m_Renderer->GetViewmode()));
    updateGL();
  }

}

void RenderWindow::ToggleRenderWindowView2x2() {
  if (m_Renderer != NULL) {
    m_Renderer->SetViewmode(AbstrRenderer::VM_TWOBYTWO);
    emit RenderWindowViewChanged(int(m_Renderer->GetViewmode()));
    updateGL();
  }
}

void RenderWindow::ToggleRenderWindowViewSingle() {
  if (m_Renderer != NULL) {
    m_Renderer->SetViewmode(AbstrRenderer::VM_SINGLE);
    emit RenderWindowViewChanged(int(m_Renderer->GetViewmode()));
    updateGL();
  }
}

void RenderWindow::Cleanup() {
  if (m_Renderer == NULL) return;

  makeCurrent();
  m_Renderer->Cleanup();
  m_MasterController.ReleaseVolumerenderer(m_Renderer);
  m_Renderer = NULL;
}

void RenderWindow::closeEvent(QCloseEvent *event) {
  QGLWidget::closeEvent(event);

  emit WindowClosing(this);
}

void RenderWindow::focusInEvent ( QFocusEvent * event ) {
  // call superclass method
  QGLWidget::focusInEvent(event);
  m_Renderer->SetTimeSlice(m_iTimeSliceMSecsActive);

  if (event->gotFocus()) {
    emit WindowActive(this);
  }
}

void RenderWindow::focusOutEvent ( QFocusEvent * event ) {
  // call superclass method
  QGLWidget::focusOutEvent(event);
  m_Renderer->SetTimeSlice(m_iTimeSliceMSecsInActive);

  if (!event->gotFocus()) {
    emit WindowInActive(this);
  }
}

void RenderWindow::CheckForRedraw() {
  if (m_Renderer->CheckForRedraw()) {
    makeCurrent();
    update();
  }
}

void RenderWindow::SetBlendPrecision(AbstrRenderer::EBlendPrecision eBlendPrecisionMode) {
  makeCurrent();
  m_Renderer->SetBlendPrecision(eBlendPrecisionMode);
}

void RenderWindow::SetPerfMeasures(unsigned int iMinFramerate, unsigned int iLODDelay, unsigned int iActiveTS, unsigned int iInactiveTS) {
  makeCurrent();
  m_iTimeSliceMSecsActive   = iActiveTS;
  m_iTimeSliceMSecsInActive = iInactiveTS;
  m_Renderer->SetPerfMeasures(iMinFramerate, iLODDelay);
}
<|endoftext|>


<commit_before>///
/// @file  S2_easy.cpp
/// @brief Calculate the contribution of the clustered easy leaves
///        and the sparse easy leaves in parallel using OpenMP
///        (Deleglise-Rivat algorithm).
///
/// Copyright (C) 2014 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#include <PiTable.hpp>
#include <primecount-internal.hpp>
#include <inttypes.hpp>
#include <pmath.hpp>
#include <S2Status.hpp>

#include <stdint.h>
#include <algorithm>
#include <iostream>
#include <vector>

#ifdef _OPENMP
  #include <omp.h>
#endif

using namespace std;
using namespace primecount;

namespace {
namespace S2_easy {

/// Calculate the contribution of the clustered easy leaves
/// and the sparse easy leaves.
/// @param T  either int64_t or uint128_t.
///
template <typename T1, typename T2, typename T3>
T1 S2_easy(T1 x,
           int64_t y,
           int64_t z,
           int64_t c,
           T2& pi,
           vector<T3>& primes,
           int threads)
{
  if (print_status())
  {
    cout << endl;
    cout << "=== S2_easy(x, y) ===" << endl;
    cout << "Computation of the easy special leaves" << endl;
  }

  int64_t pi_sqrty = pi[isqrt(y)];
  int64_t pi_x13 = pi[iroot<3>(x)];
  T1 S2_total = 0;
  double time = get_wtime();
  S2Status status;

  #pragma omp parallel for schedule(dynamic, 1) num_threads(threads) reduction(+: S2_total)
  for (int64_t b = max(c, pi_sqrty) + 1; b <= pi_x13; b++)
  {
    T1 prime = primes[b];
    int64_t prime64 =  primes[b];
    int64_t min_trivial_leaf = min(x / (prime * prime), y);
    int64_t min_clustered_easy_leaf = isqrt(x / prime64);
    int64_t min_sparse_easy_leaf = z / prime64;
    int64_t min_hard_leaf = max(y / prime64, prime64);

    min_sparse_easy_leaf = max(min_sparse_easy_leaf, min_hard_leaf);
    min_clustered_easy_leaf = max(min_clustered_easy_leaf, min_hard_leaf);
    int64_t l = pi[min_trivial_leaf];
    T1 S2_result = 0;

    // Find all clustered easy leaves:
    // x / n <= y and phi(x / n, b - 1) == phi(x / m, b - 1)
    // where phi(x / n, b - 1) = pi(x / n) - b + 2
    while (primes[l] > min_clustered_easy_leaf)
    {
      T1 n = prime * primes[l];
      int64_t xn = (int64_t) (x / n);
      int64_t phi_xn = pi[xn] - b + 2;
      T1 m = prime * primes[b + phi_xn - 1];
      int64_t xm = max((int64_t) (x / m), min_clustered_easy_leaf);
      int64_t l2 = pi[xm];
      T1 phi_factor = l - l2;
      S2_result += phi_xn * phi_factor;
      l = l2;
    }

    // Find all sparse easy leaves:
    // x / n <= y and phi(x / n, b - 1) = pi(x / n) - b + 2
    for (; primes[l] > min_sparse_easy_leaf; l--)
    {
      T1 n = prime * primes[l];
      int64_t xn = (int64_t) (x / n);
      S2_result += pi[xn] - b + 2;
    }

    if (print_status())
      status.print(b, pi_x13);

    S2_total += S2_result;
  }

  if (print_status())
    print_result("S2_easy", S2_total, time);

  return S2_total;
}

} // namespace S2_easy
} // namespace

namespace primecount {

int64_t S2_easy(int64_t x,
                int64_t y,
                int64_t z,
                int64_t c,
                vector<int32_t>& pi,
                vector<int32_t>& primes,
                int threads)
{
  return S2_easy::S2_easy((intfast64_t) x, y, z, c, pi, primes, threads);
}

int64_t S2_easy(int64_t x,
                int64_t y,
                int64_t z,
                int64_t c,
                PiTable& pi,
                vector<int32_t>& primes,
                int threads)
{
  return S2_easy::S2_easy((intfast64_t) x, y, z, c, pi, primes, threads);
}

#ifdef HAVE_INT128_T

int128_t S2_easy(int128_t x,
                 int64_t y,
                 int64_t z,
                 int64_t c,
                 PiTable& pi,
                 vector<uint32_t>& primes,
                 int threads)
{
  return S2_easy::S2_easy((intfast128_t) x, y, z, c, pi, primes, threads);
}

int128_t S2_easy(int128_t x,
                 int64_t y,
                 int64_t z,
                 int64_t c,
                 PiTable& pi,
                 vector<int64_t>& primes,
                 int threads)
{
  return S2_easy::S2_easy((intfast128_t) x, y, z, c, pi, primes, threads);
}

#endif

} // namespace primecount
<commit_msg>Add cast<commit_after>///
/// @file  S2_easy.cpp
/// @brief Calculate the contribution of the clustered easy leaves
///        and the sparse easy leaves in parallel using OpenMP
///        (Deleglise-Rivat algorithm).
///
/// Copyright (C) 2014 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#include <PiTable.hpp>
#include <primecount-internal.hpp>
#include <inttypes.hpp>
#include <pmath.hpp>
#include <S2Status.hpp>

#include <stdint.h>
#include <algorithm>
#include <iostream>
#include <vector>

#ifdef _OPENMP
  #include <omp.h>
#endif

using namespace std;
using namespace primecount;

namespace {
namespace S2_easy {

/// Calculate the contribution of the clustered easy leaves
/// and the sparse easy leaves.
/// @param T  either int64_t or uint128_t.
///
template <typename T1, typename T2, typename T3>
T1 S2_easy(T1 x,
           int64_t y,
           int64_t z,
           int64_t c,
           T2& pi,
           vector<T3>& primes,
           int threads)
{
  if (print_status())
  {
    cout << endl;
    cout << "=== S2_easy(x, y) ===" << endl;
    cout << "Computation of the easy special leaves" << endl;
  }

  int64_t pi_sqrty = pi[isqrt(y)];
  int64_t pi_x13 = pi[iroot<3>(x)];
  T1 S2_total = 0;
  double time = get_wtime();
  S2Status status;

  #pragma omp parallel for schedule(dynamic, 1) num_threads(threads) reduction(+: S2_total)
  for (int64_t b = max(c, pi_sqrty) + 1; b <= pi_x13; b++)
  {
    T1 prime = primes[b];
    int64_t prime64 =  primes[b];
    int64_t min_trivial_leaf = min(x / (prime * prime), y);
    int64_t min_clustered_easy_leaf = (int64_t) isqrt(x / prime64);
    int64_t min_sparse_easy_leaf = z / prime64;
    int64_t min_hard_leaf = max(y / prime64, prime64);

    min_sparse_easy_leaf = max(min_sparse_easy_leaf, min_hard_leaf);
    min_clustered_easy_leaf = max(min_clustered_easy_leaf, min_hard_leaf);
    int64_t l = pi[min_trivial_leaf];
    T1 S2_result = 0;

    // Find all clustered easy leaves:
    // x / n <= y and phi(x / n, b - 1) == phi(x / m, b - 1)
    // where phi(x / n, b - 1) = pi(x / n) - b + 2
    while (primes[l] > min_clustered_easy_leaf)
    {
      T1 n = prime * primes[l];
      int64_t xn = (int64_t) (x / n);
      int64_t phi_xn = pi[xn] - b + 2;
      T1 m = prime * primes[b + phi_xn - 1];
      int64_t xm = max((int64_t) (x / m), min_clustered_easy_leaf);
      int64_t l2 = pi[xm];
      T1 phi_factor = l - l2;
      S2_result += phi_xn * phi_factor;
      l = l2;
    }

    // Find all sparse easy leaves:
    // x / n <= y and phi(x / n, b - 1) = pi(x / n) - b + 2
    for (; primes[l] > min_sparse_easy_leaf; l--)
    {
      T1 n = prime * primes[l];
      int64_t xn = (int64_t) (x / n);
      S2_result += pi[xn] - b + 2;
    }

    if (print_status())
      status.print(b, pi_x13);

    S2_total += S2_result;
  }

  if (print_status())
    print_result("S2_easy", S2_total, time);

  return S2_total;
}

} // namespace S2_easy
} // namespace

namespace primecount {

int64_t S2_easy(int64_t x,
                int64_t y,
                int64_t z,
                int64_t c,
                vector<int32_t>& pi,
                vector<int32_t>& primes,
                int threads)
{
  return S2_easy::S2_easy((intfast64_t) x, y, z, c, pi, primes, threads);
}

int64_t S2_easy(int64_t x,
                int64_t y,
                int64_t z,
                int64_t c,
                PiTable& pi,
                vector<int32_t>& primes,
                int threads)
{
  return S2_easy::S2_easy((intfast64_t) x, y, z, c, pi, primes, threads);
}

#ifdef HAVE_INT128_T

int128_t S2_easy(int128_t x,
                 int64_t y,
                 int64_t z,
                 int64_t c,
                 PiTable& pi,
                 vector<uint32_t>& primes,
                 int threads)
{
  return S2_easy::S2_easy((intfast128_t) x, y, z, c, pi, primes, threads);
}

int128_t S2_easy(int128_t x,
                 int64_t y,
                 int64_t z,
                 int64_t c,
                 PiTable& pi,
                 vector<int64_t>& primes,
                 int threads)
{
  return S2_easy::S2_easy((intfast128_t) x, y, z, c, pi, primes, threads);
}

#endif

} // namespace primecount
<|endoftext|>


<commit_before>#include "ghost/densemat_rm.h"
#include "ghost/util.h"
#include "ghost/locality.h"
#include <complex>

#define ROWMAJOR
#include "ghost/densemat_iter_macros.h"

template<typename T>
static ghost_error ghost_densemat_rm_averagehalo_tmpl(ghost_densemat *vec)
{
#ifdef GHOST_HAVE_MPI
    GHOST_FUNC_ENTER(GHOST_FUNCTYPE_COMMUNICATION);
    ghost_error ret = GHOST_SUCCESS;

    int rank, nrank, i, j, d, acc_dues = 0;
    T *work = NULL, *curwork = NULL;
    MPI_Request *req = NULL;
    T *sum = NULL;
    int *nrankspresent = NULL;

/*    if (vec->traits.ncols > 1) {
        ERROR_LOG("Multi-vec case not yet implemented");
        ret = GHOST_ERR_NOT_IMPLEMENTED;
        goto err;
    }
*/
    if (vec->context == NULL) {
        WARNING_LOG("Trying to average the halos of a densemat which has no context!");
        goto out;
    }

    GHOST_CALL_GOTO(ghost_rank(&rank,vec->context->mpicomm),err,ret);
    GHOST_CALL_GOTO(ghost_nrank(&nrank,vec->context->mpicomm),err,ret);

    for (i=0; i<nrank; i++) {
       acc_dues += vec->context->dues[i];
    }

    GHOST_CALL_GOTO(ghost_malloc((void **)&work, acc_dues*sizeof(T)),err,ret);
    GHOST_CALL_GOTO(ghost_malloc((void **)&req, 2*nrank*sizeof(MPI_Request)),err,ret);

    for (i=0; i<2*nrank; i++) {
        req[i] = MPI_REQUEST_NULL;
    }

   /* if(vec->context->perm_local && vec->context->flags & GHOST_PERM_NO_DISTINCTION){
    	for (int to_PE=0; to_PE<nrank; to_PE++) {
		T* packed_data;
		GHOST_CALL_GOTO(ghost_malloc((void **)&packed_data, vec->context->wishes[to_PE]*vec->traits.ncols*vec->elSize),err,ret);

    //   printf("packed data\n");
		for (int i=0; i<vec->context->wishes[to_PE]; i++){
                    for (int c=0; c<vec->traits.ncols; c++) {
                       memcpy(&packed_data[(c*vec->context->wishes[to_PE]+i)],DENSEMAT_VALPTR(vec,vec->context->perm_local->colPerm[vec->context->hput_pos[to_PE]+i],c),vec->elSize);
//			printf("%f\n",packed_data[(c*vec->context->wishes[to_PE]+i)]);

                    }
                }
               //TODO blocking and delete packed_data
               MPI_CALL_GOTO(MPI_Isend(packed_data,vec->context->wishes[to_PE]*vec->traits.ncols,vec->mpidt,to_PE,rank,vec->context->mpicomm,&req[to_PE]),err,ret);

   	}

    } else {*/
        for (i=0; i<nrank; i++) {
                MPI_CALL_GOTO(MPI_Isend(&((T *)vec->val)[vec->context->hput_pos[i]],vec->context->wishes[i]*vec->traits.ncols,vec->mpidt,i,rank,vec->context->mpicomm,&req[i]),err,ret);
        }
   // }

    curwork = work;
    for (i=0; i<nrank; i++) {
         MPI_CALL_GOTO(MPI_Irecv(curwork,vec->context->dues[i]*vec->traits.ncols,vec->mpidt,i,i,vec->context->mpicomm,&req[nrank+i]),err,ret);
        curwork += vec->context->dues[i];
    }

    MPI_CALL_GOTO(MPI_Waitall(2*nrank,req,MPI_STATUSES_IGNORE),err,ret);

     GHOST_CALL_GOTO(ghost_malloc((void **)&sum, vec->traits.ncols*vec->traits.nrows*sizeof(T)),err,ret);
     GHOST_CALL_GOTO(ghost_malloc((void **)&nrankspresent, vec->traits.nrows*sizeof(int)),err,ret);

#pragma omp parallel for schedule(static) private(i,j)
     for (i=0; i<vec->traits.nrows; i++) {
	     if(vec->context->perm_local) {
		     if(vec->context->perm_local->colInvPerm[i]< vec->context->lnrows[rank] ) { //This check is important since entsInCol has only lnrows(NO_DISTINCTION
			     //might give seg fault else) the rest are halo anyway, not needed for local sums
			     nrankspresent[i] = vec->context->entsInCol[vec->context->perm_local->colInvPerm[i]]?1:0; //this has also to be permuted since it was
			     //for unpermuted columns that we calculate
			     if(nrankspresent[i]==1){
				     for(j=0;j<vec->traits.ncols;++j){
					     sum[i*vec->traits.ncols+j] = ((T *)vec->val)[i*vec->traits.ncols+j];
				     }
			     } else {
				     for(j=0;j<vec->traits.ncols;++j){
					     sum[i*vec->traits.ncols+j] = 0;
				     }
			     }
		     } else {
			     nrankspresent[i] = 0;
			     for(j=0;j<vec->traits.ncols;++j){
				     sum[i*vec->traits.ncols+j]=0;
			     }
		     }
	     } else {
		     nrankspresent[i] = vec->context->entsInCol[i]?1:0;
		     if(nrankspresent[i]==1) {
			     for(j=0;j<vec->traits.ncols;++j){
				     sum[i*vec->traits.ncols+j] = ((T *)vec->val)[i*vec->traits.ncols+j];
			     }
		     } else {
			     for(j=0;j<vec->traits.ncols;++j){
				     sum[i*vec->traits.ncols+j] = 0;
			     }
		     }
	     }
     }

     ghost_lidx currow;
     curwork = work;

    for (i=0; i<nrank; i++) {
	    if(vec->context->perm_local) {
#pragma omp parallel for schedule(static) private(d,j)
	        for (d=0 ;d < vec->context->dues[i]; d++) {
			for(j=0 ; j<vec->traits.ncols; ++j) {
		    		sum[(vec->context->perm_local->colPerm[vec->context->duelist[i][d]])*vec->traits.ncols+j] += curwork[d*vec->traits.ncols+j];
			 }
			nrankspresent[vec->context->perm_local->colPerm[vec->context->duelist[i][d]]]++;
		}
	    } else {
#pragma omp parallel for schedule(static) private(d,j)
	        for (d=0 ;d < vec->context->dues[i]; d++) {
  		      for(j=0 ; j<vec->traits.ncols; ++j) {
              		sum[(vec->context->duelist[i][d])*vec->traits.ncols+j] += curwork[d*vec->traits.ncols+j];
            	      }
            	      nrankspresent[vec->context->duelist[i][d]]++;
		 }
	      }
           curwork += vec->context->dues[i]*vec->traits.ncols;
    }

#pragma omp parallel for schedule(static) private(currow,j)
    for (currow=0; currow<vec->traits.nrows; currow++) {
      if(nrankspresent[currow]!=0) {
		for(j=0; j<vec->traits.ncols; ++j) {
 	       		((T *)vec->val)[currow*vec->traits.ncols+j] = sum[currow*vec->traits.ncols+j]/(T)nrankspresent[currow];
		}
	    }
    }

/* } else {
    GHOST_CALL_GOTO(ghost_malloc((void **)&sum, vec->context->lnrows[rank]*sizeof(T)),err,ret);
    GHOST_CALL_GOTO(ghost_malloc((void **)&nrankspresent, vec->context->lnrows[rank]*sizeof(int)),err,ret);

    for (i=0; i<vec->context->lnrows[rank]; i++) {
        sum[i] = ((T *)vec->val)[i];
    	nrankspresent[i] = vec->context->entsInCol[i]?1:0;
    }

    ghost_lidx currow;
    curwork = work;
    for (i=0; i<nrank; i++) {
        for (d=0 ;d < vec->context->dues[i]; d++) {
	   if(vec->context->perm_local) {
	           sum[vec->context->perm_local->colPerm[vec->context->duelist[i][d]]] +=  curwork[d];
	           nrankspresent[vec->context->perm_local->colPerm[vec->context->duelist[i][d]]]++;
	   } else {
          	   sum[vec->context->duelist[i][d]] += curwork[d];
           	   nrankspresent[vec->context->duelist[i][d]]++;
	   }
        }
        curwork += vec->context->dues[i];
    }

      for (i=0; i<vec->context->lnrows[rank]; i++) {
        printf("<%d> ranks of row[%d] = %d\n",rank,i,nrankspresent[i]);
    }

    for (currow=0; currow<vec->context->lnrows[rank]; currow++) {
        ((T *)vec->val)[currow] = sum[currow]/(T)nrankspresent[currow];
    }
   }
*/

    goto out;
err:

out:
    free(sum);
    free(nrankspresent);
    free(work);
    free(req);
    GHOST_FUNC_EXIT(GHOST_FUNCTYPE_COMMUNICATION);
    return ret;
#else
    UNUSED(vec);
    ERROR_LOG("MPI is required!");
    return GHOST_ERR_MPI;
#endif
}

ghost_error ghost_densemat_rm_averagehalo_selector(ghost_densemat *vec)
{
    GHOST_FUNC_ENTER(GHOST_FUNCTYPE_COMMUNICATION);
    ghost_error ret = GHOST_SUCCESS;

    SELECT_TMPL_1DATATYPE(vec->traits.datatype,std::complex,ret,ghost_densemat_rm_averagehalo_tmpl,vec);

    GHOST_FUNC_EXIT(GHOST_FUNCTYPE_COMMUNICATION);
    return ret;
}
<commit_msg>Fix error in block vector averaging<commit_after>#include "ghost/densemat_rm.h"
#include "ghost/util.h"
#include "ghost/locality.h"
#include <complex>

#define ROWMAJOR
#include "ghost/densemat_iter_macros.h"

template<typename T>
static ghost_error ghost_densemat_rm_averagehalo_tmpl(ghost_densemat *vec)
{
#ifdef GHOST_HAVE_MPI
    GHOST_FUNC_ENTER(GHOST_FUNCTYPE_COMMUNICATION);
    ghost_error ret = GHOST_SUCCESS;

    int rank, nrank, i, j, d, acc_dues = 0;
    T *work = NULL, *curwork = NULL;
    MPI_Request *req = NULL;
    T *sum = NULL;
    int *nrankspresent = NULL;

/*    if (vec->traits.ncols > 1) {
        ERROR_LOG("Multi-vec case not yet implemented");
        ret = GHOST_ERR_NOT_IMPLEMENTED;
        goto err;
    }
*/
    if (vec->context == NULL) {
        WARNING_LOG("Trying to average the halos of a densemat which has no context!");
        goto out;
    }

    GHOST_CALL_GOTO(ghost_rank(&rank,vec->context->mpicomm),err,ret);
    GHOST_CALL_GOTO(ghost_nrank(&nrank,vec->context->mpicomm),err,ret);

    for (i=0; i<nrank; i++) {
       acc_dues += vec->context->dues[i];
    }

    GHOST_CALL_GOTO(ghost_malloc((void **)&work, vec->traits.ncols*acc_dues*sizeof(T)),err,ret);
    GHOST_CALL_GOTO(ghost_malloc((void **)&req, 2*nrank*sizeof(MPI_Request)),err,ret);

    for (i=0; i<2*nrank; i++) {
        req[i] = MPI_REQUEST_NULL;
    }

   /* if(vec->context->perm_local && vec->context->flags & GHOST_PERM_NO_DISTINCTION){
    	for (int to_PE=0; to_PE<nrank; to_PE++) {
		T* packed_data;
		GHOST_CALL_GOTO(ghost_malloc((void **)&packed_data, vec->context->wishes[to_PE]*vec->traits.ncols*vec->elSize),err,ret);

    //   printf("packed data\n");
		for (int i=0; i<vec->context->wishes[to_PE]; i++){
                    for (int c=0; c<vec->traits.ncols; c++) {
                       memcpy(&packed_data[(c*vec->context->wishes[to_PE]+i)],DENSEMAT_VALPTR(vec,vec->context->perm_local->colPerm[vec->context->hput_pos[to_PE]+i],c),vec->elSize);
//			printf("%f\n",packed_data[(c*vec->context->wishes[to_PE]+i)]);

                    }
                }
               //TODO blocking and delete packed_data
               MPI_CALL_GOTO(MPI_Isend(packed_data,vec->context->wishes[to_PE]*vec->traits.ncols,vec->mpidt,to_PE,rank,vec->context->mpicomm,&req[to_PE]),err,ret);

   	}

    } else {*/
        for (i=0; i<nrank; i++) {
                MPI_CALL_GOTO(MPI_Isend(&((T *)vec->val)[vec->context->hput_pos[i]*vec->traits.ncols],vec->context->wishes[i]*vec->traits.ncols,vec->mpidt,i,rank,vec->context->mpicomm,&req[i]),err,ret);
        }
   // }

    curwork = work;
    for (i=0; i<nrank; i++) {
         MPI_CALL_GOTO(MPI_Irecv(curwork,vec->context->dues[i]*vec->traits.ncols,vec->mpidt,i,i,vec->context->mpicomm,&req[nrank+i]),err,ret);
        curwork += vec->context->dues[i];
    }

    MPI_CALL_GOTO(MPI_Waitall(2*nrank,req,MPI_STATUSES_IGNORE),err,ret);

     GHOST_CALL_GOTO(ghost_malloc((void **)&sum, vec->traits.ncols*vec->traits.nrows*sizeof(T)),err,ret);
     GHOST_CALL_GOTO(ghost_malloc((void **)&nrankspresent, vec->traits.nrows*sizeof(int)),err,ret);

#pragma omp parallel for schedule(static) private(i,j)
     for (i=0; i<vec->traits.nrows; i++) {
	     if(vec->context->perm_local) {
		     if(vec->context->perm_local->colInvPerm[i]< vec->context->lnrows[rank] ) { //This check is important since entsInCol has only lnrows(NO_DISTINCTION
			     //might give seg fault else) the rest are halo anyway, not needed for local sums
			     nrankspresent[i] = vec->context->entsInCol[vec->context->perm_local->colInvPerm[i]]?1:0; //this has also to be permuted since it was
			     //for unpermuted columns that we calculate
			     if(nrankspresent[i]==1){
				     for(j=0;j<vec->traits.ncols;++j){
					     sum[i*vec->traits.ncols+j] = ((T *)vec->val)[i*vec->traits.ncols+j];
				     }
			     } else {
				     for(j=0;j<vec->traits.ncols;++j){
					     sum[i*vec->traits.ncols+j] = 0;
				     }
			     }
		     } else {
			     nrankspresent[i] = 0;
			     for(j=0;j<vec->traits.ncols;++j){
				     sum[i*vec->traits.ncols+j]=0;
			     }
		     }
	     } else {
		     nrankspresent[i] = vec->context->entsInCol[i]?1:0;
		     if(nrankspresent[i]==1) {
			     for(j=0;j<vec->traits.ncols;++j){
				     sum[i*vec->traits.ncols+j] = ((T *)vec->val)[i*vec->traits.ncols+j];
			     }
		     } else {
			     for(j=0;j<vec->traits.ncols;++j){
				     sum[i*vec->traits.ncols+j] = 0;
			     }
		     }
	     }
     }

     ghost_lidx currow;
     curwork = work;

    for (i=0; i<nrank; i++) {
	    if(vec->context->perm_local) {
#pragma omp parallel for schedule(static) private(d,j)
	        for (d=0 ;d < vec->context->dues[i]; d++) {
			for(j=0 ; j<vec->traits.ncols; ++j) {
		    		sum[( vec->context->perm_local->colPerm[vec->context->duelist[i][d]] )*vec->traits.ncols + j] += curwork[d*vec->traits.ncols+j];
			 }
			nrankspresent[vec->context->perm_local->colPerm[vec->context->duelist[i][d]]]++;
		}
	    } else {
#pragma omp parallel for schedule(static) private(d,j)
	        for (d=0 ;d < vec->context->dues[i]; d++) {
  		      for(j=0 ; j<vec->traits.ncols; ++j) {
              		sum[(vec->context->duelist[i][d])*vec->traits.ncols+j] += curwork[d*vec->traits.ncols+j];
            	      }
            	      nrankspresent[vec->context->duelist[i][d]]++;
		 }
	      }
           curwork += vec->context->dues[i]*vec->traits.ncols;
    }

#pragma omp parallel for schedule(static) private(currow,j)
    for (currow=0; currow<vec->traits.nrows; currow++) {
      if(nrankspresent[currow]!=0) {
		for(j=0; j<vec->traits.ncols; ++j) {
 	       		((T *)vec->val)[currow*vec->traits.ncols+j] = sum[currow*vec->traits.ncols+j]/(T)nrankspresent[currow];
		}
	    }
    }

/* } else {
    GHOST_CALL_GOTO(ghost_malloc((void **)&sum, vec->context->lnrows[rank]*sizeof(T)),err,ret);
    GHOST_CALL_GOTO(ghost_malloc((void **)&nrankspresent, vec->context->lnrows[rank]*sizeof(int)),err,ret);

    for (i=0; i<vec->context->lnrows[rank]; i++) {
        sum[i] = ((T *)vec->val)[i];
    	nrankspresent[i] = vec->context->entsInCol[i]?1:0;
    }

    ghost_lidx currow;
    curwork = work;
    for (i=0; i<nrank; i++) {
        for (d=0 ;d < vec->context->dues[i]; d++) {
	   if(vec->context->perm_local) {
	           sum[vec->context->perm_local->colPerm[vec->context->duelist[i][d]]] +=  curwork[d];
	           nrankspresent[vec->context->perm_local->colPerm[vec->context->duelist[i][d]]]++;
	   } else {
          	   sum[vec->context->duelist[i][d]] += curwork[d];
           	   nrankspresent[vec->context->duelist[i][d]]++;
	   }
        }
        curwork += vec->context->dues[i];
    }

      for (i=0; i<vec->context->lnrows[rank]; i++) {
        printf("<%d> ranks of row[%d] = %d\n",rank,i,nrankspresent[i]);
    }

    for (currow=0; currow<vec->context->lnrows[rank]; currow++) {
        ((T *)vec->val)[currow] = sum[currow]/(T)nrankspresent[currow];
    }
   }
*/

    goto out;
err:

out:
    free(sum);
    free(nrankspresent);
    free(work);
    free(req);
    GHOST_FUNC_EXIT(GHOST_FUNCTYPE_COMMUNICATION);
    return ret;
#else
    UNUSED(vec);
    ERROR_LOG("MPI is required!");
    return GHOST_ERR_MPI;
#endif
}

ghost_error ghost_densemat_rm_averagehalo_selector(ghost_densemat *vec)
{
    GHOST_FUNC_ENTER(GHOST_FUNCTYPE_COMMUNICATION);
    ghost_error ret = GHOST_SUCCESS;

    SELECT_TMPL_1DATATYPE(vec->traits.datatype,std::complex,ret,ghost_densemat_rm_averagehalo_tmpl,vec);

    GHOST_FUNC_EXIT(GHOST_FUNCTYPE_COMMUNICATION);
    return ret;
}
<|endoftext|>


<commit_before>/***************************************************************************
**
** Copyright (C) 2010, 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (directui@nokia.com)
**
** This file is part of libmeegotouch.
**
** 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 "mcolorlistview.h"
#include "mcolorlistview_p.h"

#include <MButton>
#include <MButtonGroup>
#include <MGridLayoutPolicy>
#include <MLayout>
#include <MTheme>
#include <QGraphicsGridLayout>
#include <MStylableWidget>

#include "mcolorlist.h"

M_REGISTER_VIEW_NEW(MColorListView, MColorList)

class SimpleColoredButton : public MButton
{
public:

    SimpleColoredButton() : m_color(QColor(0, 0, 0))
    {
    }

    SimpleColoredButton(const QColor &color) : m_color(color)
    {
    }

    ~SimpleColoredButton()
    {
    }

    QColor color()
    {
        return m_color;
    }

    void setColor(const QColor &color)
    {
        m_color = color;
    }

    void paint(QPainter *painter, const QStyleOptionGraphicsItem *option , QWidget *widget)
    {
        Q_UNUSED(option);
        Q_UNUSED(widget);
        QRectF paintRect(style()->marginLeft(),
                         style()->marginTop(),
                         size().width() - style()->marginLeft() - style()->marginRight(),
                         size().height() - style()->marginTop() - style()->marginBottom());

        painter->fillRect(paintRect, m_color);
        if (isChecked()) {
            painter->setPen(QColor(0, 0, 0));
            painter->drawRect(rect());
        }
    }

private:

    QColor m_color;

};

MColorListViewPrivate::MColorListViewPrivate(MColorListView *p, MColorList *controller)
    : q_ptr(p), controller(controller), landscapePolicy(0), portraitPolicy(0), buttonGroup(0)
{
    QGraphicsGridLayout *layout = new QGraphicsGridLayout();
    layout->setContentsMargins(0, 0, 0, 0);
    layout->setSpacing(0);
    controller->setLayout(layout);

    MStylableWidget* container = new MStylableWidget();
    container->setStyleName("ColorSelectionContainer");
    MLayout *containerLayout = new MLayout();
    container->setLayout(containerLayout);

    landscapePolicy = new MGridLayoutPolicy(containerLayout);
    landscapePolicy->setContentsMargins(0, 0, 0, 0);
    landscapePolicy->setSpacing(0);
    containerLayout->setLandscapePolicy(landscapePolicy);

    portraitPolicy = new MGridLayoutPolicy(containerLayout);
    portraitPolicy->setContentsMargins(0, 0, 0, 0);
    portraitPolicy->setSpacing(0);
    containerLayout->setPortraitPolicy(portraitPolicy);

    layout->addItem(container, 0, 0);

    // Current color list
    colors << QColor(0x95, 0xE8, 0x5D);
    colors << QColor(0x73, 0xC0, 0xF5);
    colors << QColor(0xCB, 0xA4, 0xDE);
    colors << QColor(0xE9, 0x48, 0xA3);
    colors << QColor(0xFF, 0x9E, 0x9E);
    colors << QColor(0xFF, 0xF6, 0x57);
    colors << QColor(0x9C, 0x9C, 0x9C);

    colors << QColor(0x74, 0xD9, 0x41);
    colors << QColor(0x31, 0xB0, 0xDE);
    colors << QColor(0xBC, 0x79, 0xDE);
    colors << QColor(0xE9, 0x48, 0xA3);
    colors << QColor(0xFF, 0x79, 0x4D);
    colors << QColor(0xFB, 0xFF, 0x14);
    colors << QColor(0x80, 0x80, 0x80);

    colors << QColor(0x55, 0xD5, 0x00);
    colors << QColor(0x00, 0x88, 0xE6);
    colors << QColor(0xAE, 0x4E, 0xDE);
    colors << QColor(0xE9, 0x48, 0xA3);
    colors << QColor(0xFF, 0x40, 0x00);
    colors << QColor(0xFF, 0xE6, 0x00);
    colors << QColor(0x4D, 0x4D, 0x4D);

    colors << QColor(0x45, 0x90, 0x27);
    colors << QColor(0x00, 0x6F, 0xBA);
    colors << QColor(0x89, 0x3D, 0xAF);
    colors << QColor(0xE9, 0x48, 0xA3);
    colors << QColor(0xCC, 0x33, 0x00);
    colors << QColor(0xFF, 0x90, 0x00);
    colors << QColor(0x33, 0x33, 0x33);

    colors << QColor(0x00, 0x73, 0x00);
    colors << QColor(0x00, 0x41, 0x82);
    colors << QColor(0x5E, 0x2A, 0x78);
    colors << QColor(0xE9, 0x48, 0xA3);
    colors << QColor(0xB5, 0x2D, 0x00);
    colors << QColor(0xFF, 0x6A, 0x00);
    colors << QColor(0x1A, 0x1A, 0x1A);
}

MColorListViewPrivate::~MColorListViewPrivate()
{
    delete buttonGroup;
}

void MColorListViewPrivate::updateColors()
{
    Q_Q(MColorListView);

    // A bit crude, perhaps, but let's conserve memory. this is called
    // relatively rarely anyway.
    if (buttonGroup) {
        int i = landscapePolicy->count() - 1;
        Q_ASSERT(landscapePolicy->count() == portraitPolicy->count());
        while (i >= 0) {
            landscapePolicy->removeAt(i--);
            portraitPolicy->removeAt(i--);
        }
        QList<MButton*> list = buttonGroup->buttons();
        while (!list.isEmpty()) {
            delete list.takeLast();
        }
        delete buttonGroup;
    }

    buttonGroup = new MButtonGroup();
    QObject::connect(buttonGroup, SIGNAL(buttonClicked(MButton*)),
                     q, SLOT(buttonClicked(MButton*)));

    const QColor &selectedColor = q->model()->selectedColor();

    int landColumns = 7;
    int portRows = 7;
    for (int i = 0; i < colors.size(); ++i) {
        SimpleColoredButton* button = new SimpleColoredButton(colors[i]);
        button->setStyleName("ColorSelectionButton");
        button->setCheckable(true);
        // We must check for selected color here too as the button has
        // to be checked *before* it is added to the group.
        if (colors[i] == selectedColor) {
            button->setChecked(true);
        }
        buttonGroup->addButton(button);
        // TODO: Calendar ALG defines that the color list should roll
        // horizontally in landscape mode (row by row), and vertically
        // in portraint mode (column by column). The implementation
        // here doesn't work nicely (for portrait) if we have more or
        // less colors than 28.
        landscapePolicy->addItem(button, i/landColumns, i%landColumns);
        portraitPolicy->addItem(button, i%portRows, i/portRows);
    }
}

void MColorListViewPrivate::updateSelectedColor()
{
    Q_Q(MColorListView);
    const QColor &color = q->model()->selectedColor();

    QList<MButton*> buttons = buttonGroup->buttons();
    for (int i = 0; i < buttons.size(); ++i) {
        if (static_cast<SimpleColoredButton*>(buttons[i])->color() == color) {
            buttons[i]->setChecked(true);
            break;
        }
    }
}

MColorListView::MColorListView(MColorList *controller)
    :MWidgetView(controller), d_ptr(new MColorListViewPrivate(this, controller))
{

}

MColorListView::~MColorListView()
{
    delete d_ptr;
}

void MColorListView::applyStyle()
{
    MWidgetView::applyStyle();
}

void MColorListView::setupModel()
{
    MWidgetView::setupModel();
    Q_D(MColorListView);
    d->updateColors();
    /*
     * Note: d->updateSelectedColor() should not be called here because the
     * selected button has to be checked before it is added to a MButtonGroup
     * for the button group to function properly.
     */
}

void MColorListView::updateData(const QList<const char*> &modifications)
{
    Q_D(MColorListView);
    MWidgetView::updateData(modifications);

    const char *member;
    foreach (member, modifications) {
        if (member == MColorListModel::SelectedColor) {
            d->updateSelectedColor();
        }
    }
}

void MColorListView::buttonClicked(MButton *button)
{
    model()->setSelectedColor(static_cast<SimpleColoredButton*>(button)->color());
}
<commit_msg>Fixes: NB#255284 - MColorList contains wrong colors<commit_after>/***************************************************************************
**
** Copyright (C) 2010, 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (directui@nokia.com)
**
** This file is part of libmeegotouch.
**
** 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 "mcolorlistview.h"
#include "mcolorlistview_p.h"

#include <MButton>
#include <MButtonGroup>
#include <MGridLayoutPolicy>
#include <MLayout>
#include <MTheme>
#include <QGraphicsGridLayout>
#include <MStylableWidget>

#include "mcolorlist.h"

M_REGISTER_VIEW_NEW(MColorListView, MColorList)

class SimpleColoredButton : public MButton
{
public:

    SimpleColoredButton() : m_color(QColor(0, 0, 0))
    {
    }

    SimpleColoredButton(const QColor &color) : m_color(color)
    {
    }

    ~SimpleColoredButton()
    {
    }

    QColor color()
    {
        return m_color;
    }

    void setColor(const QColor &color)
    {
        m_color = color;
    }

    void paint(QPainter *painter, const QStyleOptionGraphicsItem *option , QWidget *widget)
    {
        Q_UNUSED(option);
        Q_UNUSED(widget);
        QRectF paintRect(style()->marginLeft(),
                         style()->marginTop(),
                         size().width() - style()->marginLeft() - style()->marginRight(),
                         size().height() - style()->marginTop() - style()->marginBottom());

        painter->fillRect(paintRect, m_color);
        if (isChecked()) {
            painter->setPen(QColor(0, 0, 0));
            painter->drawRect(rect());
        }
    }

private:

    QColor m_color;

};

MColorListViewPrivate::MColorListViewPrivate(MColorListView *p, MColorList *controller)
    : q_ptr(p), controller(controller), landscapePolicy(0), portraitPolicy(0), buttonGroup(0)
{
    QGraphicsGridLayout *layout = new QGraphicsGridLayout();
    layout->setContentsMargins(0, 0, 0, 0);
    layout->setSpacing(0);
    controller->setLayout(layout);

    MStylableWidget* container = new MStylableWidget();
    container->setStyleName("ColorSelectionContainer");
    MLayout *containerLayout = new MLayout();
    container->setLayout(containerLayout);

    landscapePolicy = new MGridLayoutPolicy(containerLayout);
    landscapePolicy->setContentsMargins(0, 0, 0, 0);
    landscapePolicy->setSpacing(0);
    containerLayout->setLandscapePolicy(landscapePolicy);

    portraitPolicy = new MGridLayoutPolicy(containerLayout);
    portraitPolicy->setContentsMargins(0, 0, 0, 0);
    portraitPolicy->setSpacing(0);
    containerLayout->setPortraitPolicy(portraitPolicy);

    layout->addItem(container, 0, 0);

    // Current color list
    colors << QColor(0x92, 0xD1, 0x5E);
    colors << QColor(0x68, 0xBF, 0xDE);
    colors << QColor(0xBB, 0x7F, 0xDE);
    colors << QColor(0xFF, 0x87, 0x95);
    colors << QColor(0xFF, 0xE3, 0x59);
    colors << QColor(0xC0, 0xBD, 0xAB);

    colors << QColor(0x5F, 0xC2, 0x1D);
    colors << QColor(0x31, 0x9C, 0xDE);
    colors << QColor(0x95, 0x6F, 0xCF);
    colors << QColor(0xED, 0x4C, 0x4C);
    colors << QColor(0xFF, 0xC9, 0x1A);
    colors << QColor(0x8A, 0x87, 0x80);

    colors << QColor(0x58, 0xAD, 0x2D);
    colors << QColor(0x29, 0x7D, 0xD1);
    colors << QColor(0xAE, 0x4E, 0xDE);
    colors << QColor(0xC9, 0x3C, 0x32);
    colors << QColor(0xFF, 0xB1, 0x14);
    colors << QColor(0x4D, 0x4D, 0x4D);

    colors << QColor(0x23, 0x8C, 0x17);
    colors << QColor(0x1A, 0x66, 0xC9);
    colors << QColor(0x86, 0x33, 0xAF);
    colors << QColor(0xB3, 0x27, 0x1E);
    colors << QColor(0xFF, 0x88, 0x00);
    colors << QColor(0x33, 0x33, 0x33);

    colors << QColor(0x24, 0x73, 0x2E);
    colors << QColor(0x12, 0x3D, 0x82);
    colors << QColor(0x6A, 0x2A, 0x78);
    colors << QColor(0x94, 0x11, 0x00);
    colors << QColor(0xFF, 0x6F, 0x00);
    colors << QColor(0x1A, 0x1A, 0x1A);
}

MColorListViewPrivate::~MColorListViewPrivate()
{
    delete buttonGroup;
}

void MColorListViewPrivate::updateColors()
{
    Q_Q(MColorListView);

    // A bit crude, perhaps, but let's conserve memory. this is called
    // relatively rarely anyway.
    if (buttonGroup) {
        int i = landscapePolicy->count() - 1;
        Q_ASSERT(landscapePolicy->count() == portraitPolicy->count());
        while (i >= 0) {
            landscapePolicy->removeAt(i--);
            portraitPolicy->removeAt(i--);
        }
        QList<MButton*> list = buttonGroup->buttons();
        while (!list.isEmpty()) {
            delete list.takeLast();
        }
        delete buttonGroup;
    }

    buttonGroup = new MButtonGroup();
    QObject::connect(buttonGroup, SIGNAL(buttonClicked(MButton*)),
                     q, SLOT(buttonClicked(MButton*)));

    const QColor &selectedColor = q->model()->selectedColor();

    int landColumns = 6;
    int portRows = 6;
    for (int i = 0; i < colors.size(); ++i) {
        SimpleColoredButton* button = new SimpleColoredButton(colors[i]);
        button->setStyleName("ColorSelectionButton");
        button->setCheckable(true);
        // We must check for selected color here too as the button has
        // to be checked *before* it is added to the group.
        if (colors[i] == selectedColor) {
            button->setChecked(true);
        }
        buttonGroup->addButton(button);
        // TODO: Calendar ALG defines that the color list should roll
        // horizontally in landscape mode (row by row), and vertically
        // in portraint mode (column by column). The implementation
        // here doesn't work nicely (for portrait) if we have more or
        // less colors than 28.
        landscapePolicy->addItem(button, i/landColumns, i%landColumns);
        portraitPolicy->addItem(button, i%portRows, i/portRows);
    }
}

void MColorListViewPrivate::updateSelectedColor()
{
    Q_Q(MColorListView);
    const QColor &color = q->model()->selectedColor();

    QList<MButton*> buttons = buttonGroup->buttons();
    for (int i = 0; i < buttons.size(); ++i) {
        if (static_cast<SimpleColoredButton*>(buttons[i])->color() == color) {
            buttons[i]->setChecked(true);
            break;
        }
    }
}

MColorListView::MColorListView(MColorList *controller)
    :MWidgetView(controller), d_ptr(new MColorListViewPrivate(this, controller))
{

}

MColorListView::~MColorListView()
{
    delete d_ptr;
}

void MColorListView::applyStyle()
{
    MWidgetView::applyStyle();
}

void MColorListView::setupModel()
{
    MWidgetView::setupModel();
    Q_D(MColorListView);
    d->updateColors();
    /*
     * Note: d->updateSelectedColor() should not be called here because the
     * selected button has to be checked before it is added to a MButtonGroup
     * for the button group to function properly.
     */
}

void MColorListView::updateData(const QList<const char*> &modifications)
{
    Q_D(MColorListView);
    MWidgetView::updateData(modifications);

    const char *member;
    foreach (member, modifications) {
        if (member == MColorListModel::SelectedColor) {
            d->updateSelectedColor();
        }
    }
}

void MColorListView::buttonClicked(MButton *button)
{
    model()->setSelectedColor(static_cast<SimpleColoredButton*>(button)->color());
}
<|endoftext|>


<commit_before>#include <gtest/gtest.h>

#include <gmpxx.h>
#include <vector>
#include <string>

#include <rsa-attack-lib/rsa-attack-lib.hh>

using namespace std;

TEST(factorize, smallSemiPrime) {
  mpz_class small_n = 48443;
  pair<mpz_class, mpz_class> expected_outputs = make_pair(193, 251);
  EXPECT_EQ(expected_outputs, rsatk::find_prime_factors(small_n));
}

TEST(factorize, bigSemiPrime) {
  mpz_class big_n = 8884963;
  pair<mpz_class, mpz_class> expected_outputs = make_pair(2677, 3319);

  // output won't be the same
  EXPECT_EQ(expected_outputs, rsatk::find_prime_factors(big_n));
}

TEST(factorize, smallNormalNumber) {
  mpz_class norm_num = 108;
  // factors are (2, 54) , (4, 27) , (9, 12) , (3, 36) , (6, 18)
  // since none of these are prime, result should be empty
  pair<mpz_class, mpz_class> expected_outputs = make_pair(0, 0);
  EXPECT_EQ(expected_outputs, rsatk::find_prime_factors(norm_num));
}

TEST(factorize, largerN) {
  mpz_class big_n = 239774199806447;

  pair<mpz_class, mpz_class> expected_outputs = make_pair(15484627, 15484661);

  // output won't be the same
  EXPECT_EQ(expected_outputs, rsatk::find_prime_factors(big_n));
  }

// test based from example in
// http://en.wikipedia.org/wiki/Extended_Euclidean_algorithm
TEST(ExtendedEuclidean, wikipediaExample) {
  mpz_class a = 240;
  mpz_class b = 46;

  mpz_class expected_x = -9;
  mpz_class expected_y = 47;
  mpz_class expected_gcd = 2;

  vector<mpz_class> actual = rsatk::extended_euclidean(a, b);
  EXPECT_EQ(expected_x, actual[0]);
  EXPECT_EQ(expected_y, actual[1]);
  EXPECT_EQ(expected_gcd, actual[2]);
}

// both of the ...CrackingRSATest fixtures pulled from here:
// http://doctrina.org/How-RSA-Works-With-Examples.html
class EasyCrackingRSATest : public ::testing::Test {
 protected:
  virtual void SetUp() { n = p * q; }

  mpz_class p = 11;  // we get this from factorization
  mpz_class q = 13;
  mpz_class e = 7;  // given(supposedly) in public key
  string m = "9";
  mpz_class n;
};

TEST_F(EasyCrackingRSATest, calculateTotient) {
  mpz_class expected_totient = 120;
  mpz_class actual_totient = rsatk::calculate_totient(p, q);
  EXPECT_EQ(expected_totient, actual_totient);
}

TEST_F(EasyCrackingRSATest, calculateD) {
  mpz_class expected_d = 103;
  mpz_class totient = rsatk::calculate_totient(p, q);
  ASSERT_EQ(120, totient);
  mpz_class actual_d = rsatk::calculate_d(totient, e);
  EXPECT_EQ(expected_d, actual_d);
}

TEST_F(EasyCrackingRSATest, applyPrivateKey) {
  string encrypted_message = "48";

  mpz_class totient = rsatk::calculate_totient(p, q);
  ASSERT_EQ(120, totient);
  mpz_class d = rsatk::calculate_d(totient, e);
  ASSERT_EQ(103, d);

  string decrypted_message = rsatk::decrypt_message(encrypted_message, n, d);

  EXPECT_EQ(m, decrypted_message);
}

class HarderCrackingRSATest : public ::testing::Test {
 protected:
  virtual void SetUp() {
    // the reason for this nonstandard initialization is discussed
    // http://stackoverflow.com/a/9844465
    n = p * q;
  }
  mpz_class p =
      12131072439211271897323671531612440428472427633701410925634549312301964373042085619324197365322416866541017057361365214171711713797974299334871062829803541_mpz;
  mpz_class q =
      12027524255478748885956220793734512128733387803682075433653899983955179850988797899869146900809131611153346817050832096022160146366346391812470987105415233_mpz;
  mpz_class e = 65537;
  string m = "attack at dawn";
  mpz_class n;
};

TEST_F(HarderCrackingRSATest, calculateTotient) {
  mpz_class expected_totient =
      145906768007583323230186939349070635292401872375357164399581871019873438799005358938369571402670149802121818086292467422828157022922076746906543401224889648313811232279966317301397777852365301547848273478871297222058587457152891606459269718119268971163555070802643999529549644116811947516513938184296683521280_mpz;
  mpz_class actual_totient = rsatk::calculate_totient(p, q);
  EXPECT_EQ(expected_totient, actual_totient);
}

TEST_F(HarderCrackingRSATest, calculateD) {
  mpz_class expected_d =
      89489425009274444368228545921773093919669586065884257445497854456487674839629818390934941973262879616797970608917283679875499331574161113854088813275488110588247193077582527278437906504015680623423550067240042466665654232383502922215493623289472138866445818789127946123407807725702626644091036502372545139713_mpz;
  mpz_class totient = rsatk::calculate_totient(p, q);
  mpz_class actual_d = rsatk::calculate_d(totient, e);
  EXPECT_EQ(expected_d, actual_d);
}

TEST_F(HarderCrackingRSATest, applyPrivateKey) {
  //string encrypted_message = encrypt_message(p, q, "attack at dawn");
  string encrypted_message = "attack at dawn";

  mpz_class totient = rsatk::calculate_totient(p, q);
  mpz_class d = rsatk::calculate_d(totient, e);

  string decrypted_message = rsatk::decrypt_message(encrypted_message, n, d);

  EXPECT_EQ(m, decrypted_message);
}

//
// TEST(known_totient, simple){
// EXPECT
//}

/*
  TEST(PublicKeyReading, findE){
  EXPECT_EQ(0,1); //dummy
  }

  TEST(Primes, Generate){
  generate_n_primes(1000000);
  }
*/

//class Attacks : public ::testing::Test {
//protected:
//virtual void SetUp() {
    //// the reason for this nonstandard initialization is discussed
    //// http://stackoverflow.com/a/9844465
    //n = p * q;
//}
//mpz_class p =
//12131072439211271897323671531612440428472427633701410925634549312301964373042085619324197365322416866541017057361365214171711713797974299334871062829803541_mpz;
//mpz_class q =
//12027524255478748885956220793734512128733387803682075433653899983955179850988797899869146900809131611153346817050832096022160146366346391812470987105415233_mpz;
//mpz_class e = 65537;
//string m = "attack at dawn";
//mpz_class n;
//};
<commit_msg>Added tests for low exponent attack<commit_after>#include <gtest/gtest.h>

#include <gmpxx.h>
#include <vector>
#include <string>

#include <rsa-attack-lib/rsa-attack-lib.hh>
#include <rsa-attack-lib/low_exponent.hh>

using namespace std;

TEST(factorize, smallSemiPrime) {
  mpz_class small_n = 48443;
  pair<mpz_class, mpz_class> expected_outputs = make_pair(193, 251);
  EXPECT_EQ(expected_outputs, rsatk::find_prime_factors(small_n));
}

TEST(factorize, bigSemiPrime) {
  mpz_class big_n = 8884963;
  pair<mpz_class, mpz_class> expected_outputs = make_pair(2677, 3319);

  // output won't be the same
  EXPECT_EQ(expected_outputs, rsatk::find_prime_factors(big_n));
}

TEST(factorize, smallNormalNumber) {
  mpz_class norm_num = 108;
  // factors are (2, 54) , (4, 27) , (9, 12) , (3, 36) , (6, 18)
  // since none of these are prime, result should be empty
  pair<mpz_class, mpz_class> expected_outputs = make_pair(0, 0);
  EXPECT_EQ(expected_outputs, rsatk::find_prime_factors(norm_num));
}

TEST(factorize, largerN) {
  mpz_class big_n = 239774199806447;

  pair<mpz_class, mpz_class> expected_outputs = make_pair(15484627, 15484661);

  // output won't be the same
  EXPECT_EQ(expected_outputs, rsatk::find_prime_factors(big_n));
  }

// test based from example in
// http://en.wikipedia.org/wiki/Extended_Euclidean_algorithm
TEST(ExtendedEuclidean, wikipediaExample) {
  mpz_class a = 240;
  mpz_class b = 46;

  mpz_class expected_x = -9;
  mpz_class expected_y = 47;
  mpz_class expected_gcd = 2;

  vector<mpz_class> actual = rsatk::extended_euclidean(a, b);
  EXPECT_EQ(expected_x, actual[0]);
  EXPECT_EQ(expected_y, actual[1]);
  EXPECT_EQ(expected_gcd, actual[2]);
}

// both of the ...CrackingRSATest fixtures pulled from here:
// http://doctrina.org/How-RSA-Works-With-Examples.html
class EasyCrackingRSATest : public ::testing::Test {
 protected:
  virtual void SetUp() { n = p * q; }

  mpz_class p = 11;  // we get this from factorization
  mpz_class q = 13;
  mpz_class e = 7;  // given(supposedly) in public key
  string m = "9";
  mpz_class n;
};

TEST_F(EasyCrackingRSATest, calculateTotient) {
  mpz_class expected_totient = 120;
  mpz_class actual_totient = rsatk::calculate_totient(p, q);
  EXPECT_EQ(expected_totient, actual_totient);
}

TEST_F(EasyCrackingRSATest, calculateD) {
  mpz_class expected_d = 103;
  mpz_class totient = rsatk::calculate_totient(p, q);
  ASSERT_EQ(120, totient);
  mpz_class actual_d = rsatk::calculate_d(totient, e);
  EXPECT_EQ(expected_d, actual_d);
}

TEST_F(EasyCrackingRSATest, applyPrivateKey) {
  string encrypted_message = "48";

  mpz_class totient = rsatk::calculate_totient(p, q);
  ASSERT_EQ(120, totient);
  mpz_class d = rsatk::calculate_d(totient, e);
  ASSERT_EQ(103, d);

  string decrypted_message = rsatk::decrypt_message(encrypted_message, n, d);

  EXPECT_EQ(m, decrypted_message);
}

class HarderCrackingRSATest : public ::testing::Test {
 protected:
  virtual void SetUp() {
    // the reason for this nonstandard initialization is discussed
    // http://stackoverflow.com/a/9844465
    n = p * q;
  }
  mpz_class p =
      12131072439211271897323671531612440428472427633701410925634549312301964373042085619324197365322416866541017057361365214171711713797974299334871062829803541_mpz;
  mpz_class q =
      12027524255478748885956220793734512128733387803682075433653899983955179850988797899869146900809131611153346817050832096022160146366346391812470987105415233_mpz;
  mpz_class e = 65537;
  string m = "attack at dawn";
  mpz_class n;
};

TEST_F(HarderCrackingRSATest, calculateTotient) {
  mpz_class expected_totient =
      145906768007583323230186939349070635292401872375357164399581871019873438799005358938369571402670149802121818086292467422828157022922076746906543401224889648313811232279966317301397777852365301547848273478871297222058587457152891606459269718119268971163555070802643999529549644116811947516513938184296683521280_mpz;
  mpz_class actual_totient = rsatk::calculate_totient(p, q);
  EXPECT_EQ(expected_totient, actual_totient);
}

TEST_F(HarderCrackingRSATest, calculateD) {
  mpz_class expected_d =
      89489425009274444368228545921773093919669586065884257445497854456487674839629818390934941973262879616797970608917283679875499331574161113854088813275488110588247193077582527278437906504015680623423550067240042466665654232383502922215493623289472138866445818789127946123407807725702626644091036502372545139713_mpz;
  mpz_class totient = rsatk::calculate_totient(p, q);
  mpz_class actual_d = rsatk::calculate_d(totient, e);
  EXPECT_EQ(expected_d, actual_d);
}

TEST_F(HarderCrackingRSATest, applyPrivateKey) {
  //string encrypted_message = encrypt_message(p, q, "attack at dawn");
  string encrypted_message = "attack at dawn";

  mpz_class totient = rsatk::calculate_totient(p, q);
  mpz_class d = rsatk::calculate_d(totient, e);

  string decrypted_message = rsatk::decrypt_message(encrypted_message, n, d);

  EXPECT_EQ(m, decrypted_message);
}

//
// TEST(known_totient, simple){
// EXPECT
//}

/*
  TEST(PublicKeyReading, findE){
  EXPECT_EQ(0,1); //dummy
  }

  TEST(Primes, Generate){
  generate_n_primes(1000000);
  }
*/

class LowExpAttacks : public ::testing::Test {
protected:
  virtual void SetUp() {
    mpz_powm(c_1.get_mpz_t(), m.get_mpz_t(), e.get_mpz_t(), n_1.get_mpz_t());
    mpz_powm(c_2.get_mpz_t(), m.get_mpz_t(), e.get_mpz_t(), n_2.get_mpz_t());
    mpz_powm(c_3.get_mpz_t(), m.get_mpz_t(), e.get_mpz_t(), n_3.get_mpz_t());

    r_1.C = c_1;
    r_2.C = c_2;
    r_3.C = c_3;

    r_1.n = n_1;
    r_2.n = n_2;
    r_3.n = n_3;

    r_1.e = e;
    r_2.e = e;
    r_3.e = e;
  }
  rsatk::RSA_data r_1;
  rsatk::RSA_data r_2;
  rsatk::RSA_data r_3;

  mpz_class e = 3;
  mpz_class m = 102;

  mpz_class n_1 = 377;
  mpz_class n_2 = 391;
  mpz_class n_3 = 589;

  mpz_class c_1;
  mpz_class c_2;
  mpz_class c_3;
};

TEST_F(LowExpAttacks, decryption){
  mpz_class decrypted = lowexp::low_exponent_attack(r_1, r_2, r_3);
  EXPECT_EQ(m, decrypted);
}
//TEST(Mod, functionTest);
<|endoftext|>


<commit_before>/*****************************************************************************
 * Media Library
 *****************************************************************************
 * Copyright (C) 2015 Hugo Beauzée-Luyssen, Videolabs
 *
 * Authors: Hugo Beauzée-Luyssen<hugo@beauzee.fr>
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

#if HAVE_CONFIG_H
# include "config.h"
#endif

#include "FsDiscoverer.h"

#include <algorithm>
#include <queue>
#include <utility>

#include "factory/FileSystemFactory.h"
#include "filesystem/IDevice.h"
#include "Media.h"
#include "File.h"
#include "Device.h"
#include "Folder.h"
#include "logging/Logger.h"
#include "MediaLibrary.h"
#include "utils/Filename.h"

namespace
{

class DeviceRemovedException : public std::runtime_error
{
public:
    DeviceRemovedException() noexcept
        : std::runtime_error( "A device was removed during the discovery" )
    {
    }
};

}

namespace medialibrary
{

FsDiscoverer::FsDiscoverer( std::shared_ptr<factory::IFileSystem> fsFactory, MediaLibrary* ml, IMediaLibraryCb* cb )
    : m_ml( ml )
    , m_fsFactory( std::move( fsFactory ))
    , m_cb( cb )
{
}

bool FsDiscoverer::discover( const std::string &entryPoint )
{
    LOG_INFO( "Adding to discovery list: ", entryPoint );

    if ( m_fsFactory->isMrlSupported( entryPoint ) == false )
        return false;

    std::shared_ptr<fs::IDirectory> fsDir = m_fsFactory->createDirectory( entryPoint );
    auto f = Folder::fromMrl( m_ml, entryPoint );
    // If the folder exists, we assume it will be handled by reload()
    if ( f != nullptr )
        return true;
    try
    {
        if ( hasDotNoMediaFile( *fsDir ) )
            return true;
        return addFolder( std::move( fsDir ), nullptr );
    }
    catch ( std::system_error& ex )
    {
        LOG_WARN( entryPoint, " discovery aborted because of a filesystem error: ", ex.what() );
    }
    catch ( sqlite::errors::ConstraintViolation& ex )
    {
        LOG_WARN( entryPoint, " discovery aborted (assuming blacklisted folder): ", ex.what() );
    }
    catch ( DeviceRemovedException& )
    {
        // Simply ignore, the device has already been marked as removed and the DB updated accordingly
        LOG_INFO( "Discovery of ", fsDir->mrl(), " was stopped after the device was removed" );
    }
    return true;
}

void FsDiscoverer::reloadFolder( std::shared_ptr<Folder> f )
{
    auto folder = m_fsFactory->createDirectory( f->mrl() );
    try
    {
        checkFolder( std::move( folder ), std::move( f ), false );
    }
    catch ( DeviceRemovedException& )
    {
        LOG_INFO( "Reloading of ", f->mrl(), " was stopped after the device was removed" );
    }
}

bool FsDiscoverer::reload()
{
    LOG_INFO( "Reloading all folders" );
    auto rootFolders = Folder::fetchRootFolders( m_ml );
    for ( const auto& f : rootFolders )
        reloadFolder( f );
    return true;
}

bool FsDiscoverer::reload( const std::string& entryPoint )
{
    if ( m_fsFactory->isMrlSupported( entryPoint ) == false )
        return false;
    LOG_INFO( "Reloading folder ", entryPoint );
    auto folder = Folder::fromMrl( m_ml, entryPoint );
    if ( folder == nullptr )
    {
        LOG_ERROR( "Can't reload ", entryPoint, ": folder wasn't found in database" );
        return false;
    }
    reloadFolder( std::move( folder ) );
    return true;
}

void FsDiscoverer::checkFolder( std::shared_ptr<fs::IDirectory> currentFolderFs,
                                std::shared_ptr<Folder> currentFolder,
                                bool newFolder ) const
{
    try
    {
        // We already know of this folder, though it may now contain a .nomedia file.
        // In this case, simply delete the folder.
        if ( hasDotNoMediaFile( *currentFolderFs ) )
        {
            if ( newFolder == false )
            {
                LOG_INFO( "Deleting folder ", currentFolderFs->mrl(), " due to a .nomedia file" );
                m_ml->deleteFolder( *currentFolder );
            }
            else
                LOG_INFO( "Ignoring folder ", currentFolderFs->mrl(), " due to a .nomedia file" );
            return;
        }
    }
    // Only check once for a system_error. They are bound to happen when we list the files/folders
    // within, and hasDotMediaFile is the first place when this is done
    catch ( std::system_error& ex )
    {
        LOG_WARN( "Failed to browse ", currentFolderFs->mrl(), ": ", ex.what() );
        // Even when we're discovering a new folder, we want to rule out device removal as the cause of
        // an IO error. If this is the cause, simply abort the discovery. All the folder we have
        // discovered so far will be marked as non-present through sqlite hooks, and we'll resume the
        // discovery when the device gets plugged back in
        if ( currentFolderFs->device()->isRemovable() )
        {
            // If the device is removable, check if it was indeed removed.
            LOG_INFO( "The device containing ", currentFolderFs->mrl(), " is removable. Checking for device removal..." );
            m_ml->refreshDevices( *m_fsFactory );
            // The device presence flag will be changed in place, so simply retest it
            if ( currentFolderFs->device()->isPresent() == false )
                throw DeviceRemovedException();
            LOG_INFO( "Device was not removed" );
        }
        // However if the device isn't removable, we want to:
        // - ignore it when we're discovering a new folder.
        // - delete it when it was discovered in the past. This is likely to be due to a permission change
        //   as we would not check the folder if it wasn't present during the parent folder browsing
        //   but it might also be that we're checking an entry point.
        //   The error won't arise earlier, as we only perform IO when reading the folder from this function.
        if ( newFolder == false )
        {
            // If we ever came across this folder, its content is now unaccessible: let's remove it.
            m_ml->deleteFolder( *currentFolder );
        }
        return;
    }

    m_cb->onDiscoveryProgress( currentFolderFs->mrl() );
    // Load the folders we already know of:
    LOG_INFO( "Checking for modifications in ", currentFolderFs->mrl() );
    // Don't try to fetch any potential sub folders if the folder was freshly added
    std::vector<std::shared_ptr<Folder>> subFoldersInDB;
    if ( newFolder == false )
        subFoldersInDB = currentFolder->folders();
    for ( const auto& subFolder : currentFolderFs->dirs() )
    {
        auto it = std::find_if( begin( subFoldersInDB ), end( subFoldersInDB ), [&subFolder](const std::shared_ptr<Folder>& f) {
            return f->mrl() == subFolder->mrl();
        });
        // We don't know this folder, it's a new one
        if ( it == end( subFoldersInDB ) )
        {
            if ( hasDotNoMediaFile( *subFolder ) )
            {
                LOG_INFO( "Ignoring folder with a .nomedia file" );
                continue;
            }
            LOG_INFO( "New folder detected: ", subFolder->mrl() );
            try
            {
                addFolder( subFolder, currentFolder.get() );
                continue;
            }
            catch ( sqlite::errors::ConstraintViolation& ex )
            {
                // Best attempt to detect a foreign key violation, indicating the parent folders have been
                // deleted due to blacklisting
                if ( strstr( ex.what(), "foreign key" ) != nullptr )
                {
                    LOG_WARN( "Creation of a folder failed because the parent is non existing: ", ex.what(),
                              ". Assuming it was deleted due to blacklisting" );
                    return;
                }
                LOG_WARN( "Creation of a duplicated folder failed: ", ex.what(), ". Assuming it was blacklisted" );
                continue;
            }
        }
        auto folderInDb = *it;
        // In any case, check for modifications, as a change related to a mountpoint might
        // not update the folder modification date.
        // Also, relying on the modification date probably isn't portable
        checkFolder( subFolder, folderInDb, false );
        subFoldersInDB.erase( it );
    }
    // Now all folders we had in DB but haven't seen from the FS must have been deleted.
    for ( const auto& f : subFoldersInDB )
    {
        LOG_INFO( "Folder ", f->mrl(), " not found in FS, deleting it" );
        m_ml->deleteFolder( *f );
    }
    checkFiles( currentFolderFs, currentFolder );
    LOG_INFO( "Done checking subfolders in ", currentFolderFs->mrl() );
}

void FsDiscoverer::checkFiles( std::shared_ptr<fs::IDirectory> parentFolderFs,
                               std::shared_ptr<Folder> parentFolder ) const
{
    LOG_INFO( "Checking file in ", parentFolderFs->mrl() );
    static const std::string req = "SELECT * FROM " + policy::FileTable::Name
            + " WHERE folder_id = ?";
    auto files = File::fetchAll<File>( m_ml, req, parentFolder->id() );
    std::vector<std::shared_ptr<fs::IFile>> filesToAdd;
    std::vector<std::shared_ptr<File>> filesToRemove;
    for ( const auto& fileFs: parentFolderFs->files() )
    {
        auto it = std::find_if( begin( files ), end( files ), [fileFs](const std::shared_ptr<File>& f) {
            return f->mrl() == fileFs->mrl();
        });
        if ( it == end( files ) )
        {
            if ( MediaLibrary::isExtensionSupported( fileFs->extension().c_str() ) == true )
                filesToAdd.push_back( fileFs );
            continue;
        }
        if ( fileFs->lastModificationDate() == (*it)->lastModificationDate() )
        {
            // Unchanged file
            files.erase( it );
            continue;
        }
        auto& file = (*it);
        LOG_INFO( "Forcing file refresh ", fileFs->mrl() );
        // Pre-cache the file's media, since we need it to remove. However, better doing it
        // out of a write context, since that way, other threads can also read the database.
        file->media();
        filesToRemove.push_back( std::move( file ) );
        filesToAdd.push_back( fileFs );
        files.erase( it );
    }
    using FilesT = decltype( files );
    using FilesToRemoveT = decltype( filesToRemove );
    using FilesToAddT = decltype( filesToAdd );
    sqlite::Tools::withRetries( 3, [this, &parentFolder, &parentFolderFs]
                            ( FilesT files, FilesToAddT filesToAdd, FilesToRemoveT filesToRemove ) {
        auto t = m_ml->getConn()->newTransaction();
        for ( auto file : files )
        {
            LOG_INFO( "File ", file->mrl(), " not found on filesystem, deleting it" );
            auto media = file->media();
            if ( media != nullptr && media->isDeleted() == false )
                media->removeFile( *file );
            else if ( file->isDeleted() == false )
            {
                // This is unexpected, as the file should have been deleted when the media was
                // removed.
                LOG_WARN( "Deleting a file without an associated media." );
                file->destroy();
            }
        }
        for ( auto& f : filesToRemove )
        {
            auto media = f->media();
            if ( media != nullptr )
                media->removeFile( *f );
            else
            {
                // If there is no media associated with this file, the file had to be removed through
                // a trigger
                assert( f->isDeleted() );
            }
        }
        // Insert all files at once to avoid SQL write contention
        for ( auto& p : filesToAdd )
            m_ml->addFile( p, parentFolder, parentFolderFs );
        t->commit();
        LOG_INFO( "Done checking files in ", parentFolderFs->mrl() );
    }, std::move( files ), std::move( filesToAdd ), std::move( filesToRemove ) );
}

bool FsDiscoverer::hasDotNoMediaFile( const fs::IDirectory& directory )
{
    const auto& files = directory.files();
    return std::find_if( begin( files ), end( files ), []( const std::shared_ptr<fs::IFile>& file ){
        return strcasecmp( file->name().c_str(), ".nomedia" ) == 0;
    }) != end( files );
}

bool FsDiscoverer::addFolder( std::shared_ptr<fs::IDirectory> folder,
                              Folder* parentFolder ) const
{
    auto deviceFs = folder->device();
    // We are creating a folder, there has to be a device containing it.
    assert( deviceFs != nullptr );
    // But gracefully handle failure in release mode
    if( deviceFs == nullptr )
        return false;
    auto device = Device::fromUuid( m_ml, deviceFs->uuid() );
    if ( device == nullptr )
    {
        LOG_INFO( "Creating new device in DB ", deviceFs->uuid() );
        device = Device::create( m_ml, deviceFs->uuid(),
                                 utils::file::scheme( folder->mrl() ),
                                 deviceFs->isRemovable() );
        if ( device == nullptr )
            return false;
    }

    auto f = Folder::create( m_ml, folder->mrl(),
                             parentFolder != nullptr ? parentFolder->id() : 0,
                             *device, *deviceFs );
    if ( f == nullptr )
        return false;
    checkFolder( std::move( folder ), std::move( f ), true );
    return true;
}

}
<commit_msg>FsDiscoverer: Gracefully handle a missing device<commit_after>/*****************************************************************************
 * Media Library
 *****************************************************************************
 * Copyright (C) 2015 Hugo Beauzée-Luyssen, Videolabs
 *
 * Authors: Hugo Beauzée-Luyssen<hugo@beauzee.fr>
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

#if HAVE_CONFIG_H
# include "config.h"
#endif

#include "FsDiscoverer.h"

#include <algorithm>
#include <queue>
#include <utility>

#include "factory/FileSystemFactory.h"
#include "filesystem/IDevice.h"
#include "Media.h"
#include "File.h"
#include "Device.h"
#include "Folder.h"
#include "logging/Logger.h"
#include "MediaLibrary.h"
#include "utils/Filename.h"

namespace
{

class DeviceRemovedException : public std::runtime_error
{
public:
    DeviceRemovedException() noexcept
        : std::runtime_error( "A device was removed during the discovery" )
    {
    }
};

}

namespace medialibrary
{

FsDiscoverer::FsDiscoverer( std::shared_ptr<factory::IFileSystem> fsFactory, MediaLibrary* ml, IMediaLibraryCb* cb )
    : m_ml( ml )
    , m_fsFactory( std::move( fsFactory ))
    , m_cb( cb )
{
}

bool FsDiscoverer::discover( const std::string &entryPoint )
{
    LOG_INFO( "Adding to discovery list: ", entryPoint );

    if ( m_fsFactory->isMrlSupported( entryPoint ) == false )
        return false;

    std::shared_ptr<fs::IDirectory> fsDir = m_fsFactory->createDirectory( entryPoint );
    auto f = Folder::fromMrl( m_ml, entryPoint );
    // If the folder exists, we assume it will be handled by reload()
    if ( f != nullptr )
        return true;
    try
    {
        if ( hasDotNoMediaFile( *fsDir ) )
            return true;
        return addFolder( std::move( fsDir ), nullptr );
    }
    catch ( std::system_error& ex )
    {
        LOG_WARN( entryPoint, " discovery aborted because of a filesystem error: ", ex.what() );
    }
    catch ( sqlite::errors::ConstraintViolation& ex )
    {
        LOG_WARN( entryPoint, " discovery aborted (assuming blacklisted folder): ", ex.what() );
    }
    catch ( DeviceRemovedException& )
    {
        // Simply ignore, the device has already been marked as removed and the DB updated accordingly
        LOG_INFO( "Discovery of ", fsDir->mrl(), " was stopped after the device was removed" );
    }
    return true;
}

void FsDiscoverer::reloadFolder( std::shared_ptr<Folder> f )
{
    auto folder = m_fsFactory->createDirectory( f->mrl() );
    try
    {
        checkFolder( std::move( folder ), std::move( f ), false );
    }
    catch ( DeviceRemovedException& )
    {
        LOG_INFO( "Reloading of ", f->mrl(), " was stopped after the device was removed" );
    }
}

bool FsDiscoverer::reload()
{
    LOG_INFO( "Reloading all folders" );
    auto rootFolders = Folder::fetchRootFolders( m_ml );
    for ( const auto& f : rootFolders )
        reloadFolder( f );
    return true;
}

bool FsDiscoverer::reload( const std::string& entryPoint )
{
    if ( m_fsFactory->isMrlSupported( entryPoint ) == false )
        return false;
    LOG_INFO( "Reloading folder ", entryPoint );
    auto folder = Folder::fromMrl( m_ml, entryPoint );
    if ( folder == nullptr )
    {
        LOG_ERROR( "Can't reload ", entryPoint, ": folder wasn't found in database" );
        return false;
    }
    reloadFolder( std::move( folder ) );
    return true;
}

void FsDiscoverer::checkFolder( std::shared_ptr<fs::IDirectory> currentFolderFs,
                                std::shared_ptr<Folder> currentFolder,
                                bool newFolder ) const
{
    try
    {
        // We already know of this folder, though it may now contain a .nomedia file.
        // In this case, simply delete the folder.
        if ( hasDotNoMediaFile( *currentFolderFs ) )
        {
            if ( newFolder == false )
            {
                LOG_INFO( "Deleting folder ", currentFolderFs->mrl(), " due to a .nomedia file" );
                m_ml->deleteFolder( *currentFolder );
            }
            else
                LOG_INFO( "Ignoring folder ", currentFolderFs->mrl(), " due to a .nomedia file" );
            return;
        }
    }
    // Only check once for a system_error. They are bound to happen when we list the files/folders
    // within, and hasDotMediaFile is the first place when this is done
    catch ( std::system_error& ex )
    {
        LOG_WARN( "Failed to browse ", currentFolderFs->mrl(), ": ", ex.what() );
        // Even when we're discovering a new folder, we want to rule out device removal as the cause of
        // an IO error. If this is the cause, simply abort the discovery. All the folder we have
        // discovered so far will be marked as non-present through sqlite hooks, and we'll resume the
        // discovery when the device gets plugged back in
        auto device = currentFolderFs->device();
        // The device might not be present at all, and therefor we might miss a
        // representation for it.
        if ( device == nullptr || device->isRemovable() )
        {
            // If the device is removable/missing, check if it was indeed removed.
            LOG_INFO( "The device containing ", currentFolderFs->mrl(), " is ",
                      device != nullptr ? "removable" : "not found",
                      ". Refreshing device cache..." );

            m_ml->refreshDevices( *m_fsFactory );
            // If the device was missing, refresh our list of devices in case
            // the device was plugged back and/or we missed a notification for it
            if ( device == nullptr )
                device = currentFolderFs->device();
            // The device presence flag will be changed in place, so simply retest it
            if ( device == nullptr || device->isPresent() == false )
                throw DeviceRemovedException();
            LOG_INFO( "Device was not removed" );
        }
        // However if the device isn't removable, we want to:
        // - ignore it when we're discovering a new folder.
        // - delete it when it was discovered in the past. This is likely to be due to a permission change
        //   as we would not check the folder if it wasn't present during the parent folder browsing
        //   but it might also be that we're checking an entry point.
        //   The error won't arise earlier, as we only perform IO when reading the folder from this function.
        if ( newFolder == false )
        {
            // If we ever came across this folder, its content is now unaccessible: let's remove it.
            m_ml->deleteFolder( *currentFolder );
        }
        return;
    }

    m_cb->onDiscoveryProgress( currentFolderFs->mrl() );
    // Load the folders we already know of:
    LOG_INFO( "Checking for modifications in ", currentFolderFs->mrl() );
    // Don't try to fetch any potential sub folders if the folder was freshly added
    std::vector<std::shared_ptr<Folder>> subFoldersInDB;
    if ( newFolder == false )
        subFoldersInDB = currentFolder->folders();
    for ( const auto& subFolder : currentFolderFs->dirs() )
    {
        auto it = std::find_if( begin( subFoldersInDB ), end( subFoldersInDB ), [&subFolder](const std::shared_ptr<Folder>& f) {
            return f->mrl() == subFolder->mrl();
        });
        // We don't know this folder, it's a new one
        if ( it == end( subFoldersInDB ) )
        {
            if ( hasDotNoMediaFile( *subFolder ) )
            {
                LOG_INFO( "Ignoring folder with a .nomedia file" );
                continue;
            }
            LOG_INFO( "New folder detected: ", subFolder->mrl() );
            try
            {
                addFolder( subFolder, currentFolder.get() );
                continue;
            }
            catch ( sqlite::errors::ConstraintViolation& ex )
            {
                // Best attempt to detect a foreign key violation, indicating the parent folders have been
                // deleted due to blacklisting
                if ( strstr( ex.what(), "foreign key" ) != nullptr )
                {
                    LOG_WARN( "Creation of a folder failed because the parent is non existing: ", ex.what(),
                              ". Assuming it was deleted due to blacklisting" );
                    return;
                }
                LOG_WARN( "Creation of a duplicated folder failed: ", ex.what(), ". Assuming it was blacklisted" );
                continue;
            }
        }
        auto folderInDb = *it;
        // In any case, check for modifications, as a change related to a mountpoint might
        // not update the folder modification date.
        // Also, relying on the modification date probably isn't portable
        checkFolder( subFolder, folderInDb, false );
        subFoldersInDB.erase( it );
    }
    // Now all folders we had in DB but haven't seen from the FS must have been deleted.
    for ( const auto& f : subFoldersInDB )
    {
        LOG_INFO( "Folder ", f->mrl(), " not found in FS, deleting it" );
        m_ml->deleteFolder( *f );
    }
    checkFiles( currentFolderFs, currentFolder );
    LOG_INFO( "Done checking subfolders in ", currentFolderFs->mrl() );
}

void FsDiscoverer::checkFiles( std::shared_ptr<fs::IDirectory> parentFolderFs,
                               std::shared_ptr<Folder> parentFolder ) const
{
    LOG_INFO( "Checking file in ", parentFolderFs->mrl() );
    static const std::string req = "SELECT * FROM " + policy::FileTable::Name
            + " WHERE folder_id = ?";
    auto files = File::fetchAll<File>( m_ml, req, parentFolder->id() );
    std::vector<std::shared_ptr<fs::IFile>> filesToAdd;
    std::vector<std::shared_ptr<File>> filesToRemove;
    for ( const auto& fileFs: parentFolderFs->files() )
    {
        auto it = std::find_if( begin( files ), end( files ), [fileFs](const std::shared_ptr<File>& f) {
            return f->mrl() == fileFs->mrl();
        });
        if ( it == end( files ) )
        {
            if ( MediaLibrary::isExtensionSupported( fileFs->extension().c_str() ) == true )
                filesToAdd.push_back( fileFs );
            continue;
        }
        if ( fileFs->lastModificationDate() == (*it)->lastModificationDate() )
        {
            // Unchanged file
            files.erase( it );
            continue;
        }
        auto& file = (*it);
        LOG_INFO( "Forcing file refresh ", fileFs->mrl() );
        // Pre-cache the file's media, since we need it to remove. However, better doing it
        // out of a write context, since that way, other threads can also read the database.
        file->media();
        filesToRemove.push_back( std::move( file ) );
        filesToAdd.push_back( fileFs );
        files.erase( it );
    }
    using FilesT = decltype( files );
    using FilesToRemoveT = decltype( filesToRemove );
    using FilesToAddT = decltype( filesToAdd );
    sqlite::Tools::withRetries( 3, [this, &parentFolder, &parentFolderFs]
                            ( FilesT files, FilesToAddT filesToAdd, FilesToRemoveT filesToRemove ) {
        auto t = m_ml->getConn()->newTransaction();
        for ( auto file : files )
        {
            LOG_INFO( "File ", file->mrl(), " not found on filesystem, deleting it" );
            auto media = file->media();
            if ( media != nullptr && media->isDeleted() == false )
                media->removeFile( *file );
            else if ( file->isDeleted() == false )
            {
                // This is unexpected, as the file should have been deleted when the media was
                // removed.
                LOG_WARN( "Deleting a file without an associated media." );
                file->destroy();
            }
        }
        for ( auto& f : filesToRemove )
        {
            auto media = f->media();
            if ( media != nullptr )
                media->removeFile( *f );
            else
            {
                // If there is no media associated with this file, the file had to be removed through
                // a trigger
                assert( f->isDeleted() );
            }
        }
        // Insert all files at once to avoid SQL write contention
        for ( auto& p : filesToAdd )
            m_ml->addFile( p, parentFolder, parentFolderFs );
        t->commit();
        LOG_INFO( "Done checking files in ", parentFolderFs->mrl() );
    }, std::move( files ), std::move( filesToAdd ), std::move( filesToRemove ) );
}

bool FsDiscoverer::hasDotNoMediaFile( const fs::IDirectory& directory )
{
    const auto& files = directory.files();
    return std::find_if( begin( files ), end( files ), []( const std::shared_ptr<fs::IFile>& file ){
        return strcasecmp( file->name().c_str(), ".nomedia" ) == 0;
    }) != end( files );
}

bool FsDiscoverer::addFolder( std::shared_ptr<fs::IDirectory> folder,
                              Folder* parentFolder ) const
{
    auto deviceFs = folder->device();
    // We are creating a folder, there has to be a device containing it.
    assert( deviceFs != nullptr );
    // But gracefully handle failure in release mode
    if( deviceFs == nullptr )
        return false;
    auto device = Device::fromUuid( m_ml, deviceFs->uuid() );
    if ( device == nullptr )
    {
        LOG_INFO( "Creating new device in DB ", deviceFs->uuid() );
        device = Device::create( m_ml, deviceFs->uuid(),
                                 utils::file::scheme( folder->mrl() ),
                                 deviceFs->isRemovable() );
        if ( device == nullptr )
            return false;
    }

    auto f = Folder::create( m_ml, folder->mrl(),
                             parentFolder != nullptr ? parentFolder->id() : 0,
                             *device, *deviceFs );
    if ( f == nullptr )
        return false;
    checkFolder( std::move( folder ), std::move( f ), true );
    return true;
}

}
<|endoftext|>


<commit_before>#include <iostream>

#include <tightdb.hpp>

#include "../util/timer.hpp"
#include "../util/mem.hpp"
#include "../util/number_names.hpp"

using namespace std;
using namespace tightdb;

namespace {

// Get and Set are too fast (50ms/M) for normal 64-bit rand*rand*rand*rand*rand (5-10ms/M)
uint64_t rand2()
{
    static int64_t seed = 2862933555777941757ULL;
    static int64_t seed2 = 0;
    seed = (2862933555777941757ULL * seed + 3037000493ULL);
    seed2++;
    return seed * seed2 + seed2;
}

TIGHTDB_TABLE_1(IntegerTable,
                first, Int)

TIGHTDB_TABLE_1(StringTable,
                first, String)

enum Days {
    Mon,
    Tue,
    Wed,
    Thu,
    Fri,
    Sat,
    Sun
};

TIGHTDB_TABLE_4(TestTable,
                first,  Int,
                second, String,
                third,  Int,
                fourth, Enum<Days>)

} // anonymous namespace

int main()
{
    TestTable table;

    // Build large table
    for (size_t i = 0; i < 250000; ++i) {
        // create random string
        const size_t n = rand() % 1000;// * 10 + rand();
        const string s = test_util::number_name(n);

        table.add(n, s.c_str(), 100, Wed);
    }
    table.add(0, "abcde", 100, Wed);

    cout << "Memory usage: "<<test_util::get_mem_usage()<<" bytes\n";

    test_util::Timer timer;

    // Search small integer column
    {
        timer.reset();

        // Do a search over entire column (value not found)
        for (size_t i = 0; i < 100; ++i) {
            const size_t res = table.column().fourth.find_first(Tue);
            if (res != size_t(-1)) {
                cout << "error\n";
            }
        }

        cout << "Search (small integer): "<<timer<<"\n";
    }

    // Search byte-size integer column
    {
        timer.reset();

        // Do a search over entire column (value not found)
        for (size_t i = 0; i < 100; ++i) {
            const size_t res = table.column().third.find_first(50);
            if (res != size_t(-1)) {
                cout << "error\n";
            }
        }

        cout << "Search (byte-size integer): "<<timer<<"\n";
    }

    // Search string column
    {
        timer.reset();

        // Do a search over entire column (value not found)
        for (size_t i = 0; i < 100; ++i) {
            const size_t res = table.column().second.find_first("abcde");
            if (res != 250000) {
                cerr << "error\n";
            }
        }

        cout << "Search (string): "<<timer<<"\n";
    }

    // Add index
    {
        timer.reset();

        table.column().first.set_index();

        cout << "Add index: "<<timer<<"\n";
    }

    cout << "Memory usage2: "<<test_util::get_mem_usage()<<" bytes\n";

    // Search with index
    {
        timer.reset();

        for (size_t i = 0; i < 100000; ++i) {
            const size_t n = rand() % 1000;
            const size_t res = table.column().first.find_first(n);
            if (res == 2500002) { // to avoid above find being optimized away
                cout << "error\n";
            }
        }

        cout << "Search index: "<<timer<<"\n";
    }

#ifdef _MSC_VER
    cin.get();
#endif
}
<commit_msg>add_index() changed to add_search_index()<commit_after>#include <iostream>

#include <tightdb.hpp>

#include "../util/timer.hpp"
#include "../util/mem.hpp"
#include "../util/number_names.hpp"

using namespace std;
using namespace tightdb;

namespace {

// Get and Set are too fast (50ms/M) for normal 64-bit rand*rand*rand*rand*rand (5-10ms/M)
uint64_t rand2()
{
    static int64_t seed = 2862933555777941757ULL;
    static int64_t seed2 = 0;
    seed = (2862933555777941757ULL * seed + 3037000493ULL);
    seed2++;
    return seed * seed2 + seed2;
}

TIGHTDB_TABLE_1(IntegerTable,
                first, Int)

TIGHTDB_TABLE_1(StringTable,
                first, String)

enum Days {
    Mon,
    Tue,
    Wed,
    Thu,
    Fri,
    Sat,
    Sun
};

TIGHTDB_TABLE_4(TestTable,
                first,  Int,
                second, String,
                third,  Int,
                fourth, Enum<Days>)

} // anonymous namespace

int main()
{
    TestTable table;

    // Build large table
    for (size_t i = 0; i < 250000; ++i) {
        // create random string
        const size_t n = rand() % 1000;// * 10 + rand();
        const string s = test_util::number_name(n);

        table.add(n, s.c_str(), 100, Wed);
    }
    table.add(0, "abcde", 100, Wed);

    cout << "Memory usage: "<<test_util::get_mem_usage()<<" bytes\n";

    test_util::Timer timer;

    // Search small integer column
    {
        timer.reset();

        // Do a search over entire column (value not found)
        for (size_t i = 0; i < 100; ++i) {
            const size_t res = table.column().fourth.find_first(Tue);
            if (res != size_t(-1)) {
                cout << "error\n";
            }
        }

        cout << "Search (small integer): "<<timer<<"\n";
    }

    // Search byte-size integer column
    {
        timer.reset();

        // Do a search over entire column (value not found)
        for (size_t i = 0; i < 100; ++i) {
            const size_t res = table.column().third.find_first(50);
            if (res != size_t(-1)) {
                cout << "error\n";
            }
        }

        cout << "Search (byte-size integer): "<<timer<<"\n";
    }

    // Search string column
    {
        timer.reset();

        // Do a search over entire column (value not found)
        for (size_t i = 0; i < 100; ++i) {
            const size_t res = table.column().second.find_first("abcde");
            if (res != 250000) {
                cerr << "error\n";
            }
        }

        cout << "Search (string): "<<timer<<"\n";
    }

    // Add index
    {
        timer.reset();

        table.column().first.add_search_index();

        cout << "Add index: "<<timer<<"\n";
    }

    cout << "Memory usage2: "<<test_util::get_mem_usage()<<" bytes\n";

    // Search with index
    {
        timer.reset();

        for (size_t i = 0; i < 100000; ++i) {
            const size_t n = rand() % 1000;
            const size_t res = table.column().first.find_first(n);
            if (res == 2500002) { // to avoid above find being optimized away
                cout << "error\n";
            }
        }

        cout << "Search index: "<<timer<<"\n";
    }

#ifdef _MSC_VER
    cin.get();
#endif
}
<|endoftext|>