<commit_before>/*!
 * \file int_path.hpp
 * \brief file int_path.hpp
 *
 * Copyright 2017 by Intel.
 *
 * Contact: kevin.rogovin@intel.com
 *
 * This Source Code Form is subject to the
 * terms of the Mozilla Public License, v. 2.0.
 * If a copy of the MPL was not distributed with
 * this file, You can obtain one at
 * http://mozilla.org/MPL/2.0/.
 *
 * \author Kevin Rogovin <kevin.rogovin@intel.com>
 *
 */

#pragma once

#include <fastuidraw/util/util.hpp>
#include <fastuidraw/util/c_array.hpp>
#include <fastuidraw/util/vecN.hpp>
#include <fastuidraw/util/reference_counted.hpp>
#include <fastuidraw/util/fastuidraw_memory.hpp>
#include <fastuidraw/path.hpp>
#include <fastuidraw/text/glyph_render_data_curve_pair.hpp>
#include <fastuidraw/text/glyph_render_data_distance_field.hpp>

#include "array2d.hpp"
#include "bounding_box.hpp"
#include "util_private.hpp"

namespace fastuidraw
{
  namespace detail
  {
    class IntBezierCurve
    {
    public:

      template<typename T>
      class transformation
      {
      public:
        transformation(T sc = T(1), vecN<T, 2> tr = vecN<T, 2>(T(0))):
          m_scale(sc),
          m_translate(tr)
        {}

        T
        scale(void) const
        {
          return m_scale;
        }

        vecN<T, 2>
        translate(void) const
        {
          return m_translate;
        }

        template<typename U>
        transformation<U>
        cast(void) const
        {
          return transformation<U>(U(m_scale), vecN<U, 2>(m_translate));
        }

        vecN<T, 2>
        operator()(vecN<T, 2> p) const
        {
          return m_translate + m_scale * p;
        }

      private:
        T m_scale;
        vecN<T, 2> m_translate;
      };

      class ID_t
      {
      public:
        ID_t(void):
          m_contourID(-1),
          m_curveID(-1)
        {}

        unsigned int m_contourID;
        unsigned int m_curveID;
      };

      IntBezierCurve(const ID_t &pID, const IntBezierCurve &curve):
        m_ID(pID),
        m_control_pts(curve.m_control_pts),
        m_num_control_pts(curve.m_num_control_pts),
        m_as_polynomial_fcn(curve.m_as_polynomial_fcn),
        m_derivatives_cancel(curve.m_derivatives_cancel),
        m_bb(curve.m_bb)
      {
      }

      IntBezierCurve(const ID_t &pID, const ivec2 &pt0, const ivec2 &pt1):
        m_ID(pID),
        m_control_pts(pt0, pt1, ivec2(), ivec2()),
        m_num_control_pts(2)
      {
        process_control_pts();
      }

      IntBezierCurve(const ID_t &pID, const ivec2 &pt0, const ivec2 &ct,
                     const ivec2 &pt1):
        m_ID(pID),
        m_control_pts(pt0, ct, pt1, ivec2()),
        m_num_control_pts(3)
      {
        process_control_pts();
      }

      IntBezierCurve(const ID_t &pID, const ivec2 &pt0, const ivec2 &ct0,
                     const ivec2 &ct1, const ivec2 &pt1):
        m_ID(pID),
        m_control_pts(pt0, ct0, ct1, pt1),
        m_num_control_pts(4)
      {
        process_control_pts();
      }

      ~IntBezierCurve()
      {}

      const ID_t&
      ID(void) const
      {
        return m_ID;
      }

      const_c_array<ivec2>
      control_pts(void) const
      {
        return const_c_array<ivec2>(m_control_pts.c_ptr(), m_num_control_pts);
      }

      const BoundingBox<int>&
      bounding_box(void) const
      {
        return m_bb;
      }

      BoundingBox<int>
      bounding_box(const transformation<int> &tr) const
      {
        BoundingBox<int> R;
        R.union_point(tr(m_bb.min_point()));
        R.union_point(tr(m_bb.max_point()));
        return R;
      }

      static
      bool
      are_ordered_neighbors(const IntBezierCurve &curve0,
                            const IntBezierCurve &curve1)
      {
        return curve0.control_pts().back() == curve1.control_pts().front();
      }

      int
      degree(void) const
      {
        FASTUIDRAWassert(m_num_control_pts > 0);
        return m_num_control_pts - 1;
      }

      const_c_array<vec2>
      derivatives_cancel(void) const
      {
        return const_c_array<vec2>(m_derivatives_cancel.c_ptr(),
                                   m_num_derivatives_cancel);
      }

      const_c_array<int>
      as_polynomial(int coord) const
      {
        return const_c_array<int>(m_as_polynomial_fcn[coord].c_ptr(), m_num_control_pts);
      }

      vecN<const_c_array<int>, 2>
      as_polynomial(void) const
      {
        return vecN<const_c_array<int>, 2>(as_polynomial(0), as_polynomial(1));
      }

      vec2
      eval(float t) const;

    private:
      void
      process_control_pts(void);

      void
      compute_derivatives_cancel_pts(void);

      c_array<int>
      as_polynomial(int coord)
      {
        return c_array<int>(m_as_polynomial_fcn[coord].c_ptr(), m_num_control_pts);
      }

      ID_t m_ID;
      vecN<ivec2, 4> m_control_pts;
      unsigned int m_num_control_pts;
      vecN<ivec4, 2> m_as_polynomial_fcn;

      // where dx/dt +- dy/dt = 0
      vecN<vec2, 6> m_derivatives_cancel;
      unsigned int m_num_derivatives_cancel;
      BoundingBox<int> m_bb;
    };

    class IntContour
    {
    public:
      IntContour(void)
      {}

      void
      add_curve(const IntBezierCurve &curve)
      {
        FASTUIDRAWassert(m_curves.empty() || IntBezierCurve::are_ordered_neighbors(m_curves.back(), curve));
        m_curves.push_back(curve);
      }

      bool
      closed(void)
      {
        return !m_curves.empty()
          && IntBezierCurve::are_ordered_neighbors(m_curves.back(), m_curves.front());
      }

      const std::vector<IntBezierCurve>&
      curves(void) const
      {
        return m_curves;
      }

      const IntBezierCurve&
      curve(unsigned int curveID) const
      {
        FASTUIDRAWassert(curveID < m_curves.size());
        return m_curves[curveID];
      }

      /* Filter the Contour as follows:
          1. Collapse any curves that are within a texel
          2. Curves of tiny curvature are realized as a line
          3. Cubics are broken into quadratics
         The transformation tr is -NOT- applied to the contour,
         it is used as the transformation from IntContour
         coordinates to texel coordinates. The value of texel_size
         gives the size of a texel with the texel at (0, 0)
         starting at (0, 0) [in texel coordinates].
       */
      void
      filter(float curvature_collapse,
             const IntBezierCurve::transformation<int> &tr, ivec2 texel_size);

      void
      add_to_path(const IntBezierCurve::transformation<float> &tr, Path *dst) const;

    private:
      std::vector<IntBezierCurve> m_curves;
    };

    class IntPath
    {
    public:
      IntPath(void)
      {}

      void
      move_to(const ivec2 &pt);

      void
      line_to(const ivec2 &pt);

      void
      conic_to(const ivec2 &control_pt, const ivec2 &pt);

      void
      cubic_to(const ivec2 &control_pt0, const ivec2 &control_pt1, const ivec2 &pt);

      bool
      empty(void) const
      {
        return m_contours.empty();
      }

      /* Add this IntPath with a transforamtion tr applied to it to a
         pre-exising (and possibly empty) Path.
         \param tr transformation to apply to data of path
       */
      void
      add_to_path(const IntBezierCurve::transformation<float> &tr, Path *dst) const;

      /* Filter the Path as follows:
          1. Collapse any curves that are within a texel
          2. Curves of tiny curvature are realized as a line
          3. Cubics are broken into quadratics
         The transformation tr is -NOT- applied to the path,
         it is used as the transformation from IntContour
         coordinates to texel coordinates. The value of texel_size
         gives the size of a texel with the texel at (0, 0)
         starting at (0, 0) [in texel coordinates].
       */
      void
      filter(float curvature_collapse,
             const IntBezierCurve::transformation<int> &tr,
             ivec2 texel_size);

      /* Compute distance field data, where distance values are
         sampled at the center of each texel; the caller needs to
         make sure that the path with the transformation tr applied
         is entirely within the region [0, W] x [0, H] where
         (W, H) = texel_size * image_sz.
         \param texel_size the size of each texel in coordinates
                           AFTER tr is applied
         \param image_sz size of the distance field to make
         \param tr transformation to apply to data of path
       */
      void
      extract_render_data(const ivec2 &texel_size, const ivec2 &image_sz,
                          float max_distance,
                          IntBezierCurve::transformation<int> tr,
                          GlyphRenderDataDistanceField *dst) const;

      /* Compute curve-pair render data. The caller should have applied
         filter() before calling to reduce cubics and collapse tiny
         curves; also, the caller needs to make sure that the path
         with the transformation tr applied is entirely within the
         region [0, W] x [0, H] where (W, H) = texel_size * image_sz.
         \param texel_size the size of each texel in coordinates
                           AFTER tr is applied
         \param image_sz size of the distance field to make
         \param tr transformation to apply to data of path
       */
      void
      extract_render_data(const ivec2 &texel_size, const ivec2 &image_sz,
                          IntBezierCurve::transformation<int> tr,
                          GlyphRenderDataCurvePair *dst) const;

    private:
      IntBezierCurve::ID_t
      computeID(void);

      fastuidraw::ivec2 m_last_pt;
      std::vector<IntContour> m_contours;
    };

  } //namespace fastuidraw
} //namespace detail
<commit_msg>fastuidraw/private/int_path: add comparison operator to IntBezierCurve::ID_t<commit_after>/*!
 * \file int_path.hpp
 * \brief file int_path.hpp
 *
 * Copyright 2017 by Intel.
 *
 * Contact: kevin.rogovin@intel.com
 *
 * This Source Code Form is subject to the
 * terms of the Mozilla Public License, v. 2.0.
 * If a copy of the MPL was not distributed with
 * this file, You can obtain one at
 * http://mozilla.org/MPL/2.0/.
 *
 * \author Kevin Rogovin <kevin.rogovin@intel.com>
 *
 */

#pragma once

#include <vector>

#include <fastuidraw/util/util.hpp>
#include <fastuidraw/util/c_array.hpp>
#include <fastuidraw/util/vecN.hpp>
#include <fastuidraw/util/reference_counted.hpp>
#include <fastuidraw/util/fastuidraw_memory.hpp>
#include <fastuidraw/path.hpp>
#include <fastuidraw/text/glyph_render_data_curve_pair.hpp>
#include <fastuidraw/text/glyph_render_data_distance_field.hpp>

#include "array2d.hpp"
#include "bounding_box.hpp"
#include "util_private.hpp"

namespace fastuidraw
{
  namespace detail
  {
    class IntBezierCurve
    {
    public:

      template<typename T>
      class transformation
      {
      public:
        transformation(T sc = T(1), vecN<T, 2> tr = vecN<T, 2>(T(0))):
          m_scale(sc),
          m_translate(tr)
        {}

        T
        scale(void) const
        {
          return m_scale;
        }

        vecN<T, 2>
        translate(void) const
        {
          return m_translate;
        }

        template<typename U>
        transformation<U>
        cast(void) const
        {
          return transformation<U>(U(m_scale), vecN<U, 2>(m_translate));
        }

        vecN<T, 2>
        operator()(vecN<T, 2> p) const
        {
          return m_translate + m_scale * p;
        }

      private:
        T m_scale;
        vecN<T, 2> m_translate;
      };

      class ID_t
      {
      public:
        ID_t(void):
          m_contourID(-1),
          m_curveID(-1)
        {}

        bool
        operator<(const ID_t &rhs) const
        {
          return m_contourID == rhs.m_contourID
            || (m_contourID == rhs.m_contourID
                && m_curveID << rhs.m_curveID);
        }

        unsigned int m_contourID;
        unsigned int m_curveID;
      };

      IntBezierCurve(const ID_t &pID, const IntBezierCurve &curve):
        m_ID(pID),
        m_control_pts(curve.m_control_pts),
        m_num_control_pts(curve.m_num_control_pts),
        m_as_polynomial_fcn(curve.m_as_polynomial_fcn),
        m_derivatives_cancel(curve.m_derivatives_cancel),
        m_bb(curve.m_bb)
      {
      }

      IntBezierCurve(const ID_t &pID, const ivec2 &pt0, const ivec2 &pt1):
        m_ID(pID),
        m_control_pts(pt0, pt1, ivec2(), ivec2()),
        m_num_control_pts(2)
      {
        process_control_pts();
      }

      IntBezierCurve(const ID_t &pID, const ivec2 &pt0, const ivec2 &ct,
                     const ivec2 &pt1):
        m_ID(pID),
        m_control_pts(pt0, ct, pt1, ivec2()),
        m_num_control_pts(3)
      {
        process_control_pts();
      }

      IntBezierCurve(const ID_t &pID, const ivec2 &pt0, const ivec2 &ct0,
                     const ivec2 &ct1, const ivec2 &pt1):
        m_ID(pID),
        m_control_pts(pt0, ct0, ct1, pt1),
        m_num_control_pts(4)
      {
        process_control_pts();
      }

      ~IntBezierCurve()
      {}

      const ID_t&
      ID(void) const
      {
        return m_ID;
      }

      const_c_array<ivec2>
      control_pts(void) const
      {
        return const_c_array<ivec2>(m_control_pts.c_ptr(), m_num_control_pts);
      }

      const BoundingBox<int>&
      bounding_box(void) const
      {
        return m_bb;
      }

      BoundingBox<int>
      bounding_box(const transformation<int> &tr) const
      {
        BoundingBox<int> R;
        R.union_point(tr(m_bb.min_point()));
        R.union_point(tr(m_bb.max_point()));
        return R;
      }

      static
      bool
      are_ordered_neighbors(const IntBezierCurve &curve0,
                            const IntBezierCurve &curve1)
      {
        return curve0.control_pts().back() == curve1.control_pts().front();
      }

      int
      degree(void) const
      {
        FASTUIDRAWassert(m_num_control_pts > 0);
        return m_num_control_pts - 1;
      }

      const_c_array<vec2>
      derivatives_cancel(void) const
      {
        return const_c_array<vec2>(m_derivatives_cancel.c_ptr(),
                                   m_num_derivatives_cancel);
      }

      const_c_array<int>
      as_polynomial(int coord) const
      {
        return const_c_array<int>(m_as_polynomial_fcn[coord].c_ptr(), m_num_control_pts);
      }

      vecN<const_c_array<int>, 2>
      as_polynomial(void) const
      {
        return vecN<const_c_array<int>, 2>(as_polynomial(0), as_polynomial(1));
      }

      vec2
      eval(float t) const;

    private:
      void
      process_control_pts(void);

      void
      compute_derivatives_cancel_pts(void);

      c_array<int>
      as_polynomial(int coord)
      {
        return c_array<int>(m_as_polynomial_fcn[coord].c_ptr(), m_num_control_pts);
      }

      ID_t m_ID;
      vecN<ivec2, 4> m_control_pts;
      unsigned int m_num_control_pts;
      vecN<ivec4, 2> m_as_polynomial_fcn;

      // where dx/dt +- dy/dt = 0
      vecN<vec2, 6> m_derivatives_cancel;
      unsigned int m_num_derivatives_cancel;
      BoundingBox<int> m_bb;
    };

    class IntContour
    {
    public:
      IntContour(void)
      {}

      void
      add_curve(const IntBezierCurve &curve)
      {
        FASTUIDRAWassert(m_curves.empty() || IntBezierCurve::are_ordered_neighbors(m_curves.back(), curve));
        m_curves.push_back(curve);
      }

      bool
      closed(void)
      {
        return !m_curves.empty()
          && IntBezierCurve::are_ordered_neighbors(m_curves.back(), m_curves.front());
      }

      const std::vector<IntBezierCurve>&
      curves(void) const
      {
        return m_curves;
      }

      const IntBezierCurve&
      curve(unsigned int curveID) const
      {
        FASTUIDRAWassert(curveID < m_curves.size());
        return m_curves[curveID];
      }

      /* Filter the Contour as follows:
          1. Collapse any curves that are within a texel
          2. Curves of tiny curvature are realized as a line
          3. Cubics are broken into quadratics
         The transformation tr is -NOT- applied to the contour,
         it is used as the transformation from IntContour
         coordinates to texel coordinates. The value of texel_size
         gives the size of a texel with the texel at (0, 0)
         starting at (0, 0) [in texel coordinates].
       */
      void
      filter(float curvature_collapse,
             const IntBezierCurve::transformation<int> &tr, ivec2 texel_size);

      void
      add_to_path(const IntBezierCurve::transformation<float> &tr, Path *dst) const;

    private:
      std::vector<IntBezierCurve> m_curves;
    };

    class IntPath
    {
    public:
      IntPath(void)
      {}

      void
      move_to(const ivec2 &pt);

      void
      line_to(const ivec2 &pt);

      void
      conic_to(const ivec2 &control_pt, const ivec2 &pt);

      void
      cubic_to(const ivec2 &control_pt0, const ivec2 &control_pt1, const ivec2 &pt);

      bool
      empty(void) const
      {
        return m_contours.empty();
      }

      /* Add this IntPath with a transforamtion tr applied to it to a
         pre-exising (and possibly empty) Path.
         \param tr transformation to apply to data of path
       */
      void
      add_to_path(const IntBezierCurve::transformation<float> &tr, Path *dst) const;

      /* Filter the Path as follows:
          1. Collapse any curves that are within a texel
          2. Curves of tiny curvature are realized as a line
          3. Cubics are broken into quadratics
         The transformation tr is -NOT- applied to the path,
         it is used as the transformation from IntContour
         coordinates to texel coordinates. The value of texel_size
         gives the size of a texel with the texel at (0, 0)
         starting at (0, 0) [in texel coordinates].
       */
      void
      filter(float curvature_collapse,
             const IntBezierCurve::transformation<int> &tr,
             ivec2 texel_size);

      /* Compute distance field data, where distance values are
         sampled at the center of each texel; the caller needs to
         make sure that the path with the transformation tr applied
         is entirely within the region [0, W] x [0, H] where
         (W, H) = texel_size * image_sz.
         \param texel_size the size of each texel in coordinates
                           AFTER tr is applied
         \param image_sz size of the distance field to make
         \param tr transformation to apply to data of path
       */
      void
      extract_render_data(const ivec2 &texel_size, const ivec2 &image_sz,
                          float max_distance,
                          IntBezierCurve::transformation<int> tr,
                          GlyphRenderDataDistanceField *dst) const;

      /* Compute curve-pair render data. The caller should have applied
         filter() before calling to reduce cubics and collapse tiny
         curves; also, the caller needs to make sure that the path
         with the transformation tr applied is entirely within the
         region [0, W] x [0, H] where (W, H) = texel_size * image_sz.
         \param texel_size the size of each texel in coordinates
                           AFTER tr is applied
         \param image_sz size of the distance field to make
         \param tr transformation to apply to data of path
       */
      void
      extract_render_data(const ivec2 &texel_size, const ivec2 &image_sz,
                          IntBezierCurve::transformation<int> tr,
                          GlyphRenderDataCurvePair *dst) const;

    private:
      IntBezierCurve::ID_t
      computeID(void);

      fastuidraw::ivec2 m_last_pt;
      std::vector<IntContour> m_contours;
    };

  } //namespace fastuidraw
} //namespace detail
<|endoftext|>


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

#include "../testhelpers.h"
#include "../tracker_direct_common.h"

#include <QtTest/QtTest>
#include <QtSparql/QtSparql>

class tst_QSparqlTrackerDirectConcurrency : public QObject
{
    Q_OBJECT
public:
    tst_QSparqlTrackerDirectConcurrency();
    virtual ~tst_QSparqlTrackerDirectConcurrency();

private:

private slots:
    void initTestCase();
    void cleanupTestCase();
    void init();
    void cleanup();

    void sameConnection_selectQueries();
    void sameConnection_selectQueries_data();
    //void sameConnection_updateQueries();
    void sameConnection_multipleThreads_selectQueries();
    void sameConnection_multipleThreads_selectQueries_data();
    //void sameConnection_multipleThreads_updateQueries();

    // multpleConnections tests will all be multi threaded
    //void multipleConnections_selectQueries();
    //void multipleConnections_updateQueries();

private:
    QSharedPointer<QSignalSpy> dataReadySpy;
};

namespace {

class SignalObject : public QObject
{
    Q_OBJECT
public:
    SignalObject() : position(0) {}
    ~SignalObject()
    {
        // delete the signal mappers that were created
        foreach(QSignalMapper* map, signalMaps) {
           delete map;
        }
    }

    QSet<QSparqlResult*> pendingResults;
    int position;
    QList<QSignalMapper* > signalMaps;
    QList<QPair<int, int> > resultRanges;

    void append(QSparqlResult *r, QPair<int, int> range)
    {
        QSignalMapper *dataReadyMapper = new QSignalMapper();
        QSignalMapper *finishedMapper = new QSignalMapper();
        dataReadyMapper->setMapping(r, position);
        finishedMapper->setMapping(r, position);
        position++;

        connect(r, SIGNAL(dataReady(int)), dataReadyMapper, SLOT(map()));
        connect(dataReadyMapper, SIGNAL(mapped(int)), this, SLOT(onDataReady(int)));
        connect(r, SIGNAL(finished()), finishedMapper, SLOT(map()));
        connect(finishedMapper, SIGNAL(mapped(int)), this, SLOT(onFinished(int)));

        resultList.append(r);
        resultRanges.append(range);
        pendingResults.insert(r);

        // keep track of the signal mappers to delete later
        signalMaps.append(dataReadyMapper);
        signalMaps.append(finishedMapper);
    }
    QList<QSparqlResult*> resultList;

    bool waitForAllFinished(int silenceTimeoutMs)
    {
        QTime timeoutTimer;
        timeoutTimer.start();
        bool timeout = false;
        while (!pendingResults.empty() && !timeout) {
            const int pendingResultsCountBefore = pendingResults.count();
            QTest::qWait(silenceTimeoutMs / 10);
            if (pendingResults.count() < pendingResultsCountBefore) {
                timeoutTimer.restart();
            }
            else if (timeoutTimer.elapsed() > silenceTimeoutMs) {
                timeout = true;
            }
        }
        return !timeout;
    }

public Q_SLOTS:
    void onDataReady(int listPos)
    {
        QSparqlResult *result = resultList.at(listPos);
        while (result->next()) {
            // just do something pointless with the result
            result->value(1).toInt();
            result->value(0).toString();
        }
    }

    void onFinished(int listPos)
    {
        QPair<int, int> resultRange = resultRanges.at(listPos);
        QSparqlResult* result = resultList.at(listPos);
        int expectedResultSize = (resultRange.second - resultRange.first) + 1;
        QCOMPARE(expectedResultSize, result->size());
        // the results should have been fully nexted in the data ready function
        QCOMPARE(result->pos(), (int)QSparql::AfterLastRow);
        // go back through the results and validate that they are in range
        int resultCount = 0;
        while (result->previous()) {
            //we don't know the order, so just ensure the result is within range
            QVERIFY(result->value(1).toInt() <= resultRange.second && result->value(1).toInt() >= resultRange.first);
            resultCount++;
        }
        // now make sure the results counted match the size
        QCOMPARE(resultCount, expectedResultSize);
        pendingResults.remove(result);
    }

};

class ThreadObject : public QObject
{
    Q_OBJECT
public:
    QSparqlConnection *connection;
    SignalObject *signalObject;
    QList<QSparqlResult*> resultList;
    bool deleteConnection;
    bool deleteSignalObject;

    int numQueries;
    int testDataSize;

    ThreadObject()
    : connection(0), signalObject(0), deleteConnection(false), deleteSignalObject(false)
    {
    }

    ~ThreadObject()
    {
    }

    void cleanup()
    {
        if (deleteConnection) {
            delete connection;
        } else {
            // if we were passed a connection, delete the results
            // here to avoid leaking them
            foreach(QSparqlResult* result, resultList)
                delete result;
        }

        if (deleteSignalObject)
            delete signalObject;
    }
    void setParameters(int numQueries, int testDataSize)
    {
        this->numQueries = numQueries;
        this->testDataSize = testDataSize;
    }
    void setConnection(QSparqlConnection* connection)
    {
        this->connection = connection;
    }

    void setSignalObject(SignalObject* signalObject)
    {
        this->signalObject = signalObject;

    }

    void waitForFinished()
    {
        signalObject->waitForAllFinished(8000);
    }

public Q_SLOTS:
    void startQueries()
    {
        if (!connection) {
            this->connection = new QSparqlConnection("QTRACKER_DIRECT");
            deleteConnection = true;
        }
        if (!signalObject) {
            this->signalObject = new SignalObject();
            deleteSignalObject = true;
        }

        QTime time = QTime::currentTime();
        qsrand((uint)time.msec());
        // store the result ranges we are going to use
        QList<QPair<int, int> > resultRanges;
        // first result will read everything
        resultRanges.append(qMakePair(1, testDataSize));
        for (int i=1;i<numQueries;i++) {
            // high + 1) - low) + low
            int low = qrand() % ((testDataSize) - 1) + 1;
            int high = qrand() % ((testDataSize+1) - low) + low;
            resultRanges.append(qMakePair(low, high));
        }

        for (int i=0;i<numQueries;i++) {
            QPair<int, int> resultRange = resultRanges.at(i);
            QSparqlQuery select(QString("select ?u ?t {?u a nmm:MusicPiece;"
                                    "nmm:trackNumber ?t;"
                                    "nie:isLogicalPartOf <qsparql-tracker-direct-tests-concurrency-stress>"
                                    "FILTER ( ?t >=%1 && ?t <=%2 ) }").arg(resultRange.first).arg(resultRange.second));
            QSparqlResult *result = connection->exec(select);
            resultList.append(result);
            signalObject->append(result, resultRange);
        }

        waitForFinished();
        cleanup();
        this->thread()->quit();
    }

};

} //end namespace

tst_QSparqlTrackerDirectConcurrency::tst_QSparqlTrackerDirectConcurrency()
{
}

tst_QSparqlTrackerDirectConcurrency::~tst_QSparqlTrackerDirectConcurrency()
{
}

void tst_QSparqlTrackerDirectConcurrency::initTestCase()
{
    // For running the test without installing the plugins. Should work in
    // normal and vpath builds.
    QCoreApplication::addLibraryPath("../../../plugins");
}

void tst_QSparqlTrackerDirectConcurrency::cleanupTestCase()
{
}

void tst_QSparqlTrackerDirectConcurrency::init()
{
}

void tst_QSparqlTrackerDirectConcurrency::cleanup()
{
}

void tst_QSparqlTrackerDirectConcurrency::sameConnection_selectQueries()
{
    QFETCH(int, testDataAmount);
    QFETCH(int, numQueries);
    QFETCH(int, maxThreadCount);

    QSparqlConnectionOptions options;
    options.setDataReadyInterval(500);
    options.setMaxThreadCount(maxThreadCount);
    const QString testTag("<qsparql-tracker-direct-tests-concurrency-stress>");
    QScopedPointer<TestData> testData(createTestData(testDataAmount, "<qsparql-tracker-direct-tests>", testTag));
    QTest::qWait(2000);
    QVERIFY( testData->isOK() );

    // seed the random number generator
    QTime time = QTime::currentTime();
    qsrand((uint)time.msec());
    // store the result ranges we are going to use
    QList<QPair<int, int> > resultRanges;
    // first result will read everything
    resultRanges.append(qMakePair(1, 3000));
    for (int i=1;i<numQueries;i++) {
        // high + 1) - low) + low
        int low = qrand() % ((testDataAmount) - 1) + 1;
        int high = qrand() % ((testDataAmount+1) - low) + low;
        resultRanges.append(qMakePair(low, high));
    }

    QSparqlConnection conn("QTRACKER_DIRECT", options);
    SignalObject signalObject;

    for (int i=0;i<numQueries;i++) {
        QPair<int, int> resultRange = resultRanges.at(i);
        QSparqlQuery select(QString("select ?u ?t {?u a nmm:MusicPiece;"
                                    "nmm:trackNumber ?t;"
                                    "nie:isLogicalPartOf <qsparql-tracker-direct-tests-concurrency-stress>"
                                    "FILTER ( ?t >=%1 && ?t <=%2 ) }").arg(resultRange.first).arg(resultRange.second));
        QSparqlResult *result = conn.exec(select);
        signalObject.append(result, resultRange);
    }

    QVERIFY(signalObject.waitForAllFinished(8000));
}

void tst_QSparqlTrackerDirectConcurrency::sameConnection_selectQueries_data()
{
    QTest::addColumn<int>("testDataAmount");
    QTest::addColumn<int>("numQueries");
    QTest::addColumn<int>("maxThreadCount");

    QTest::newRow("3000 items, 10 queries, 4 Threads") <<
        3000 << 10 << 4;
    QTest::newRow("3000 items, 100 queries, 4 Threads") <<
        3000 << 100 << 4;
    QTest::newRow("3000 items, 10 queries, 1 Thread") <<
        3000 << 10 << 1;
    QTest::newRow("3000 items, 100 queries, 1 Thread") <<
        3000 << 100 << 1;
}

void tst_QSparqlTrackerDirectConcurrency::sameConnection_multipleThreads_selectQueries()
{
    QFETCH(int, testDataAmount);
    QFETCH(int, numQueries);
    QFETCH(int, numThreads);

    QSparqlConnection connection("QTRACKER_DIRECT");
    const QString testTag("<qsparql-tracker-direct-tests-concurrency-stress>");
    QScopedPointer<TestData> testData(createTestData(testDataAmount, "<qsparql-tracker-direct-tests>", testTag));
    QTest::qWait(2000);
    QVERIFY( testData->isOK() );

    QList<QThread*> createdThreads;
    QList<ThreadObject*> threadObjects;
    for (int i=0;i<numThreads;i++) {
        QThread *newThread = new QThread();
        createdThreads.append(newThread);

        ThreadObject *threadObject = new ThreadObject();
        threadObjects.append(threadObject);

        threadObject->setConnection(&connection);
        threadObject->setParameters(numQueries, testDataAmount);
        threadObject->moveToThread(newThread);

        // connec the threads started signal to the slot that does the work
        QObject::connect(newThread, SIGNAL(started()), threadObject, SLOT(startQueries()));
    }
    // start all the threads
    foreach(QThread* thread, createdThreads) {
        thread->start();
    }
    // wait for all the threads then delete
    // TODO: add timer so we don't wait forever
    foreach(QThread* thread, createdThreads) {
        while (!thread->isFinished())
            QTest::qWait(500);
        delete thread;
    }

    //cleanup
    foreach(ThreadObject *threadObject, threadObjects)
        delete threadObject;
}

void tst_QSparqlTrackerDirectConcurrency::sameConnection_multipleThreads_selectQueries_data()
{
    QTest::addColumn<int>("testDataAmount");
    QTest::addColumn<int>("numQueries");
    QTest::addColumn<int>("numThreads");

    QTest::newRow("3000 items, 10 queries, 2 Threads") <<
        3000 << 10 << 2;
    QTest::newRow("3000 items, 100 queries, 2 Threads") <<
        3000 << 100 << 2;
    QTest::newRow("3000 items, 10 queries, 10 Threads") <<
        3000 << 10 << 10;
    QTest::newRow("3000 items, 100 queries, 10 Threads") <<
        3000 << 100 << 10;
}

QTEST_MAIN( tst_QSparqlTrackerDirectConcurrency )
#include "tst_qsparql_tracker_direct_concurrency.moc"
<commit_msg>Add a test for multiple connections/threads with select queries<commit_after>/****************************************************************************
**
** Copyright (C) 2010-2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (ivan.frade@nokia.com)
**
** This file is part of the test suite of the QtSparql module (not yet part of the Qt Toolkit).
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
** If you have questions regarding the use of this file, please contact
** Nokia at ivan.frade@nokia.com.
** $QT_END_LICENSE$
**
****************************************************************************/

#include "../testhelpers.h"
#include "../tracker_direct_common.h"

#include <QtTest/QtTest>
#include <QtSparql/QtSparql>

class tst_QSparqlTrackerDirectConcurrency : public QObject
{
    Q_OBJECT
public:
    tst_QSparqlTrackerDirectConcurrency();
    virtual ~tst_QSparqlTrackerDirectConcurrency();

private:

private slots:
    void initTestCase();
    void cleanupTestCase();
    void init();
    void cleanup();

    void sameConnection_selectQueries();
    void sameConnection_selectQueries_data();
    //void sameConnection_updateQueries();
    void sameConnection_multipleThreads_selectQueries();
    void sameConnection_multipleThreads_selectQueries_data();
    //void sameConnection_multipleThreads_updateQueries();

    // multpleConnections tests will all be multi threaded
    void multipleConnections_selectQueries();
    void multipleConnections_selectQueries_data();
    //void multipleConnections_updateQueries();

private:
    QSharedPointer<QSignalSpy> dataReadySpy;
};

namespace {

class SignalObject : public QObject
{
    Q_OBJECT
public:
    SignalObject() : position(0) {}
    ~SignalObject()
    {
        // delete the signal mappers that were created
        foreach(QSignalMapper* map, signalMaps) {
           delete map;
        }
    }

    QSet<QSparqlResult*> pendingResults;
    int position;
    QList<QSignalMapper* > signalMaps;
    QList<QPair<int, int> > resultRanges;

    void append(QSparqlResult *r, QPair<int, int> range)
    {
        QSignalMapper *dataReadyMapper = new QSignalMapper();
        QSignalMapper *finishedMapper = new QSignalMapper();
        dataReadyMapper->setMapping(r, position);
        finishedMapper->setMapping(r, position);
        position++;

        connect(r, SIGNAL(dataReady(int)), dataReadyMapper, SLOT(map()));
        connect(dataReadyMapper, SIGNAL(mapped(int)), this, SLOT(onDataReady(int)));
        connect(r, SIGNAL(finished()), finishedMapper, SLOT(map()));
        connect(finishedMapper, SIGNAL(mapped(int)), this, SLOT(onFinished(int)));

        resultList.append(r);
        resultRanges.append(range);
        pendingResults.insert(r);

        // keep track of the signal mappers to delete later
        signalMaps.append(dataReadyMapper);
        signalMaps.append(finishedMapper);
    }
    QList<QSparqlResult*> resultList;

    bool waitForAllFinished(int silenceTimeoutMs)
    {
        QTime timeoutTimer;
        timeoutTimer.start();
        bool timeout = false;
        while (!pendingResults.empty() && !timeout) {
            const int pendingResultsCountBefore = pendingResults.count();
            QTest::qWait(silenceTimeoutMs / 10);
            if (pendingResults.count() < pendingResultsCountBefore) {
                timeoutTimer.restart();
            }
            else if (timeoutTimer.elapsed() > silenceTimeoutMs) {
                timeout = true;
            }
        }
        return !timeout;
    }

public Q_SLOTS:
    void onDataReady(int listPos)
    {
        QSparqlResult *result = resultList.at(listPos);
        while (result->next()) {
            // just do something pointless with the result
            result->value(1).toInt();
            result->value(0).toString();
        }
    }

    void onFinished(int listPos)
    {
        QPair<int, int> resultRange = resultRanges.at(listPos);
        QSparqlResult* result = resultList.at(listPos);
        int expectedResultSize = (resultRange.second - resultRange.first) + 1;
        QCOMPARE(expectedResultSize, result->size());
        // the results should have been fully nexted in the data ready function
        QCOMPARE(result->pos(), (int)QSparql::AfterLastRow);
        // go back through the results and validate that they are in range
        int resultCount = 0;
        while (result->previous()) {
            //we don't know the order, so just ensure the result is within range
            QVERIFY(result->value(1).toInt() <= resultRange.second && result->value(1).toInt() >= resultRange.first);
            resultCount++;
        }
        // now make sure the results counted match the size
        QCOMPARE(resultCount, expectedResultSize);
        pendingResults.remove(result);
    }

};

class ThreadObject : public QObject
{
    Q_OBJECT
public:
    QSparqlConnection *connection;
    SignalObject *signalObject;
    QList<QSparqlResult*> resultList;
    bool deleteConnection;
    bool deleteSignalObject;

    int numQueries;
    int testDataSize;

    ThreadObject()
    : connection(0), signalObject(0), deleteConnection(false), deleteSignalObject(false)
    {
    }

    ~ThreadObject()
    {
    }

    void cleanup()
    {
        if (deleteConnection) {
            delete connection;
        } else {
            // if we were passed a connection, delete the results
            // here to avoid leaking them
            foreach(QSparqlResult* result, resultList)
                delete result;
        }

        if (deleteSignalObject)
            delete signalObject;
    }
    void setParameters(int numQueries, int testDataSize)
    {
        this->numQueries = numQueries;
        this->testDataSize = testDataSize;
    }
    void setConnection(QSparqlConnection* connection)
    {
        this->connection = connection;
    }

    void setSignalObject(SignalObject* signalObject)
    {
        this->signalObject = signalObject;

    }

    void waitForFinished()
    {
        signalObject->waitForAllFinished(8000);
    }

public Q_SLOTS:
    void startQueries()
    {
        if (!connection) {
            this->connection = new QSparqlConnection("QTRACKER_DIRECT");
            deleteConnection = true;
        }
        if (!signalObject) {
            this->signalObject = new SignalObject();
            deleteSignalObject = true;
        }

        QTime time = QTime::currentTime();
        qsrand((uint)time.msec());
        // store the result ranges we are going to use
        QList<QPair<int, int> > resultRanges;
        // first result will read everything
        resultRanges.append(qMakePair(1, testDataSize));
        for (int i=1;i<numQueries;i++) {
            // high + 1) - low) + low
            int low = qrand() % ((testDataSize) - 1) + 1;
            int high = qrand() % ((testDataSize+1) - low) + low;
            resultRanges.append(qMakePair(low, high));
        }

        for (int i=0;i<numQueries;i++) {
            QPair<int, int> resultRange = resultRanges.at(i);
            QSparqlQuery select(QString("select ?u ?t {?u a nmm:MusicPiece;"
                                    "nmm:trackNumber ?t;"
                                    "nie:isLogicalPartOf <qsparql-tracker-direct-tests-concurrency-stress>"
                                    "FILTER ( ?t >=%1 && ?t <=%2 ) }").arg(resultRange.first).arg(resultRange.second));
            QSparqlResult *result = connection->exec(select);
            resultList.append(result);
            signalObject->append(result, resultRange);
        }

        waitForFinished();
        cleanup();
        this->thread()->quit();
    }

};

} //end namespace

tst_QSparqlTrackerDirectConcurrency::tst_QSparqlTrackerDirectConcurrency()
{
}

tst_QSparqlTrackerDirectConcurrency::~tst_QSparqlTrackerDirectConcurrency()
{
}

void tst_QSparqlTrackerDirectConcurrency::initTestCase()
{
    // For running the test without installing the plugins. Should work in
    // normal and vpath builds.
    QCoreApplication::addLibraryPath("../../../plugins");
}

void tst_QSparqlTrackerDirectConcurrency::cleanupTestCase()
{
}

void tst_QSparqlTrackerDirectConcurrency::init()
{
}

void tst_QSparqlTrackerDirectConcurrency::cleanup()
{
}

void tst_QSparqlTrackerDirectConcurrency::sameConnection_selectQueries()
{
    QFETCH(int, testDataAmount);
    QFETCH(int, numQueries);
    QFETCH(int, maxThreadCount);

    QSparqlConnectionOptions options;
    options.setDataReadyInterval(500);
    options.setMaxThreadCount(maxThreadCount);
    const QString testTag("<qsparql-tracker-direct-tests-concurrency-stress>");
    QScopedPointer<TestData> testData(createTestData(testDataAmount, "<qsparql-tracker-direct-tests>", testTag));
    QTest::qWait(2000);
    QVERIFY( testData->isOK() );

    // seed the random number generator
    QTime time = QTime::currentTime();
    qsrand((uint)time.msec());
    // store the result ranges we are going to use
    QList<QPair<int, int> > resultRanges;
    // first result will read everything
    resultRanges.append(qMakePair(1, 3000));
    for (int i=1;i<numQueries;i++) {
        // high + 1) - low) + low
        int low = qrand() % ((testDataAmount) - 1) + 1;
        int high = qrand() % ((testDataAmount+1) - low) + low;
        resultRanges.append(qMakePair(low, high));
    }

    QSparqlConnection conn("QTRACKER_DIRECT", options);
    SignalObject signalObject;

    for (int i=0;i<numQueries;i++) {
        QPair<int, int> resultRange = resultRanges.at(i);
        QSparqlQuery select(QString("select ?u ?t {?u a nmm:MusicPiece;"
                                    "nmm:trackNumber ?t;"
                                    "nie:isLogicalPartOf <qsparql-tracker-direct-tests-concurrency-stress>"
                                    "FILTER ( ?t >=%1 && ?t <=%2 ) }").arg(resultRange.first).arg(resultRange.second));
        QSparqlResult *result = conn.exec(select);
        signalObject.append(result, resultRange);
    }

    QVERIFY(signalObject.waitForAllFinished(8000));
}

void tst_QSparqlTrackerDirectConcurrency::sameConnection_selectQueries_data()
{
    QTest::addColumn<int>("testDataAmount");
    QTest::addColumn<int>("numQueries");
    QTest::addColumn<int>("maxThreadCount");

    QTest::newRow("3000 items, 10 queries, 4 Threads") <<
        3000 << 10 << 4;
    QTest::newRow("3000 items, 100 queries, 4 Threads") <<
        3000 << 100 << 4;
    QTest::newRow("3000 items, 10 queries, 1 Thread") <<
        3000 << 10 << 1;
    QTest::newRow("3000 items, 100 queries, 1 Thread") <<
        3000 << 100 << 1;
}

void tst_QSparqlTrackerDirectConcurrency::sameConnection_multipleThreads_selectQueries()
{
    QFETCH(int, testDataAmount);
    QFETCH(int, numQueries);
    QFETCH(int, numThreads);

    QSparqlConnection connection("QTRACKER_DIRECT");
    const QString testTag("<qsparql-tracker-direct-tests-concurrency-stress>");
    QScopedPointer<TestData> testData(createTestData(testDataAmount, "<qsparql-tracker-direct-tests>", testTag));
    QTest::qWait(2000);
    QVERIFY( testData->isOK() );

    QList<QThread*> createdThreads;
    QList<ThreadObject*> threadObjects;
    for (int i=0;i<numThreads;i++) {
        QThread *newThread = new QThread();
        createdThreads.append(newThread);

        ThreadObject *threadObject = new ThreadObject();
        threadObjects.append(threadObject);

        threadObject->setConnection(&connection);
        threadObject->setParameters(numQueries, testDataAmount);
        threadObject->moveToThread(newThread);

        // connec the threads started signal to the slot that does the work
        QObject::connect(newThread, SIGNAL(started()), threadObject, SLOT(startQueries()));
    }
    // start all the threads
    foreach(QThread* thread, createdThreads) {
        thread->start();
    }
    // wait for all the threads then delete
    // TODO: add timer so we don't wait forever
    foreach(QThread* thread, createdThreads) {
        while (!thread->isFinished())
            QTest::qWait(500);
        delete thread;
    }

    //cleanup
    foreach(ThreadObject *threadObject, threadObjects)
        delete threadObject;
}

void tst_QSparqlTrackerDirectConcurrency::sameConnection_multipleThreads_selectQueries_data()
{
    QTest::addColumn<int>("testDataAmount");
    QTest::addColumn<int>("numQueries");
    QTest::addColumn<int>("numThreads");

    QTest::newRow("3000 items, 10 queries, 2 Threads") <<
        3000 << 10 << 2;
    QTest::newRow("3000 items, 100 queries, 2 Threads") <<
        3000 << 100 << 2;
    QTest::newRow("3000 items, 10 queries, 10 Threads") <<
        3000 << 10 << 10;
    QTest::newRow("3000 items, 100 queries, 10 Threads") <<
        3000 << 100 << 10;
}

void tst_QSparqlTrackerDirectConcurrency::multipleConnections_selectQueries()
{
    QFETCH(int, testDataAmount);
    QFETCH(int, numQueries);
    QFETCH(int, numThreads);

    QSparqlConnection connection("QTRACKER_DIRECT");
    const QString testTag("<qsparql-tracker-direct-tests-concurrency-stress>");
    QScopedPointer<TestData> testData(createTestData(testDataAmount, "<qsparql-tracker-direct-tests>", testTag));
    QTest::qWait(2000);
    QVERIFY( testData->isOK() );

    QList<QThread*> createdThreads;
    QList<ThreadObject*> threadObjects;
    for (int i=0;i<numThreads;i++) {
        QThread *newThread = new QThread();
        createdThreads.append(newThread);

        ThreadObject *threadObject = new ThreadObject();
        threadObjects.append(threadObject);
        threadObject->setParameters(numQueries, testDataAmount);
        threadObject->moveToThread(newThread);

        // connec the threads started signal to the slot that does the work
        QObject::connect(newThread, SIGNAL(started()), threadObject, SLOT(startQueries()));
    }
    // start all the threads
    foreach(QThread* thread, createdThreads) {
        thread->start();
    }
    // wait for all the threads then delete
    // TODO: add timer so we don't wait forever
    foreach(QThread* thread, createdThreads) {
        while (!thread->isFinished())
            QTest::qWait(500);
        delete thread;
    }
    //cleanup
    foreach(ThreadObject *threadObject, threadObjects)
        delete threadObject;
}

void tst_QSparqlTrackerDirectConcurrency::multipleConnections_selectQueries_data()
{
    qDebug() << "This data function has been called....";
    QTest::addColumn<int>("testDataAmount");
    QTest::addColumn<int>("numQueries");
    QTest::addColumn<int>("numThreads");

    QTest::newRow("3000 items, 10 queries, 2 Threads") <<
        3000 << 10 << 2;
    QTest::newRow("3000 items, 100 queries, 2 Threads") <<
        3000 << 100 << 2;
    QTest::newRow("3000 items, 10 queries, 10 Threads") <<
        3000 << 10 << 10;
    QTest::newRow("3000 items, 100 queries, 10 Threads") <<
        3000 << 100 << 10;
}

QTEST_MAIN( tst_QSparqlTrackerDirectConcurrency )
#include "tst_qsparql_tracker_direct_concurrency.moc"
<|endoftext|>


<commit_before>/** @file
    @brief Implementation

    @date 2014

    @author
    Ryan Pavlik
    <ryan@sensics.com>
    <http://sensics.com>
*/

// Copyright 2014 Sensics, Inc.
//
// All rights reserved.
//
// (Final version intended to be licensed under
// the Apache License, Version 2.0)

// Internal Includes
#include "ServerImpl.h"
#include <osvr/Connection/Connection.h>
#include <osvr/PluginHost/RegistrationContext.h>
#include <osvr/Util/MessageKeys.h>
#include <osvr/Connection/MessageType.h>

// Library/third-party includes
// - none

// Standard includes
#include <stdexcept>
#include <functional>

namespace osvr {
namespace server {
    ServerImpl::ServerImpl(connection::ConnectionPtr const &conn)
        : m_conn(conn), m_ctx(make_shared<pluginhost::RegistrationContext>()),
          m_running(false) {
        if (!m_conn) {
            throw std::logic_error(
                "Can't pass a null ConnectionPtr into Server constructor!");
        }
        osvr::connection::Connection::storeConnection(*m_ctx, m_conn);

        if (!m_sysDevice) {
            m_sysDevice = connection::DeviceToken::createVirtualDevice(
                util::messagekeys::systemSender(), m_conn);
        }
        if (!m_routingMessageType) {
            m_routingMessageType =
                m_conn->registerMessageType(util::messagekeys::routingData());
        }
    }

    ServerImpl::~ServerImpl() { stop(); }

    void ServerImpl::start() {
        boost::unique_lock<boost::mutex> lock(m_runControl);
        m_running = true;

        // Use a lambda to run the loop.
        m_thread = boost::thread([&] {
            bool keepRunning = true;
            ::util::LoopGuard guard(m_run);
            do {
                keepRunning = this->loop();
            } while (keepRunning);
            m_ctx.reset();
            m_conn.reset();
            m_running = false;
        });
        m_run.signalAndWaitForStart();
    }

    void ServerImpl::startAndAwaitShutdown() {
        start();
        m_thread.join();
    }

    void ServerImpl::stop() {
        boost::unique_lock<boost::mutex> lock(m_runControl);
        m_run.signalAndWaitForShutdown();
        m_thread.join();
        m_thread = boost::thread();
    }
    void ServerImpl::signalStop() {
        boost::unique_lock<boost::mutex> lock(m_runControl);
        m_run.signalShutdown();
    }

    void ServerImpl::loadPlugin(std::string const &pluginName) {
        m_callControlled(std::bind(&pluginhost::RegistrationContext::loadPlugin,
                                   m_ctx, pluginName));
    }

    void ServerImpl::instantiateDriver(std::string const &plugin,
                                       std::string const &driver,
                                       std::string const &params) {
        m_ctx->instantiateDriver(plugin, driver, params);
    }

    void ServerImpl::triggerHardwareDetect() {
        m_callControlled(std::bind(
            &pluginhost::RegistrationContext::triggerHardwareDetect, m_ctx));
    }

    void ServerImpl::registerMainloopMethod(MainloopMethod f) {
        if (f) {
            m_mainloopMethods.push_back(f);
        }
    }

    bool ServerImpl::loop() {
        m_conn->process();
        for (auto &f : m_mainloopMethods) {
            f();
        }
        /// @todo do queued things in here?
        /// @todo configurable waiting?
        m_thread.yield();
        return m_run.shouldContinue();
    }

    template <typename Callable>
    inline void ServerImpl::m_callControlled(Callable f) {
        boost::unique_lock<boost::mutex> lock(m_runControl);
        if (m_running) {
            /// @todo not yet implemented
            throw std::logic_error("not yet implemented");
        }
        f();
    }

} // namespace server
} // namespace osvr<commit_msg>callControlled in server is OK if we're running as long as we're in the right thread.<commit_after>/** @file
    @brief Implementation

    @date 2014

    @author
    Ryan Pavlik
    <ryan@sensics.com>
    <http://sensics.com>
*/

// Copyright 2014 Sensics, Inc.
//
// All rights reserved.
//
// (Final version intended to be licensed under
// the Apache License, Version 2.0)

// Internal Includes
#include "ServerImpl.h"
#include <osvr/Connection/Connection.h>
#include <osvr/PluginHost/RegistrationContext.h>
#include <osvr/Util/MessageKeys.h>
#include <osvr/Connection/MessageType.h>

// Library/third-party includes
// - none

// Standard includes
#include <stdexcept>
#include <functional>

namespace osvr {
namespace server {
    ServerImpl::ServerImpl(connection::ConnectionPtr const &conn)
        : m_conn(conn), m_ctx(make_shared<pluginhost::RegistrationContext>()),
          m_running(false) {
        if (!m_conn) {
            throw std::logic_error(
                "Can't pass a null ConnectionPtr into Server constructor!");
        }
        osvr::connection::Connection::storeConnection(*m_ctx, m_conn);

        if (!m_sysDevice) {
            m_sysDevice = connection::DeviceToken::createVirtualDevice(
                util::messagekeys::systemSender(), m_conn);
        }
        if (!m_routingMessageType) {
            m_routingMessageType =
                m_conn->registerMessageType(util::messagekeys::routingData());
        }
    }

    ServerImpl::~ServerImpl() { stop(); }

    void ServerImpl::start() {
        boost::unique_lock<boost::mutex> lock(m_runControl);
        m_running = true;

        // Use a lambda to run the loop.
        m_thread = boost::thread([&] {
            bool keepRunning = true;
            ::util::LoopGuard guard(m_run);
            do {
                keepRunning = this->loop();
            } while (keepRunning);
            m_ctx.reset();
            m_conn.reset();
            m_running = false;
        });
        m_run.signalAndWaitForStart();
    }

    void ServerImpl::startAndAwaitShutdown() {
        start();
        m_thread.join();
    }

    void ServerImpl::stop() {
        boost::unique_lock<boost::mutex> lock(m_runControl);
        m_run.signalAndWaitForShutdown();
        m_thread.join();
        m_thread = boost::thread();
    }
    void ServerImpl::signalStop() {
        boost::unique_lock<boost::mutex> lock(m_runControl);
        m_run.signalShutdown();
    }

    void ServerImpl::loadPlugin(std::string const &pluginName) {
        m_callControlled(std::bind(&pluginhost::RegistrationContext::loadPlugin,
                                   m_ctx, pluginName));
    }

    void ServerImpl::instantiateDriver(std::string const &plugin,
                                       std::string const &driver,
                                       std::string const &params) {
        m_ctx->instantiateDriver(plugin, driver, params);
    }

    void ServerImpl::triggerHardwareDetect() {
        m_callControlled(std::bind(
            &pluginhost::RegistrationContext::triggerHardwareDetect, m_ctx));
    }

    void ServerImpl::registerMainloopMethod(MainloopMethod f) {
        if (f) {
            m_mainloopMethods.push_back(f);
        }
    }

    bool ServerImpl::loop() {
        m_conn->process();
        for (auto &f : m_mainloopMethods) {
            f();
        }
        /// @todo do queued things in here?
        /// @todo configurable waiting?
        m_thread.yield();
        return m_run.shouldContinue();
    }

    template <typename Callable>
    inline void ServerImpl::m_callControlled(Callable f) {
        boost::unique_lock<boost::mutex> lock(m_runControl);
        if (m_running && boost::this_thread::get_id() != m_thread.get_id()) {
            /// @todo callControlled after the run loop started from outside the
            /// run loop's thread is not yet implemented
            throw std::logic_error("not yet implemented");
        }
        f();
    }

} // namespace server
} // namespace osvr<|endoftext|>


<commit_before>/**
 * \ file UniversalFixedDelayLineFilter.cpp
 */

#include <ATK/Delay/UniversalFixedDelayLineFilter.h>

#include <ATK/Core/InPointerFilter.h>
#include <ATK/Core/OutPointerFilter.h>

#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_NO_MAIN
#include <boost/test/unit_test.hpp>

#include <boost/math/constants/constants.hpp>

#define PROCESSSIZE (1024*64)

BOOST_AUTO_TEST_CASE( UniversalFixedDelayLineFilter_sinus_line100_delay50_test )
{
  boost::scoped_array<float> data(new float[PROCESSSIZE]);
  for(std::int64_t i = 0; i < PROCESSSIZE; ++i)
  {
    data[i] = std::sin(2 * boost::math::constants::pi<float>() * (i+1.)/48000 * 1000);
  }

  ATK::InPointerFilter<float> generator(data.get(), 1, PROCESSSIZE, false);
  generator.set_output_sampling_rate(48000);

  boost::scoped_array<float> outdata(new float[PROCESSSIZE]);

  ATK::UniversalFixedDelayLineFilter<float> filter(100);
  filter.set_input_sampling_rate(48000);
  filter.set_input_port(0, &generator, 0);
  filter.set_delay(50);

  ATK::OutPointerFilter<float> output(outdata.get(), 1, PROCESSSIZE, false);
  output.set_input_sampling_rate(48000);
  output.set_input_port(0, &filter, 0);

  output.process(1);
  output.process(49);
  output.process(51);
  output.process(PROCESSSIZE - 1 - 49 -51);

  for(std::int64_t i = 0; i < 50; ++i)
  {
    BOOST_REQUIRE_EQUAL(0, outdata[i]);
  }

  for(std::int64_t i = 50; i < PROCESSSIZE; ++i)
  {
    BOOST_REQUIRE_EQUAL(data[i - 50], outdata[i]);
  }
}
<commit_msg>Testing additional options in the delay line<commit_after>/**
 * \ file UniversalFixedDelayLineFilter.cpp
 */

#include <ATK/Delay/UniversalFixedDelayLineFilter.h>

#include <ATK/Core/InPointerFilter.h>
#include <ATK/Core/OutPointerFilter.h>

#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_NO_MAIN
#include <boost/test/unit_test.hpp>

#include <boost/math/constants/constants.hpp>

#define PROCESSSIZE (1024*64)

BOOST_AUTO_TEST_CASE( UniversalFixedDelayLineFilter_sinus_line100_delay50_test )
{
  boost::scoped_array<float> data(new float[PROCESSSIZE]);
  for(std::int64_t i = 0; i < PROCESSSIZE; ++i)
  {
    data[i] = std::sin(2 * boost::math::constants::pi<float>() * (i+1.)/48000 * 1000);
  }

  ATK::InPointerFilter<float> generator(data.get(), 1, PROCESSSIZE, false);
  generator.set_output_sampling_rate(48000);

  boost::scoped_array<float> outdata(new float[PROCESSSIZE]);

  ATK::UniversalFixedDelayLineFilter<float> filter(100);
  filter.set_input_sampling_rate(48000);
  filter.set_input_port(0, &generator, 0);
  filter.set_delay(50);

  ATK::OutPointerFilter<float> output(outdata.get(), 1, PROCESSSIZE, false);
  output.set_input_sampling_rate(48000);
  output.set_input_port(0, &filter, 0);

  output.process(49);
  output.process(1);
  output.process(51);
  output.process(PROCESSSIZE - 1 - 49 -51);

  for(std::int64_t i = 0; i < 50; ++i)
  {
    BOOST_REQUIRE_EQUAL(0, outdata[i]);
  }

  for(std::int64_t i = 50; i < PROCESSSIZE; ++i)
  {
    BOOST_REQUIRE_EQUAL(data[i - 50], outdata[i]);
  }
}

BOOST_AUTO_TEST_CASE( UniversalFixedDelayLineFilter_sinus_line25_delay24_blend_1_feedforward_1_feedback_0_test )
{
  boost::scoped_array<float> data(new float[PROCESSSIZE]);
  for(std::int64_t i = 0; i < PROCESSSIZE; ++i)
  {
    data[i] = std::sin(2 * boost::math::constants::pi<float>() * (i+1.)/48000 * 1000);
  }

  ATK::InPointerFilter<float> generator(data.get(), 1, PROCESSSIZE, false);
  generator.set_output_sampling_rate(48000);

  boost::scoped_array<float> outdata(new float[PROCESSSIZE]);

  ATK::UniversalFixedDelayLineFilter<float> filter(25);
  filter.set_input_sampling_rate(48000);
  filter.set_input_port(0, &generator, 0);
  filter.set_delay(24);
  filter.set_blend(1);
  filter.set_feedback(0);
  filter.set_feedforward(1);

  ATK::OutPointerFilter<float> output(outdata.get(), 1, PROCESSSIZE, false);
  output.set_input_sampling_rate(48000);
  output.set_input_port(0, &filter, 0);

  output.process(49);
  output.process(1);
  output.process(51);
  output.process(PROCESSSIZE - 1 - 49 -51);

  for(std::int64_t i = 24; i < PROCESSSIZE; ++i)
  {
    BOOST_REQUIRE_SMALL(outdata[i], 0.0001f);
  }
}

BOOST_AUTO_TEST_CASE( UniversalFixedDelayLineFilter_sinus_line25_delay24_blend_0_feedforward_0_feedback_1_test )
{
  boost::scoped_array<float> data(new float[PROCESSSIZE]);
  for(std::int64_t i = 0; i < PROCESSSIZE; ++i)
  {
    data[i] = std::sin(2 * boost::math::constants::pi<float>() * (i+1.)/48000 * 1000);
  }

  ATK::InPointerFilter<float> generator(data.get(), 1, PROCESSSIZE, false);
  generator.set_output_sampling_rate(48000);

  boost::scoped_array<float> outdata(new float[PROCESSSIZE]);

  ATK::UniversalFixedDelayLineFilter<float> filter(25);
  filter.set_input_sampling_rate(48000);
  filter.set_input_port(0, &generator, 0);
  filter.set_delay(24);
  filter.set_blend(0);
  filter.set_feedback(1);
  filter.set_feedforward(0);

  ATK::OutPointerFilter<float> output(outdata.get(), 1, PROCESSSIZE, false);
  output.set_input_sampling_rate(48000);
  output.set_input_port(0, &filter, 0);

  output.process(49);
  output.process(1);
  output.process(51);
  output.process(PROCESSSIZE - 1 - 49 -51);

  for(std::int64_t i = 24; i < PROCESSSIZE; ++i)
  {
    BOOST_REQUIRE_SMALL(outdata[i], 0.0001f);
  }
}
<|endoftext|>


<commit_before>/** @file
    @brief Implementation

    @date 2014

    @author
    Ryan Pavlik
    <ryan@sensics.com>
    <http://sensics.com>
*/

// Copyright 2014 Sensics, Inc.
//
// All rights reserved.
//
// (Final version intended to be licensed under
// the Apache License, Version 2.0)

// Internal Includes
#include "ServerImpl.h"
#include <osvr/Connection/Connection.h>
#include <osvr/PluginHost/RegistrationContext.h>
#include <osvr/Util/MessageKeys.h>
#include <osvr/Connection/MessageType.h>
#include <osvr/Util/Verbosity.h>

// Library/third-party includes
// - none

// Standard includes
#include <stdexcept>
#include <functional>

namespace osvr {
namespace server {
    ServerImpl::ServerImpl(connection::ConnectionPtr const &conn)
        : m_conn(conn), m_ctx(make_shared<pluginhost::RegistrationContext>()),
          m_running(false) {
        if (!m_conn) {
            throw std::logic_error(
                "Can't pass a null ConnectionPtr into Server constructor!");
        }
        osvr::connection::Connection::storeConnection(*m_ctx, m_conn);

        if (!m_sysDevice) {
            m_sysDevice = connection::DeviceToken::createVirtualDevice(
                util::messagekeys::systemSender(), m_conn);
        }
        if (!m_routingMessageType) {
            m_routingMessageType =
                m_conn->registerMessageType(util::messagekeys::routingData());
        }
        m_conn->registerConnectionHandler(
            std::bind(&ServerImpl::triggerHardwareDetect, std::ref(*this)));
        m_conn->registerConnectionHandler(
            std::bind(&ServerImpl::m_sendRoutes, std::ref(*this)));
    }

    ServerImpl::~ServerImpl() { stop(); }

    void ServerImpl::start() {
        boost::unique_lock<boost::mutex> lock(m_runControl);
        m_running = true;

        // Use a lambda to run the loop.
        m_thread = boost::thread([&] {
            bool keepRunning = true;
            ::util::LoopGuard guard(m_run);
            do {
                keepRunning = this->loop();
            } while (keepRunning);
            m_ctx.reset();
            m_conn.reset();
            m_running = false;
        });
        m_run.signalAndWaitForStart();
    }

    void ServerImpl::startAndAwaitShutdown() {
        start();
        awaitShutdown();
    }

    void ServerImpl::awaitShutdown() { m_thread.join(); }

    void ServerImpl::stop() {
        boost::unique_lock<boost::mutex> lock(m_runControl);
        m_run.signalAndWaitForShutdown();
        m_thread.join();
        m_thread = boost::thread();
    }

    void ServerImpl::signalStop() {
        boost::unique_lock<boost::mutex> lock(m_runControl);
        m_run.signalShutdown();
    }

    void ServerImpl::loadPlugin(std::string const &pluginName) {
        m_callControlled(std::bind(&pluginhost::RegistrationContext::loadPlugin,
                                   m_ctx, pluginName));
    }

    void ServerImpl::instantiateDriver(std::string const &plugin,
                                       std::string const &driver,
                                       std::string const &params) {
        m_ctx->instantiateDriver(plugin, driver, params);
    }

    void ServerImpl::triggerHardwareDetect() {
        OSVR_DEV_VERBOSE("Performing hardware auto-detection.");
        m_callControlled(std::bind(
            &pluginhost::RegistrationContext::triggerHardwareDetect, m_ctx));
    }

    void ServerImpl::registerMainloopMethod(MainloopMethod f) {
        if (f) {
            m_callControlled([&] { m_mainloopMethods.push_back(f); });
        }
    }

    bool ServerImpl::loop() {
        bool shouldContinue;
        {
            /// @todo More elegant way of running queued things than grabbing a
            /// mutex each time through?
            boost::unique_lock<boost::mutex> lock(m_mainThreadMutex);
            m_conn->process();
            for (auto &f : m_mainloopMethods) {
                f();
            }
            shouldContinue = m_run.shouldContinue();
        }
        /// @todo configurable waiting?
        m_thread.yield();
        return shouldContinue;
    }

    bool ServerImpl::addRoute(std::string const &routingDirective) {
        bool wasNew;
        m_callControlled([&] { wasNew = m_routes.addRoute(routingDirective); });
        return wasNew;
    }

    std::string ServerImpl::getRoutes(bool styled) const {
        std::string ret;
        m_callControlled([&] { ret = m_routes.getRoutes(styled); });
        return ret;
    }

    std::string ServerImpl::getSource(std::string const &destination) const {
        std::string ret;
        m_callControlled([&] { ret = m_routes.getSource(destination); });
        return ret;
    }

    void ServerImpl::m_sendRoutes() {
        std::string message = getRoutes(false);
        OSVR_DEV_VERBOSE("Transmitting " << m_routes.size()
                                         << " routes to the client.");
        m_sysDevice->sendData(m_routingMessageType.get(), message.c_str(),
                              message.size());
    }

} // namespace server
} // namespace osvr<commit_msg>Don't have a nested callControlled when sending routes.<commit_after>/** @file
    @brief Implementation

    @date 2014

    @author
    Ryan Pavlik
    <ryan@sensics.com>
    <http://sensics.com>
*/

// Copyright 2014 Sensics, Inc.
//
// All rights reserved.
//
// (Final version intended to be licensed under
// the Apache License, Version 2.0)

// Internal Includes
#include "ServerImpl.h"
#include <osvr/Connection/Connection.h>
#include <osvr/PluginHost/RegistrationContext.h>
#include <osvr/Util/MessageKeys.h>
#include <osvr/Connection/MessageType.h>
#include <osvr/Util/Verbosity.h>

// Library/third-party includes
// - none

// Standard includes
#include <stdexcept>
#include <functional>

namespace osvr {
namespace server {
    ServerImpl::ServerImpl(connection::ConnectionPtr const &conn)
        : m_conn(conn), m_ctx(make_shared<pluginhost::RegistrationContext>()),
          m_running(false) {
        if (!m_conn) {
            throw std::logic_error(
                "Can't pass a null ConnectionPtr into Server constructor!");
        }
        osvr::connection::Connection::storeConnection(*m_ctx, m_conn);

        if (!m_sysDevice) {
            m_sysDevice = connection::DeviceToken::createVirtualDevice(
                util::messagekeys::systemSender(), m_conn);
        }
        if (!m_routingMessageType) {
            m_routingMessageType =
                m_conn->registerMessageType(util::messagekeys::routingData());
        }
        m_conn->registerConnectionHandler(
            std::bind(&ServerImpl::triggerHardwareDetect, std::ref(*this)));
        m_conn->registerConnectionHandler(
            std::bind(&ServerImpl::m_sendRoutes, std::ref(*this)));
    }

    ServerImpl::~ServerImpl() { stop(); }

    void ServerImpl::start() {
        boost::unique_lock<boost::mutex> lock(m_runControl);
        m_running = true;

        // Use a lambda to run the loop.
        m_thread = boost::thread([&] {
            bool keepRunning = true;
            ::util::LoopGuard guard(m_run);
            do {
                keepRunning = this->loop();
            } while (keepRunning);
            m_ctx.reset();
            m_conn.reset();
            m_running = false;
        });
        m_run.signalAndWaitForStart();
    }

    void ServerImpl::startAndAwaitShutdown() {
        start();
        awaitShutdown();
    }

    void ServerImpl::awaitShutdown() { m_thread.join(); }

    void ServerImpl::stop() {
        boost::unique_lock<boost::mutex> lock(m_runControl);
        m_run.signalAndWaitForShutdown();
        m_thread.join();
        m_thread = boost::thread();
    }

    void ServerImpl::signalStop() {
        boost::unique_lock<boost::mutex> lock(m_runControl);
        m_run.signalShutdown();
    }

    void ServerImpl::loadPlugin(std::string const &pluginName) {
        m_callControlled(std::bind(&pluginhost::RegistrationContext::loadPlugin,
                                   m_ctx, pluginName));
    }

    void ServerImpl::instantiateDriver(std::string const &plugin,
                                       std::string const &driver,
                                       std::string const &params) {
        m_ctx->instantiateDriver(plugin, driver, params);
    }

    void ServerImpl::triggerHardwareDetect() {
        OSVR_DEV_VERBOSE("Performing hardware auto-detection.");
        m_callControlled(std::bind(
            &pluginhost::RegistrationContext::triggerHardwareDetect, m_ctx));
    }

    void ServerImpl::registerMainloopMethod(MainloopMethod f) {
        if (f) {
            m_callControlled([&] { m_mainloopMethods.push_back(f); });
        }
    }

    bool ServerImpl::loop() {
        bool shouldContinue;
        {
            /// @todo More elegant way of running queued things than grabbing a
            /// mutex each time through?
            boost::unique_lock<boost::mutex> lock(m_mainThreadMutex);
            m_conn->process();
            for (auto &f : m_mainloopMethods) {
                f();
            }
            shouldContinue = m_run.shouldContinue();
        }
        /// @todo configurable waiting?
        m_thread.yield();
        return shouldContinue;
    }

    bool ServerImpl::addRoute(std::string const &routingDirective) {
        bool wasNew;
        m_callControlled([&] { wasNew = m_routes.addRoute(routingDirective); });
        return wasNew;
    }

    std::string ServerImpl::getRoutes(bool styled) const {
        std::string ret;
        m_callControlled([&] { ret = m_routes.getRoutes(styled); });
        return ret;
    }

    std::string ServerImpl::getSource(std::string const &destination) const {
        std::string ret;
        m_callControlled([&] { ret = m_routes.getSource(destination); });
        return ret;
    }

    void ServerImpl::m_sendRoutes() {
        std::string message = m_routes.getRoutes();
        OSVR_DEV_VERBOSE("Transmitting " << m_routes.size()
                                         << " routes to the client.");
        m_sysDevice->sendData(m_routingMessageType.get(), message.c_str(),
                              message.size());
    }

} // namespace server
} // namespace osvr<|endoftext|>


<commit_before>// Arguments: Doubles, Doubles, Doubles, Doubles
#include <stan/math/prim.hpp>

using stan::math::var;
using std::numeric_limits;
using std::vector;

class AgradDistributionsStudentT : public AgradDistributionTest {
 public:
  void valid_values(vector<vector<double> >& parameters,
                    vector<double>& log_prob) {
    vector<double> param(4);

    param[0] = 1.0;  // y
    param[1] = 1.0;  // nu
    param[2] = 0.0;  // mu
    param[3] = 1.0;  // sigma
    parameters.push_back(param);
    log_prob.push_back(-1.837877066409345339082);  // expected log_prob

    param[0] = -3.0;  // y
    param[1] = 2.0;   // nu
    param[2] = 0.0;   // mu
    param[3] = 1.0;   // sigma
    parameters.push_back(param);
    log_prob.push_back(-3.596842909197555560041);  // expected log_prob
  }

  void invalid_values(vector<size_t>& index, vector<double>& value) {
    // y

    // nu
    index.push_back(1U);
    value.push_back(0.0);

    index.push_back(1U);
    value.push_back(-1.0);

    index.push_back(1U);
    value.push_back(numeric_limits<double>::infinity());

    index.push_back(1U);
    value.push_back(-numeric_limits<double>::infinity());

    // mu
    index.push_back(2U);
    value.push_back(numeric_limits<double>::infinity());

    index.push_back(2U);
    value.push_back(-numeric_limits<double>::infinity());

    // sigma
    index.push_back(3U);
    value.push_back(0.0);

    index.push_back(3U);
    value.push_back(-1.0);

    index.push_back(3U);
    value.push_back(numeric_limits<double>::infinity());

    index.push_back(3U);
    value.push_back(-numeric_limits<double>::infinity());
  }

  template <class T_y, class T_dof, class T_loc, class T_scale, typename T4,
            typename T5>
  typename stan::return_type<T_y, T_dof, T_loc, T_scale>::type log_prob(
      const T_y& y, const T_dof& nu, const T_loc& mu, const T_scale& sigma,
      const T4&, const T5&) {
    return stan::math::student_t_log(y, nu, mu, sigma);
  }

  template <bool propto, class T_y, class T_dof, class T_loc, class T_scale,
            typename T4, typename T5>
  typename stan::return_type<T_y, T_dof, T_loc, T_scale>::type log_prob(
      const T_y& y, const T_dof& nu, const T_loc& mu, const T_scale& sigma,
      const T4&, const T5&) {
    return stan::math::student_t_log<propto>(y, nu, mu, sigma);
  }

  template <class T_y, class T_dof, class T_loc, class T_scale, typename T4,
            typename T5>
  typename stan::return_type<T_y, T_dof, T_loc, T_scale>::type
  log_prob_function(const T_y& y, const T_dof& nu, const T_loc& mu,
                    const T_scale& sigma, const T4&, const T5&) {
    using boost::math::lgamma;
    using stan::math::log1p;
    using stan::math::LOG_SQRT_PI;
    using stan::math::square;
    using std::log;

    return lgamma((nu + 1.0) / 2.0) - lgamma(nu / 2.0) - LOG_SQRT_PI
           - 0.5 * log(nu) - log(sigma)
           - ((nu + 1.0) / 2.0) * log1p(square(((y - mu) / sigma)) / nu);
  }
};
<commit_msg>[Jenkins] auto-formatting by clang-format version 6.0.0 (tags/google/stable/2017-11-14)<commit_after>// Arguments: Doubles, Doubles, Doubles, Doubles
#include <stan/math/prim.hpp>

using stan::math::var;
using std::numeric_limits;
using std::vector;

class AgradDistributionsStudentT : public AgradDistributionTest {
 public:
  void valid_values(vector<vector<double> >& parameters,
                    vector<double>& log_prob) {
    vector<double> param(4);

    param[0] = 1.0;  // y
    param[1] = 1.0;  // nu
    param[2] = 0.0;  // mu
    param[3] = 1.0;  // sigma
    parameters.push_back(param);
    log_prob.push_back(-1.837877066409345339082);  // expected log_prob

    param[0] = -3.0;  // y
    param[1] = 2.0;   // nu
    param[2] = 0.0;   // mu
    param[3] = 1.0;   // sigma
    parameters.push_back(param);
    log_prob.push_back(-3.596842909197555560041);  // expected log_prob
  }

  void invalid_values(vector<size_t>& index, vector<double>& value) {
    // y

    // nu
    index.push_back(1U);
    value.push_back(0.0);

    index.push_back(1U);
    value.push_back(-1.0);

    index.push_back(1U);
    value.push_back(numeric_limits<double>::infinity());

    index.push_back(1U);
    value.push_back(-numeric_limits<double>::infinity());

    // mu
    index.push_back(2U);
    value.push_back(numeric_limits<double>::infinity());

    index.push_back(2U);
    value.push_back(-numeric_limits<double>::infinity());

    // sigma
    index.push_back(3U);
    value.push_back(0.0);

    index.push_back(3U);
    value.push_back(-1.0);

    index.push_back(3U);
    value.push_back(numeric_limits<double>::infinity());

    index.push_back(3U);
    value.push_back(-numeric_limits<double>::infinity());
  }

  template <class T_y, class T_dof, class T_loc, class T_scale, typename T4,
            typename T5>
  typename stan::return_type<T_y, T_dof, T_loc, T_scale>::type log_prob(
      const T_y& y, const T_dof& nu, const T_loc& mu, const T_scale& sigma,
      const T4&, const T5&) {
    return stan::math::student_t_log(y, nu, mu, sigma);
  }

  template <bool propto, class T_y, class T_dof, class T_loc, class T_scale,
            typename T4, typename T5>
  typename stan::return_type<T_y, T_dof, T_loc, T_scale>::type log_prob(
      const T_y& y, const T_dof& nu, const T_loc& mu, const T_scale& sigma,
      const T4&, const T5&) {
    return stan::math::student_t_log<propto>(y, nu, mu, sigma);
  }

  template <class T_y, class T_dof, class T_loc, class T_scale, typename T4,
            typename T5>
  typename stan::return_type<T_y, T_dof, T_loc, T_scale>::type
  log_prob_function(const T_y& y, const T_dof& nu, const T_loc& mu,
                    const T_scale& sigma, const T4&, const T5&) {
    using boost::math::lgamma;
    using stan::math::LOG_SQRT_PI;
    using stan::math::log1p;
    using stan::math::square;
    using std::log;

    return lgamma((nu + 1.0) / 2.0) - lgamma(nu / 2.0) - LOG_SQRT_PI
           - 0.5 * log(nu) - log(sigma)
           - ((nu + 1.0) / 2.0) * log1p(square(((y - mu) / sigma)) / nu);
  }
};
<|endoftext|>


<commit_before>// $Id$

// The libMesh Finite Element Library.
// Copyright (C) 2002-2007  Benjamin S. Kirk, John W. Peterson

// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.

// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.

// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

// C++ Includes   -----------------------------------

// Local Includes -----------------------------------
#include "elem.h"
#include "mesh_base.h"
#include "parallel.h"
#include "partitioner.h"

// ------------------------------------------------------------
// Partitioner implementation

void Partitioner::partition (MeshBase& mesh,
			     const unsigned int n)
{
  // For now we don't repartition in parallel
  if (!mesh.is_serial())
    return;

  // Set the number of partitions in the mesh
  mesh.set_n_partitions()=n;

  // Call the partitioning function
  this->_do_partition(mesh,n);

  // Set the node's processor ids
  Partitioner::set_node_processor_ids(mesh);
}

void Partitioner::repartition (MeshBase& mesh,
			       const unsigned int n)
{
  // Set the number of partitions in the mesh
  mesh.set_n_partitions()=n;

  // Call the partitioning function
  this->_do_repartition(mesh,n);

  // Set the node's processor ids
  Partitioner::set_node_processor_ids(mesh);
}

void Partitioner::single_partition (MeshBase& mesh)
{
  // Loop over all the elements and assign them to processor 0.
  MeshBase::element_iterator       elem_it  = mesh.elements_begin();
  const MeshBase::element_iterator elem_end = mesh.elements_end();

  for ( ; elem_it != elem_end; ++elem_it)
    (*elem_it)->processor_id() = 0;

  // For a single partition, all the nodes are on processor 0
  MeshBase::node_iterator       node_it  = mesh.nodes_begin();
  const MeshBase::node_iterator node_end = mesh.nodes_end();

  for ( ; node_it != node_end; ++node_it)
    (*node_it)->processor_id() = 0;
}

void Partitioner::set_node_processor_ids(MeshBase& mesh)
{
  // This function must be run on all processors at once
  parallel_only();

  // Unset any previously-set node processor ids
  // (maybe from previous partitionings).
  MeshBase::node_iterator       node_it  = mesh.nodes_begin();
  const MeshBase::node_iterator node_end = mesh.nodes_end();

  for ( ; node_it != node_end; ++node_it)
    {
      Node *node = *node_it;
      assert(node);
      node->invalidate_processor_id();
    }

  // Loop over all the active elements
  MeshBase::element_iterator       elem_it  = mesh.active_elements_begin();
  const MeshBase::element_iterator elem_end = mesh.active_elements_end();

  for ( ; elem_it != elem_end; ++elem_it)
    {
      Elem* elem = *elem_it;
      assert(elem);

      // For each node, set the processor ID to the min of
      // its current value and this Element's processor id.
      for (unsigned int n=0; n<elem->n_nodes(); ++n)
	elem->get_node(n)->processor_id() = std::min(elem->get_node(n)->processor_id(),
						     elem->processor_id());
    }

  // And loop over the subactive elements, but don't reassign
  // nodes that are already active on another processor.
  MeshBase::element_iterator       sub_it  = mesh.subactive_elements_begin();
  const MeshBase::element_iterator sub_end = mesh.subactive_elements_end();

  for ( ; sub_it != sub_end; ++sub_it)
    {
      Elem* elem = *sub_it;
      assert(elem);

      for (unsigned int n=0; n<elem->n_nodes(); ++n)
        if (elem->get_node(n)->processor_id() == DofObject::invalid_processor_id)
	  elem->get_node(n)->processor_id() = std::min(elem->get_node(n)->processor_id(),
						       elem->processor_id());
    }

  // At this point, if we're in parallel, all our own processor ids
  // should be correct, but ghost nodes may be incorrect.  However,
  // our tenative processor ids will let us know who to ask.

  // Loop over all the nodes, count the ones on each processor
  std::vector<unsigned int>
    ghost_objects_from_proc(libMesh::n_processors(), 0);

  node_it  = mesh.nodes_begin();
  for ( ; node_it != node_end; ++node_it)
    {
      Node *node = *node_it;
      assert(node);
      unsigned int obj_procid = node->processor_id();
      assert(obj_procid != DofObject::invalid_processor_id);
      ghost_objects_from_proc[obj_procid]++;
    }

  // Request sets to send to each processor
  std::vector<std::vector<unsigned int> >
    requested_ids(libMesh::n_processors());

  // We know how many objects live on each processor, so reserve()
  // space for each.
  for (unsigned int p=0; p != libMesh::n_processors(); ++p)
    if (p != libMesh::processor_id())
      requested_ids[p].reserve(ghost_objects_from_proc[p]);

  node_it  = mesh.nodes_begin();
  for ( ; node_it != node_end; ++node_it)
    {
      Node *node = *node_it;
      requested_ids[node->processor_id()].push_back(node->id());
    }

  // Next set ghost object ids from other processors
  for (unsigned int p=1; p != libMesh::n_processors(); ++p)
    {
      // Trade my requests with processor procup and procdown
      unsigned int procup = (libMesh::processor_id() + p) %
                             libMesh::n_processors();
      unsigned int procdown = (libMesh::n_processors() +
                               libMesh::processor_id() - p) %
                               libMesh::n_processors();
      std::vector<unsigned int> request_to_fill;
      Parallel::send_receive(procup, requested_ids[procup],
                             procdown, request_to_fill);

      // Fill those requests
      std::vector<unsigned int> new_ids(request_to_fill.size());
      for (unsigned int i=0; i != request_to_fill.size(); ++i)
        {
          Node *node = mesh.node_ptr(request_to_fill[i]);
          assert(node);
          new_ids[i] = node->processor_id();
        }

      // Trade back the results
      std::vector<unsigned int> filled_request;
      Parallel::send_receive(procdown, new_ids,
                             procup, filled_request);
      assert(filled_request.size() == requested_ids[procup].size());

      // And copy the id changes we've now been informed of
      for (unsigned int i=0; i != filled_request.size(); ++i)
        {
          Node *node = mesh.node_ptr(requested_ids[procup][i]);
          assert(filled_request[i] < libMesh::n_processors());
          node->processor_id(filled_request[i]);
        }
    }
}
<commit_msg>do not partition into more pieces than we have active elements<commit_after>// $Id$

// The libMesh Finite Element Library.
// Copyright (C) 2002-2007  Benjamin S. Kirk, John W. Peterson

// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.

// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.

// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

// C++ Includes   -----------------------------------

// Local Includes -----------------------------------
#include "elem.h"
#include "mesh_base.h"
#include "parallel.h"
#include "partitioner.h"

// ------------------------------------------------------------
// Partitioner implementation

void Partitioner::partition (MeshBase& mesh,
			     const unsigned int n)
{
  // For now we don't repartition in parallel
  if (!mesh.is_serial())
    return;

  // we cannot partition into more pieces than we have
  // active elements!
  const unsigned int n_parts =
    std::min(mesh.n_active_elem(), n);

  // Set the number of partitions in the mesh
  mesh.set_n_partitions()=n_parts;

  // Call the partitioning function
  this->_do_partition(mesh,n_parts);

  // Set the node's processor ids
  Partitioner::set_node_processor_ids(mesh);
}

void Partitioner::repartition (MeshBase& mesh,
			       const unsigned int n)
{
  // we cannot partition into more pieces than we have
  // active elements!
  const unsigned int n_parts =
    std::min(mesh.n_active_elem(), n);

  // Set the number of partitions in the mesh
  mesh.set_n_partitions()=n_parts;

  // Call the partitioning function
  this->_do_repartition(mesh,n_parts);

  // Set the node's processor ids
  Partitioner::set_node_processor_ids(mesh);
}

void Partitioner::single_partition (MeshBase& mesh)
{
  // Loop over all the elements and assign them to processor 0.
  MeshBase::element_iterator       elem_it  = mesh.elements_begin();
  const MeshBase::element_iterator elem_end = mesh.elements_end();

  for ( ; elem_it != elem_end; ++elem_it)
    (*elem_it)->processor_id() = 0;

  // For a single partition, all the nodes are on processor 0
  MeshBase::node_iterator       node_it  = mesh.nodes_begin();
  const MeshBase::node_iterator node_end = mesh.nodes_end();

  for ( ; node_it != node_end; ++node_it)
    (*node_it)->processor_id() = 0;
}

void Partitioner::set_node_processor_ids(MeshBase& mesh)
{
  // This function must be run on all processors at once
  parallel_only();

  // Unset any previously-set node processor ids
  // (maybe from previous partitionings).
  MeshBase::node_iterator       node_it  = mesh.nodes_begin();
  const MeshBase::node_iterator node_end = mesh.nodes_end();

  for ( ; node_it != node_end; ++node_it)
    {
      Node *node = *node_it;
      assert(node);
      node->invalidate_processor_id();
    }

  // Loop over all the active elements
  MeshBase::element_iterator       elem_it  = mesh.active_elements_begin();
  const MeshBase::element_iterator elem_end = mesh.active_elements_end();

  for ( ; elem_it != elem_end; ++elem_it)
    {
      Elem* elem = *elem_it;
      assert(elem);

      // For each node, set the processor ID to the min of
      // its current value and this Element's processor id.
      for (unsigned int n=0; n<elem->n_nodes(); ++n)
	elem->get_node(n)->processor_id() = std::min(elem->get_node(n)->processor_id(),
						     elem->processor_id());
    }

  // And loop over the subactive elements, but don't reassign
  // nodes that are already active on another processor.
  MeshBase::element_iterator       sub_it  = mesh.subactive_elements_begin();
  const MeshBase::element_iterator sub_end = mesh.subactive_elements_end();

  for ( ; sub_it != sub_end; ++sub_it)
    {
      Elem* elem = *sub_it;
      assert(elem);

      for (unsigned int n=0; n<elem->n_nodes(); ++n)
        if (elem->get_node(n)->processor_id() == DofObject::invalid_processor_id)
	  elem->get_node(n)->processor_id() = std::min(elem->get_node(n)->processor_id(),
						       elem->processor_id());
    }

  // At this point, if we're in parallel, all our own processor ids
  // should be correct, but ghost nodes may be incorrect.  However,
  // our tenative processor ids will let us know who to ask.

  // Loop over all the nodes, count the ones on each processor
  std::vector<unsigned int>
    ghost_objects_from_proc(libMesh::n_processors(), 0);

  node_it  = mesh.nodes_begin();
  for ( ; node_it != node_end; ++node_it)
    {
      Node *node = *node_it;
      assert(node);
      unsigned int obj_procid = node->processor_id();
      assert(obj_procid != DofObject::invalid_processor_id);
      ghost_objects_from_proc[obj_procid]++;
    }

  // Request sets to send to each processor
  std::vector<std::vector<unsigned int> >
    requested_ids(libMesh::n_processors());

  // We know how many objects live on each processor, so reserve()
  // space for each.
  for (unsigned int p=0; p != libMesh::n_processors(); ++p)
    if (p != libMesh::processor_id())
      requested_ids[p].reserve(ghost_objects_from_proc[p]);

  node_it  = mesh.nodes_begin();
  for ( ; node_it != node_end; ++node_it)
    {
      Node *node = *node_it;
      requested_ids[node->processor_id()].push_back(node->id());
    }

  // Next set ghost object ids from other processors
  for (unsigned int p=1; p != libMesh::n_processors(); ++p)
    {
      // Trade my requests with processor procup and procdown
      unsigned int procup = (libMesh::processor_id() + p) %
                             libMesh::n_processors();
      unsigned int procdown = (libMesh::n_processors() +
                               libMesh::processor_id() - p) %
                               libMesh::n_processors();
      std::vector<unsigned int> request_to_fill;
      Parallel::send_receive(procup, requested_ids[procup],
                             procdown, request_to_fill);

      // Fill those requests
      std::vector<unsigned int> new_ids(request_to_fill.size());
      for (unsigned int i=0; i != request_to_fill.size(); ++i)
        {
          Node *node = mesh.node_ptr(request_to_fill[i]);
          assert(node);
          new_ids[i] = node->processor_id();
        }

      // Trade back the results
      std::vector<unsigned int> filled_request;
      Parallel::send_receive(procdown, new_ids,
                             procup, filled_request);
      assert(filled_request.size() == requested_ids[procup].size());

      // And copy the id changes we've now been informed of
      for (unsigned int i=0; i != filled_request.size(); ++i)
        {
          Node *node = mesh.node_ptr(requested_ids[procup][i]);
          assert(filled_request[i] < libMesh::n_processors());
          node->processor_id(filled_request[i]);
        }
    }
}
<|endoftext|>