<commit_before>/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, 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.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include <qtest.h>

#include <QtGui>

#include <private/qpaintengineex_p.h>
#include <private/qpaintbuffer_p.h>

//TESTED_FILES=

class ReplayWidget : public QWidget
{
    Q_OBJECT
public:
    ReplayWidget(const QString &filename);

    void paintEvent(QPaintEvent *event);
    void resizeEvent(QResizeEvent *event);

    bool done() const { return m_done; }
    qreal result() const { return m_result; }

public slots:
    void updateRect();

public:
    QList<QRegion> updates;
    QPaintBuffer buffer;

    int currentFrame;
    int currentIteration;
    QTime timer;

    QList<uint> visibleUpdates;
    QList<uint> iterationTimes;
    QString filename;

    bool m_done;
    qreal m_result;

    uint m_total;
};

void ReplayWidget::updateRect()
{
    if (!visibleUpdates.isEmpty())
        update(updates.at(visibleUpdates.at(currentFrame)));
}

void ReplayWidget::paintEvent(QPaintEvent *)
{
    if (m_done)
        return;

    QPainter p(this);

    // if partial updates don't work
    // p.setClipRegion(frames.at(currentFrame).updateRegion);

    buffer.draw(&p, visibleUpdates.at(currentFrame));

    ++currentFrame;
    if (currentFrame >= visibleUpdates.size()) {
        currentFrame = 0;
        ++currentIteration;

        uint currentElapsed = timer.isNull() ? 0 : timer.elapsed();
        timer.restart();

        m_total += currentElapsed;

        // warm up for at most 5 iterations or half a second
        if (currentIteration >= 5 || m_total >= 500) {
            iterationTimes << currentElapsed;

            if (iterationTimes.size() >= 5) {
                qreal mean = 0;
                qreal stddev = 0;
                uint min = INT_MAX;

                for (int i = 0; i < iterationTimes.size(); ++i) {
                    mean += iterationTimes.at(i);
                    min = qMin(min, iterationTimes.at(i));
                }

                mean /= qreal(iterationTimes.size());

                for (int i = 0; i < iterationTimes.size(); ++i) {
                    qreal delta = iterationTimes.at(i) - mean;
                    stddev += delta * delta;
                }

                stddev = qSqrt(stddev / iterationTimes.size());

                qSort(iterationTimes.begin(), iterationTimes.end());
                uint median = iterationTimes.at(iterationTimes.size() / 2);

                stddev = 100 * stddev / mean;
                // do 100 iterations, break earlier if we spend more than 5 seconds or have a low std deviation after 2 seconds
                if (iterationTimes.size() >= 100 || m_total >= 5000 || (m_total >= 2000 && stddev < 4)) {
                    printf("%s, iterations: %d, frames: %d, min(ms): %d, median(ms): %d, stddev: %f %%, max(fps): %f\n", qPrintable(filename),
                            iterationTimes.size(), visibleUpdates.size(), min, median, stddev, 1000. * visibleUpdates.size() / min);
                    m_result = min;
                    m_done = true;
                    return;
                }
            }
        }
    }
}

void ReplayWidget::resizeEvent(QResizeEvent *event)
{
    visibleUpdates.clear();

    QRect bounds = rect();
    for (int i = 0; i < updates.size(); ++i) {
        if (updates.at(i).intersects(bounds))
            visibleUpdates << i;
    }

    if (visibleUpdates.size() != updates.size())
        printf("Warning: skipped %d frames due to limited resolution\n", updates.size() - visibleUpdates.size());

}

ReplayWidget::ReplayWidget(const QString &filename_)
    : currentFrame(0)
    , currentIteration(0)
    , filename(filename_)
    , m_done(false)
    , m_result(0)
    , m_total(0)
{
    setWindowTitle(filename);
    QFile file(filename);

    if (!file.open(QIODevice::ReadOnly)) {
        printf("Failed to load input file '%s'\n", qPrintable(filename_));
        return;
    }

    QDataStream in(&file);

    char *data;
    uint size;
    in.readBytes(data, size);
    bool isTraceFile = size >= 7 && qstrncmp(data, "qttrace", 7) == 0;
    uint version = 0;
    if (size == 9 && qstrncmp(data, "qttraceV2", 9) == 0) {
        in.setFloatingPointPrecision(QDataStream::SinglePrecision);
        in >> version;
    }

    delete [] data;
    if (!isTraceFile) {
        printf("File '%s' is not a trace file\n", qPrintable(filename_));
        return;
    }

    in >> buffer >> updates;
    printf("Read paint buffer version %d with %d frames\n", version, buffer.numFrames());

    resize(buffer.boundingRect().size().toSize());

    setAutoFillBackground(false);
    setAttribute(Qt::WA_NoSystemBackground);
}

class tst_QTraceBench : public QObject
{
    Q_OBJECT

private slots:
    void trace();
    void trace_data();
};

static const QLatin1String prefix(":/traces/");

void tst_QTraceBench::trace_data()
{
    QTest::addColumn<QString>("filename");

    QTest::newRow("basicdrawing") << (prefix + "basicdrawing.trace");
    QTest::newRow("webkit") << (prefix + "webkit.trace");
    QTest::newRow("creator") << (prefix + "creator.trace");
    QTest::newRow("textedit") << (prefix + "textedit.trace");
    QTest::newRow("qmlphoneconcept") << (prefix + "qmlphoneconcept.trace");
    QTest::newRow("qmlsamegame") << (prefix + "qmlsamegame.trace");
}

void tst_QTraceBench::trace()
{
    QFETCH(QString, filename);

    QFile file(filename);
    if (!file.exists()) {
        qWarning() << "Missing file" << filename;
        return;
    }

    ReplayWidget widget(filename);

    if (widget.updates.isEmpty()) {
        qWarning() << "No trace updates" << filename;
        return;
    }

    widget.show();
    QTest::qWaitForWindowShown(&widget);

    while (!widget.done()) {
        widget.updateRect();
        QApplication::processEvents();
    }

    QTest::setBenchmarkResult(widget.result(), QTest::WalltimeMilliseconds);
}

QTEST_MAIN(tst_QTraceBench)
#include "tst_qtracebench.moc"
<commit_msg>Removed redundant debug output from trace benchmark.<commit_after>/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, 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.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include <qtest.h>

#include <QtGui>

#include <private/qpaintengineex_p.h>
#include <private/qpaintbuffer_p.h>

//TESTED_FILES=

class ReplayWidget : public QWidget
{
    Q_OBJECT
public:
    ReplayWidget(const QString &filename);

    void paintEvent(QPaintEvent *event);
    void resizeEvent(QResizeEvent *event);

    bool done() const { return m_done; }
    qreal result() const { return m_result; }

public slots:
    void updateRect();

public:
    QList<QRegion> updates;
    QPaintBuffer buffer;

    int currentFrame;
    int currentIteration;
    QTime timer;

    QList<uint> visibleUpdates;
    QList<uint> iterationTimes;
    QString filename;

    bool m_done;
    qreal m_result;

    uint m_total;
};

void ReplayWidget::updateRect()
{
    if (!visibleUpdates.isEmpty())
        update(updates.at(visibleUpdates.at(currentFrame)));
}

void ReplayWidget::paintEvent(QPaintEvent *)
{
    if (m_done)
        return;

    QPainter p(this);

    // if partial updates don't work
    // p.setClipRegion(frames.at(currentFrame).updateRegion);

    buffer.draw(&p, visibleUpdates.at(currentFrame));

    ++currentFrame;
    if (currentFrame >= visibleUpdates.size()) {
        currentFrame = 0;
        ++currentIteration;

        uint currentElapsed = timer.isNull() ? 0 : timer.elapsed();
        timer.restart();

        m_total += currentElapsed;

        // warm up for at most 5 iterations or half a second
        if (currentIteration >= 5 || m_total >= 500) {
            iterationTimes << currentElapsed;

            if (iterationTimes.size() >= 5) {
                qreal mean = 0;
                qreal stddev = 0;
                uint min = INT_MAX;

                for (int i = 0; i < iterationTimes.size(); ++i) {
                    mean += iterationTimes.at(i);
                    min = qMin(min, iterationTimes.at(i));
                }

                mean /= qreal(iterationTimes.size());

                for (int i = 0; i < iterationTimes.size(); ++i) {
                    qreal delta = iterationTimes.at(i) - mean;
                    stddev += delta * delta;
                }

                stddev = qSqrt(stddev / iterationTimes.size());

                qSort(iterationTimes.begin(), iterationTimes.end());
                uint median = iterationTimes.at(iterationTimes.size() / 2);

                stddev = 100 * stddev / mean;
                // do 100 iterations, break earlier if we spend more than 5 seconds or have a low std deviation after 2 seconds
                if (iterationTimes.size() >= 100 || m_total >= 5000 || (m_total >= 2000 && stddev < 4)) {
                    printf("%s, iterations: %d, frames: %d, min(ms): %d, median(ms): %d, stddev: %f %%, max(fps): %f\n", qPrintable(filename),
                            iterationTimes.size(), visibleUpdates.size(), min, median, stddev, 1000. * visibleUpdates.size() / min);
                    m_result = min;
                    m_done = true;
                    return;
                }
            }
        }
    }
}

void ReplayWidget::resizeEvent(QResizeEvent *event)
{
    visibleUpdates.clear();

    QRect bounds = rect();
    for (int i = 0; i < updates.size(); ++i) {
        if (updates.at(i).intersects(bounds))
            visibleUpdates << i;
    }

    if (visibleUpdates.size() != updates.size())
        printf("Warning: skipped %d frames due to limited resolution\n", updates.size() - visibleUpdates.size());

}

ReplayWidget::ReplayWidget(const QString &filename_)
    : currentFrame(0)
    , currentIteration(0)
    , filename(filename_)
    , m_done(false)
    , m_result(0)
    , m_total(0)
{
    setWindowTitle(filename);
    QFile file(filename);

    if (!file.open(QIODevice::ReadOnly)) {
        printf("Failed to load input file '%s'\n", qPrintable(filename_));
        return;
    }

    QDataStream in(&file);

    char *data;
    uint size;
    in.readBytes(data, size);
    bool isTraceFile = size >= 7 && qstrncmp(data, "qttrace", 7) == 0;
    uint version = 0;
    if (size == 9 && qstrncmp(data, "qttraceV2", 9) == 0) {
        in.setFloatingPointPrecision(QDataStream::SinglePrecision);
        in >> version;
    }

    delete [] data;
    if (!isTraceFile) {
        printf("File '%s' is not a trace file\n", qPrintable(filename_));
        return;
    }

    in >> buffer >> updates;

    resize(buffer.boundingRect().size().toSize());

    setAutoFillBackground(false);
    setAttribute(Qt::WA_NoSystemBackground);
}

class tst_QTraceBench : public QObject
{
    Q_OBJECT

private slots:
    void trace();
    void trace_data();
};

static const QLatin1String prefix(":/traces/");

void tst_QTraceBench::trace_data()
{
    QTest::addColumn<QString>("filename");

    QTest::newRow("basicdrawing") << (prefix + "basicdrawing.trace");
    QTest::newRow("webkit") << (prefix + "webkit.trace");
    QTest::newRow("creator") << (prefix + "creator.trace");
    QTest::newRow("textedit") << (prefix + "textedit.trace");
    QTest::newRow("qmlphoneconcept") << (prefix + "qmlphoneconcept.trace");
    QTest::newRow("qmlsamegame") << (prefix + "qmlsamegame.trace");
}

void tst_QTraceBench::trace()
{
    QFETCH(QString, filename);

    QFile file(filename);
    if (!file.exists()) {
        qWarning() << "Missing file" << filename;
        return;
    }

    ReplayWidget widget(filename);

    if (widget.updates.isEmpty()) {
        qWarning() << "No trace updates" << filename;
        return;
    }

    widget.show();
    QTest::qWaitForWindowShown(&widget);

    while (!widget.done()) {
        widget.updateRect();
        QApplication::processEvents();
    }

    QTest::setBenchmarkResult(widget.result(), QTest::WalltimeMilliseconds);
}

QTEST_MAIN(tst_QTraceBench)
#include "tst_qtracebench.moc"
<|endoftext|>


<commit_before>/// \file uparser.cc

//#define ENABLE_DEBUG_TRACES
#include <libport/compiler.hh>

#include <cassert>
#include <cstdlib>
#include <fstream>
#include <sstream>
#include <string>

#include <libport/foreach.hh>

#include <ast/nary.hh>
#include <ast/print.hh>

#include <parser/parser-impl.hh>
#include <parser/parser-utils.hh>
#include <parser/tweast.hh>
#include <parser/utoken.hh>

#include <kernel/server-timer.hh>

namespace parser
{

  /*-------------.
  | ParserImpl.  |
  `-------------*/

  ParserImpl::ParserImpl()
    : tweast_ (0),
      loc_(),
      synclines_(),
      result_(0)
  {
  }

  void
  ParserImpl::parse_ (std::istream& source)
  {
    TIMER_PUSH("parse");
    passert(*result_, !result_.get());
    result_.reset(new ParseResult);
    yyFlexLexer scanner;
    scanner.switch_streams(&source, 0);
    parser_type p(*this, scanner);
    p.set_debug_level (!!getenv ("YYDEBUG"));
    ECHO("====================== Parse begin");
    result_->status = p.parse();
    ECHO("====================== Parse end: " << res);
    TIMER_POP("parse");
  }

  parse_result_type
  ParserImpl::parse(const std::string& s)
  {
    if (getenv("PARSE"))
      LIBPORT_ECHO("Parsing: " << s);
    std::istringstream is(s);
    parse_(is);
    if (getenv("PARSE"))
      LIBPORT_ECHO("Result: " << *result_);
    return result_;
  }

  parse_result_type
  ParserImpl::parse (Tweast& t)
  {
    // Recursive calls are forbidden.  If we want to relax this
    // constraint, note that we also need to save and restore other
    // member changed during the parsing, such as warnings_ and
    // errors_.  But it is simpler to recurse with the standalone
    // parse functions.
    passert(tweast_, !tweast_);
    tweast_ = &t;
    std::istringstream is(t.input_get());
    parse_(is);
    tweast_ = 0;
    return result_;
  }

  parse_result_type
  ParserImpl::parse_file (const std::string& fn)
  {
    std::ifstream f(fn.c_str());
    if (!f.good())
    {
      // Return an error instead of creating a valid empty ast.
      result_.reset(new ParseResult);
      result_->status = 1;
    }
    else
    {
      // A location pointing to it.
      location_type loc;
      loc.initialize(new libport::Symbol(fn));

      // Exchange with the current location so that we can restore it
      // afterwards (when reading the input flow, we want to be able to
      // restore the cursor after having handled a load command).
      std::swap(loc, loc_);
      ECHO("Parsing file: " << fn);
      parse_(f);
      std::swap(loc, loc_);
    }
    return result_;
  }

  void
  ParserImpl::error(const location_type& l, const std::string& msg)
  {
    result_->error(l, msg);
  }

  void
  ParserImpl::warn(const location_type& l, const std::string& msg)
  {
    result_->warn(l, msg);
  }

}
<commit_msg>More debugging traces.<commit_after>/// \file uparser.cc

//#define ENABLE_DEBUG_TRACES
#include <libport/compiler.hh>

#include <cassert>
#include <cstdlib>
#include <fstream>
#include <sstream>
#include <string>

#include <libport/foreach.hh>

#include <ast/nary.hh>
#include <ast/print.hh>

#include <parser/parser-impl.hh>
#include <parser/parser-utils.hh>
#include <parser/tweast.hh>
#include <parser/utoken.hh>

#include <kernel/server-timer.hh>

namespace parser
{

  /*-------------.
  | ParserImpl.  |
  `-------------*/

  ParserImpl::ParserImpl()
    : tweast_ (0),
      loc_(),
      synclines_(),
      result_(0)
  {
  }

  void
  ParserImpl::parse_ (std::istream& source)
  {
    TIMER_PUSH("parse");
    passert(*result_, !result_.get());
    result_.reset(new ParseResult);
    yyFlexLexer scanner;
    scanner.switch_streams(&source, 0);
    parser_type p(*this, scanner);
    p.set_debug_level (!!getenv ("YYDEBUG"));
    if (p.debug_level())
      LIBPORT_ECHO("====================== Parse begin");
    result_->status = p.parse();
    if (p.debug_level())
      LIBPORT_ECHO("====================== Parse end:" << std::endl
                   << *result_);
    TIMER_POP("parse");
  }

  parse_result_type
  ParserImpl::parse(const std::string& s)
  {
    if (getenv("PARSE"))
      LIBPORT_ECHO("Parsing: " << s);
    std::istringstream is(s);
    parse_(is);
    if (getenv("PARSE"))
      LIBPORT_ECHO("Result: " << *result_);
    return result_;
  }

  parse_result_type
  ParserImpl::parse (Tweast& t)
  {
    // Recursive calls are forbidden.  If we want to relax this
    // constraint, note that we also need to save and restore other
    // member changed during the parsing, such as warnings_ and
    // errors_.  But it is simpler to recurse with the standalone
    // parse functions.
    passert(tweast_, !tweast_);
    tweast_ = &t;
    std::istringstream is(t.input_get());
    parse_(is);
    tweast_ = 0;
    return result_;
  }

  parse_result_type
  ParserImpl::parse_file (const std::string& fn)
  {
    std::ifstream f(fn.c_str());
    if (!f.good())
    {
      // Return an error instead of creating a valid empty ast.
      result_.reset(new ParseResult);
      result_->status = 1;
    }
    else
    {
      // A location pointing to it.
      location_type loc;
      loc.initialize(new libport::Symbol(fn));

      // Exchange with the current location so that we can restore it
      // afterwards (when reading the input flow, we want to be able to
      // restore the cursor after having handled a load command).
      std::swap(loc, loc_);
      ECHO("Parsing file: " << fn);
      parse_(f);
      std::swap(loc, loc_);
    }
    return result_;
  }

  void
  ParserImpl::error(const location_type& l, const std::string& msg)
  {
    result_->error(l, msg);
  }

  void
  ParserImpl::warn(const location_type& l, const std::string& msg)
  {
    result_->warn(l, msg);
  }

}
<|endoftext|>


<commit_before>// Copyright 2014 Ghost Authors. All rights reserved.
// Use of this source code is governed by a ALv2 license that can be
// found in the LICENSE file.

#include "library.h"

#include <vector>

#include "base/files/file_enumerator.h"
#include "base/strings/utf_string_conversions.h"

#include <QtCore/QDebug>
#include <iostream>

static std::vector<Track*> tracks_;

Library::Library() {
}

Library::~Library() {
  // TODO: should tracks_ be vector of scoped_ptr's?
}

void Library::Init(const base::FilePath& path) {
  root_path_ = path;

  // Add all mp3 files found in root_path.
  base::FileEnumerator iter(root_path_, true, base::FileEnumerator::FILES);
  for (base::FilePath name = iter.Next(); !name.empty(); name = iter.Next()) {
    if (name.MatchesExtension(FILE_PATH_LITERAL(".mp3"))) {
      Track* track = new Track(name);
      tracks_.push_back(track);
    }
  }
}

Track* Library::GetTrack(int index) {
  if (index >= 0 && index < (int) tracks_.size()) {
    return tracks_[index];
  }
  return NULL;
}

Track* Library::GetTrackForPlaying(int index) {
  if (index >= 0 && index < (int) tracks_.size()) {
    current_track_ = index;
    return GetCurrentTrack();
  }
  return NULL;
}

Track* Library::GetCurrentTrack() {
  return tracks_[current_track_];
}

int Library::GetNumTracks(void) {
  return tracks_.size();
}

void Library::EndOfStream(void) {
}

void Library::PrintTracks(void) {
  for (std::vector<Track*>::iterator it = tracks_.begin(); it != tracks_.end();
       ++it) {
    Track* track = *it;
#if defined(OS_WIN)
    std::cout << base::WideToUTF8(track->file_path_.value()) << std::endl;
#elif defined(OS_POSIX)
    std::cout << track->file_path_.value() << std::endl;
#endif
  }
}
<commit_msg>- More logging<commit_after>// Copyright 2014 Ghost Authors. All rights reserved.
// Use of this source code is governed by a ALv2 license that can be
// found in the LICENSE file.

#include "library.h"

#include <vector>

#include "base/files/file_enumerator.h"
#include "base/logging.h"
#include "base/strings/utf_string_conversions.h"

static std::vector<Track*> tracks_;

Library::Library() {
}

Library::~Library() {
  // TODO: should tracks_ be vector of scoped_ptr's?
}

void Library::Init(const base::FilePath& path) {
  root_path_ = path;

  // Add all mp3 files found in root_path.
  base::FileEnumerator iter(root_path_, true, base::FileEnumerator::FILES);
  for (base::FilePath name = iter.Next(); !name.empty(); name = iter.Next()) {
    if (name.MatchesExtension(FILE_PATH_LITERAL(".mp3"))) {
      Track* track = new Track(name);
      tracks_.push_back(track);
    }
  }
}

Track* Library::GetTrack(int index) {
  if (index >= 0 && index < (int) tracks_.size()) {
    return tracks_[index];
  }
  return NULL;
}

Track* Library::GetTrackForPlaying(int index) {
  if (index >= 0 && index < (int) tracks_.size()) {
    current_track_ = index;
    return GetCurrentTrack();
  }
  return NULL;
}

Track* Library::GetCurrentTrack() {
  return tracks_[current_track_];
}

int Library::GetNumTracks(void) {
  return tracks_.size();
}

void Library::EndOfStream(void) {
}

void Library::PrintTracks(void) {
  for (std::vector<Track*>::iterator it = tracks_.begin(); it != tracks_.end();
       ++it) {
    Track* track = *it;
#if defined(OS_WIN)
    LOG(INFO) << base::WideToUTF8(track->file_path_.value());
#elif defined(OS_POSIX)
    LOG(INFO) << track->file_path_.value();
#endif
  }
}
<|endoftext|>


<commit_before>// Copyright Howard Hinnant 2007-2010. Distributed under the Boost
// Software License, Version 1.0. (see http://www.boost.org/LICENSE_1_0.txt)

#ifndef SHARED_MUTEX
#define SHARED_MUTEX

#ifndef _LIBCPP_SHARED_LOCK
#define _LIBCPP_SHARED_LOCK
#endif

#include <mutex>
#include <condition_variable>
#include <chrono>
#include <climits>
#include <system_error>

namespace ting {

class shared_mutex
{
    typedef std::mutex              mutex_t;
    typedef std::condition_variable cond_t;
    typedef unsigned                count_t;

    mutex_t mut_;
    cond_t  gate1_;
    cond_t  gate2_;
    count_t state_;

    static const count_t write_entered_ = 1U << (sizeof(count_t)*CHAR_BIT - 1);
    static const count_t n_readers_ = ~write_entered_;

public:
    shared_mutex();
    ~shared_mutex();

    shared_mutex(const shared_mutex&) = delete;
    shared_mutex& operator=(const shared_mutex&) = delete;

// Exclusive ownership

    void lock();
    bool try_lock();
    template <class Rep, class Period>
        bool try_lock_for(const std::chrono::duration<Rep, Period>& rel_time)
        {
            return try_lock_until(std::chrono::steady_clock::now() + rel_time);
        }
    template <class Clock, class Duration>
        bool
        try_lock_until(
                      const std::chrono::time_point<Clock, Duration>& abs_time);
    void unlock();

// Shared ownership

    void lock_shared();
    bool try_lock_shared();
    template <class Rep, class Period>
        bool
        try_lock_shared_for(const std::chrono::duration<Rep, Period>& rel_time)
        {
            return try_lock_shared_until(std::chrono::steady_clock::now() +
                                         rel_time);
        }
    template <class Clock, class Duration>
        bool
        try_lock_shared_until(
                      const std::chrono::time_point<Clock, Duration>& abs_time);
    void unlock_shared();
};

template <class Clock, class Duration>
bool
shared_mutex::try_lock_until(
                       const std::chrono::time_point<Clock, Duration>& abs_time)
{
    std::unique_lock<mutex_t> lk(mut_);
    if (state_ & write_entered_)
    {
        while (true)
        {
            std::cv_status status = gate1_.wait_until(lk, abs_time);
            if ((state_ & write_entered_) == 0)
                break;
            if (status == std::cv_status::timeout)
                return false;
        }
    }
    state_ |= write_entered_;
    if (state_ & n_readers_)
    {
        while (true)
        {
            std::cv_status status = gate2_.wait_until(lk, abs_time);
            if ((state_ & n_readers_) == 0)
                break;
            if (status == std::cv_status::timeout)
            {
                state_ &= ~write_entered_;
                return false;
            }
        }
    }
    return true;
}

template <class Clock, class Duration>
bool
shared_mutex::try_lock_shared_until(
                       const std::chrono::time_point<Clock, Duration>& abs_time)
{
    std::unique_lock<mutex_t> lk(mut_);
    if ((state_ & write_entered_) || (state_ & n_readers_) == n_readers_)
    {
        while (true)
        {
            std::cv_status status = gate1_.wait_until(lk, abs_time);
            if ((state_ & write_entered_) == 0 &&
                                             (state_ & n_readers_) < n_readers_)
                break;
            if (status == std::cv_status::timeout)
                return false;
        }
    }
    count_t num_readers = (state_ & n_readers_) + 1;
    state_ &= ~n_readers_;
    state_ |= num_readers;
    return true;
}

class upgrade_mutex
{
    typedef std::mutex              mutex_t;
    typedef std::condition_variable cond_t;
    typedef unsigned                count_t;

    mutex_t mut_;
    cond_t  gate1_;
    cond_t  gate2_;
    count_t state_;

    static const unsigned write_entered_ = 1U << (sizeof(count_t)*CHAR_BIT - 1);
    static const unsigned upgradable_entered_ = write_entered_ >> 1;
    static const unsigned n_readers_ = ~(write_entered_ | upgradable_entered_);

public:

    upgrade_mutex();
    ~upgrade_mutex();

    upgrade_mutex(const upgrade_mutex&) = delete;
    upgrade_mutex& operator=(const upgrade_mutex&) = delete;

// Exclusive ownership

    void lock();
    bool try_lock();
    template <class Rep, class Period>
        bool try_lock_for(const std::chrono::duration<Rep, Period>& rel_time)
        {
            return try_lock_until(std::chrono::steady_clock::now() + rel_time);
        }
    template <class Clock, class Duration>
        bool
        try_lock_until(
                      const std::chrono::time_point<Clock, Duration>& abs_time);
    void unlock();

// Shared ownership

    void lock_shared();
    bool try_lock_shared();
    template <class Rep, class Period>
        bool
        try_lock_shared_for(const std::chrono::duration<Rep, Period>& rel_time)
        {
            return try_lock_shared_until(std::chrono::steady_clock::now() +
                                         rel_time);
        }
    template <class Clock, class Duration>
        bool
        try_lock_shared_until(
                      const std::chrono::time_point<Clock, Duration>& abs_time);
    void unlock_shared();

// Upgrade ownership

    void lock_upgrade();
    bool try_lock_upgrade();
    template <class Rep, class Period>
        bool
        try_lock_upgrade_for(
                            const std::chrono::duration<Rep, Period>& rel_time)
        {
            return try_lock_upgrade_until(std::chrono::steady_clock::now() +
                                         rel_time);
        }
    template <class Clock, class Duration>
        bool
        try_lock_upgrade_until(
                      const std::chrono::time_point<Clock, Duration>& abs_time);
    void unlock_upgrade();

// Shared <-> Exclusive

    bool try_unlock_shared_and_lock();
    template <class Rep, class Period>
        bool
        try_unlock_shared_and_lock_for(
                            const std::chrono::duration<Rep, Period>& rel_time)
        {
            return try_unlock_shared_and_lock_until(
                                   std::chrono::steady_clock::now() + rel_time);
        }
    template <class Clock, class Duration>
        bool
        try_unlock_shared_and_lock_until(
                      const std::chrono::time_point<Clock, Duration>& abs_time);
    void unlock_and_lock_shared();

// Shared <-> Upgrade

    bool try_unlock_shared_and_lock_upgrade();
    template <class Rep, class Period>
        bool
        try_unlock_shared_and_lock_upgrade_for(
                            const std::chrono::duration<Rep, Period>& rel_time)
        {
            return try_unlock_shared_and_lock_upgrade_until(
                                   std::chrono::steady_clock::now() + rel_time);
        }
    template <class Clock, class Duration>
        bool
        try_unlock_shared_and_lock_upgrade_until(
                      const std::chrono::time_point<Clock, Duration>& abs_time);
    void unlock_upgrade_and_lock_shared();

// Upgrade <-> Exclusive

    void unlock_upgrade_and_lock();
    bool try_unlock_upgrade_and_lock();
    template <class Rep, class Period>
        bool
        try_unlock_upgrade_and_lock_for(
                            const std::chrono::duration<Rep, Period>& rel_time)
        {
            return try_unlock_upgrade_and_lock_until(
                                   std::chrono::steady_clock::now() + rel_time);
        }
    template <class Clock, class Duration>
        bool
        try_unlock_upgrade_and_lock_until(
                      const std::chrono::time_point<Clock, Duration>& abs_time);
    void unlock_and_lock_upgrade();
};

template <class Clock, class Duration>
bool
upgrade_mutex::try_lock_until(
                       const std::chrono::time_point<Clock, Duration>& abs_time)
{
    std::unique_lock<mutex_t> lk(mut_);
    if (state_ & (write_entered_ | upgradable_entered_))
    {
        while (true)
        {
            std::cv_status status = gate1_.wait_until(lk, abs_time);
            if ((state_ & (write_entered_ | upgradable_entered_)) == 0)
                break;
            if (status == std::cv_status::timeout)
                return false;
        }
    }
    state_ |= write_entered_;
    if (state_ & n_readers_)
    {
        while (true)
        {
            std::cv_status status = gate2_.wait_until(lk, abs_time);
            if ((state_ & n_readers_) == 0)
                break;
            if (status == std::cv_status::timeout)
            {
                state_ &= ~write_entered_;
                return false;
            }
        }
    }
    return true;
}

template <class Clock, class Duration>
bool
upgrade_mutex::try_lock_shared_until(
                       const std::chrono::time_point<Clock, Duration>& abs_time)
{
    std::unique_lock<mutex_t> lk(mut_);
    if ((state_ & write_entered_) || (state_ & n_readers_) == n_readers_)
    {
        while (true)
        {
            std::cv_status status = gate1_.wait_until(lk, abs_time);
            if ((state_ & write_entered_) == 0 &&
                                             (state_ & n_readers_) < n_readers_)
                break;
            if (status == std::cv_status::timeout)
                return false;
        }
    }
    count_t num_readers = (state_ & n_readers_) + 1;
    state_ &= ~n_readers_;
    state_ |= num_readers;
    return true;
}

template <class Clock, class Duration>
bool
upgrade_mutex::try_lock_upgrade_until(
                       const std::chrono::time_point<Clock, Duration>& abs_time)
{
    std::unique_lock<mutex_t> lk(mut_);
    if ((state_ & (write_entered_ | upgradable_entered_)) ||
        (state_ & n_readers_) == n_readers_)
    {
        while (true)
        {
            std::cv_status status = gate1_.wait_until(lk, abs_time);
            if ((state_ & (write_entered_ | upgradable_entered_)) == 0 &&
                                             (state_ & n_readers_) < n_readers_)
                break;
            if (status == std::cv_status::timeout)
                return false;
        }
    }
    count_t num_readers = (state_ & n_readers_) + 1;
    state_ &= ~n_readers_;
    state_ |= upgradable_entered_ | num_readers;
    return true;
}

template <class Clock, class Duration>
bool
upgrade_mutex::try_unlock_shared_and_lock_until(
                       const std::chrono::time_point<Clock, Duration>& abs_time)
{
    std::unique_lock<mutex_t> lk(mut_);
    if (state_ != 1)
    {
        while (true)
        {
            std::cv_status status = gate2_.wait_until(lk, abs_time);
            if (state_ == 1)
                break;
            if (status == std::cv_status::timeout)
                return false;
        }
    }
    state_ = write_entered_;
    return true;
}

template <class Clock, class Duration>
bool
upgrade_mutex::try_unlock_shared_and_lock_upgrade_until(
                       const std::chrono::time_point<Clock, Duration>& abs_time)
{
    std::unique_lock<mutex_t> lk(mut_);
    if ((state_ & (write_entered_ | upgradable_entered_)) != 0)
    {
        while (true)
        {
            std::cv_status status = gate2_.wait_until(lk, abs_time);
            if ((state_ & (write_entered_ | upgradable_entered_)) == 0)
                break;
            if (status == std::cv_status::timeout)
                return false;
        }
    }
    state_ |= upgradable_entered_;
    return true;
}

template <class Clock, class Duration>
bool
upgrade_mutex::try_unlock_upgrade_and_lock_until(
                       const std::chrono::time_point<Clock, Duration>& abs_time)
{
    std::unique_lock<mutex_t> lk(mut_);
    if ((state_ & n_readers_) != 1)
    {
        while (true)
        {
            std::cv_status status = gate2_.wait_until(lk, abs_time);
            if ((state_ & n_readers_) == 1)
                break;
            if (status == std::cv_status::timeout)
                return false;
        }
    }
    state_ = write_entered_;
    return true;
}

template <class Mutex> class upgrade_lock;

template <class Mutex>
class shared_lock
{
public:
    typedef Mutex mutex_type;

private:
    mutex_type* m_;
    bool owns_;

    struct __nat {int _;};

public:
    shared_lock()
        : m_(nullptr), owns_(false) {}

    explicit shared_lock(mutex_type& m)
        : m_(&m), owns_(true)
        {m_->lock_shared();}

    shared_lock(mutex_type& m, std::defer_lock_t)
        : m_(&m), owns_(false) {}

    shared_lock(mutex_type& m, std::try_to_lock_t)
        : m_(&m), owns_(m.try_lock_shared()) {}

    shared_lock(mutex_type& m, std::adopt_lock_t)
        : m_(&m), owns_(true) {}

    template <class Clock, class Duration>
        shared_lock(mutex_type& m,
                    const std::chrono::time_point<Clock, Duration>& abs_time)
        : m_(&m), owns_(m.try_lock_shared_until(abs_time)) {}
    template <class Rep, class Period>
        shared_lock(mutex_type& m,
                    const std::chrono::duration<Rep, Period>& rel_time)
        : m_(&m), owns_(m.try_lock_shared_for(rel_time)) {}

    ~shared_lock()
    {
        if (owns_)
            m_->unlock_shared();
    }

    shared_lock(shared_lock const&) = delete;
    shared_lock& operator=(shared_lock const&) = delete;

    shared_lock(shared_lock&& sl)
        : m_(sl.m_), owns_(sl.owns_)
        {sl.m_ = nullptr; sl.owns_ = false;}

    shared_lock& operator=(shared_lock&& sl)
    {
        if (owns_)
            m_->unlock_shared();
        m_ = sl.m_;
        owns_ = sl.owns_;
        sl.m_ = nullptr;
        sl.owns_ = false;
        return *this;
    }

    explicit shared_lock(upgrade_lock<mutex_type>&& ul)
        : m_(ul.mutex()), owns_(ul.owns_lock())
    {
        if (owns_)
            m_->unlock_upgrade_and_lock_shared();
        ul.release();
    }

    explicit shared_lock(std::unique_lock<mutex_type>&& ul)
        : m_(ul.mutex()), owns_(ul.owns_lock())
    {
        if (owns_)
            m_->unlock_and_lock_shared();
        ul.release();
    }

    void lock();
    bool try_lock();
    template <class Rep, class Period>
        bool try_lock_for(const std::chrono::duration<Rep, Period>& rel_time)
        {
            return try_lock_until(std::chrono::steady_clock::now() + rel_time);
        }
    template <class Clock, class Duration>
        bool
        try_lock_until(
                      const std::chrono::time_point<Clock, Duration>& abs_time);
    void unlock();

    void swap(shared_lock&& u)
    {
        std::swap(m_, u.m_);
        std::swap(owns_, u.owns_);
    }

    mutex_type* release()
    {
        mutex_type* r = m_;
        m_ = nullptr;
        owns_ = false;
        return r;
    }
    bool owns_lock() const {return owns_;}
    operator int __nat::* () const {return owns_ ? &__nat::_ : 0;}
    mutex_type* mutex() const {return m_;}

};

template <class Mutex>
void
shared_lock<Mutex>::lock()
{
    if (m_ == nullptr)
        throw std::system_error(std::error_code(EPERM, std::system_category()),
                                    "shared_lock::lock: references null mutex");
    if (owns_)
        throw std::system_error(std::error_code(EDEADLK, std::system_category()),
                                           "shared_lock::lock: already locked");
    m_->lock_shared();
    owns_ = true;
}

template <class Mutex>
bool
shared_lock<Mutex>::try_lock()
{
    if (m_ == nullptr)
        throw std::system_error(std::error_code(EPERM, std::system_category()),
                                "shared_lock::try_lock: references null mutex");
    if (owns_)
        throw std::system_error(std::error_code(EDEADLK, std::system_category()),
                                       "shared_lock::try_lock: already locked");
    owns_ = m_->try_lock_shared();
    return owns_;
}

template <class Mutex>
template <class Clock, class Duration>
bool
shared_lock<Mutex>::try_lock_until(
                       const std::chrono::time_point<Clock, Duration>& abs_time)
{
    if (m_ == nullptr)
        throw std::system_error(std::error_code(EPERM, std::system_category()),
                          "shared_lock::try_lock_until: references null mutex");
    if (owns_)
        throw std::system_error(std::error_code(EDEADLK, std::system_category()),
                                 "shared_lock::try_lock_until: already locked");
    owns_ = m_->try_lock_shared_until(abs_time);
    return owns_;
}

template <class Mutex>
void
shared_lock<Mutex>::unlock()
{
    if (!owns_)
        throw std::system_error(std::error_code(EPERM, std::system_category()),
                                "shared_lock::unlock: not locked");
    m_->unlock_shared();
    owns_ = false;
}

template <class Mutex>
inline
void
swap(shared_lock<Mutex>&  x, shared_lock<Mutex>&  y)
{
    x.swap(y);
}

template <class Mutex>
class upgrade_lock
{
public:
    typedef Mutex mutex_type;

private:
    mutex_type* m_;
    bool owns_;

    struct __nat {int _;};

public:
    upgrade_lock()
        : m_(nullptr), owns_(false) {}

    explicit upgrade_lock(mutex_type& m)
        : m_(&m), owns_(true)
        {m_->lock_upgrade();}

    upgrade_lock(mutex_type& m, std::defer_lock_t)
        : m_(&m), owns_(false) {}

    upgrade_lock(mutex_type& m, std::try_to_lock_t)
        : m_(&m), owns_(m.try_lock_upgrade()) {}

    upgrade_lock(mutex_type& m, std::adopt_lock_t)
        : m_(&m), owns_(true) {}

    template <class Clock, class Duration>
        upgrade_lock(mutex_type& m,
                    const std::chrono::time_point<Clock, Duration>& abs_time)
        : m_(&m), owns_(m.try_lock_upgrade_until(abs_time)) {}
    template <class Rep, class Period>
        upgrade_lock(mutex_type& m,
                    const std::chrono::duration<Rep, Period>& rel_time)
        : m_(&m), owns_(m.try_lock_upgrade_for(rel_time)) {}

    ~upgrade_lock()
    {
        if (owns_)
            m_->unlock_upgrade();
    }

    upgrade_lock(upgrade_lock const&) = delete;
    upgrade_lock& operator=(upgrade_lock const&) = delete;

    upgrade_lock(upgrade_lock&& ul)
        : m_(ul.m_), owns_(ul.owns_)
        {
            ul.m_ = nullptr;
            ul.owns_ = false;
        }

    upgrade_lock& operator=(upgrade_lock&& ul)
    {
        if (owns_)
            m_->unlock_upgrade();
        m_ = ul.m_;
        owns_ = ul.owns_;
        ul.m_ = nullptr;
        ul.owns_ = false;
        return *this;
    }

    upgrade_lock(shared_lock<mutex_type>&& sl, std::try_to_lock_t)
        : m_(nullptr), owns_(false)
    {
        if (sl.owns_lock())
        {
            if (sl.mutex()->try_unlock_shared_and_lock_upgrade())
            {
                m_ = sl.release();
                owns_ = true;
            }
        }
        else
            m_ = sl.release();
    }

    template <class Clock, class Duration>
        upgrade_lock(shared_lock<mutex_type>&& sl,
                     const std::chrono::time_point<Clock, Duration>& abs_time)
        : m_(nullptr), owns_(false)
    {
        if (sl.owns_lock())
        {
            if (sl.mutex()->try_unlock_shared_and_lock_upgrade_until(abs_time))
            {
                m_ = sl.release();
                owns_ = true;
            }
        }
        else
            m_ = sl.release();
    }

    template <class Rep, class Period>
        upgrade_lock(shared_lock<mutex_type>&& sl,
                     const std::chrono::duration<Rep, Period>& rel_time)
        : m_(nullptr), owns_(false)
    {
        if (sl.owns_lock())
        {
            if (sl.mutex()->try_unlock_shared_and_lock_upgrade_for(rel_time))
            {
                m_ = sl.release();
                owns_ = true;
            }
        }
        else
            m_ = sl.release();
    }

    explicit upgrade_lock(std::unique_lock<mutex_type>&& ul)
        : m_(ul.mutex()), owns_(ul.owns_lock())
    {
        if (owns_)
            m_->unlock_and_lock_upgrade();
        ul.release();
    }

    void lock();
    bool try_lock();
    template <class Rep, class Period>
        bool try_lock_for(const std::chrono::duration<Rep, Period>& rel_time)
        {
            return try_lock_until(std::chrono::steady_clock::now() + rel_time);
        }
    template <class Clock, class Duration>
        bool
        try_lock_until(
                      const std::chrono::time_point<Clock, Duration>& abs_time);
    void unlock();

    void swap(upgrade_lock&& u)
    {
        std::swap(m_, u.m_);
        std::swap(owns_, u.owns_);
    }

    mutex_type* release()
    {
        mutex_type* r = m_;
        m_ = 0;
        owns_ = false;
        return r;
    }

    bool owns_lock() const {return owns_;}
    operator int __nat::* () const {return owns_ ? &__nat::_ : 0;}
    mutex_type* mutex() const {return m_;}
};

template <class Mutex>
void
upgrade_lock<Mutex>::lock()
{
    if (m_ == nullptr)
        throw std::system_error(std::error_code(EPERM, std::system_category()),
                                   "upgrade_lock::lock: references null mutex");
    if (owns_)
        throw std::system_error(std::error_code(EDEADLK, std::system_category()),
                                          "upgrade_lock::lock: already locked");
    m_->lock_upgrade();
    owns_ = true;
}

template <class Mutex>
bool
upgrade_lock<Mutex>::try_lock()
{
    if (m_ == nullptr)
        throw std::system_error(std::error_code(EPERM, std::system_category()),
                               "upgrade_lock::try_lock: references null mutex");
    if (owns_)
        throw std::system_error(std::error_code(EDEADLK, std::system_category()),
                                      "upgrade_lock::try_lock: already locked");
    owns_ = m_->try_lock_upgrade();
    return owns_;
}

template <class Mutex>
template <class Clock, class Duration>
bool
upgrade_lock<Mutex>::try_lock_until(
                       const std::chrono::time_point<Clock, Duration>& abs_time)
{
    if (m_ == nullptr)
        throw std::system_error(std::error_code(EPERM, std::system_category()),
                         "upgrade_lock::try_lock_until: references null mutex");
    if (owns_)
        throw std::system_error(std::error_code(EDEADLK, std::system_category()),
                                "upgrade_lock::try_lock_until: already locked");
    owns_ = m_->try_lock_upgrade_until(abs_time);
    return owns_;
}

template <class Mutex>
void
upgrade_lock<Mutex>::unlock()
{
    if (!owns_)
        throw std::system_error(std::error_code(EPERM, std::system_category()),
                                "upgrade_lock::unlock: not locked");
    m_->unlock_upgrade();
    owns_ = false;
}

template <class Mutex>
inline
void
swap(upgrade_lock<Mutex>&  x, upgrade_lock<Mutex>&  y)
{
    x.swap(y);
}

template <class ToLock, class FromLock>
class transfer_lock
{
    ToLock to_lock_;
    FromLock& from_lock_;

public:
    explicit transfer_lock(FromLock& fl)
        : to_lock_(std::move(fl)),
          from_lock_(fl) {}
    ~transfer_lock() {from_lock_ = FromLock(std::move(to_lock_));}

    transfer_lock(const transfer_lock&) = delete;
    transfer_lock& operator=(const transfer_lock&) = delete;
};

}  // ting

#endif<commit_msg>remove unused<commit_after><|endoftext|>


<commit_before>/*
    Copyright (C) 2011 vlc-phonon AUTHORS

    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, see <http://www.gnu.org/licenses/>.
*/

#include "libvlc.h"

#include <QtCore/QByteArray>
#include <QtCore/QCoreApplication>
#include <QtCore/QDebug>
#include <QtCore/QDir>
#include <QtCore/QLibrary>
#include <QtCore/QSettings>
#include <QtCore/QString>
#include <QtCore/QStringBuilder>
#include <QtCore/QVarLengthArray>

#include <vlc/libvlc.h>

#include "debug.h"

LibVLC *LibVLC::self;

LibVLC::LibVLC() :
    m_vlcInstance(0)
{
}

LibVLC::~LibVLC()
{
    libvlc_release(m_vlcInstance);
    vlcUnload();
    self = 0;
}

bool LibVLC::init()
{
    Q_ASSERT_X(!self, "LibVLC", "there should be only one LibVLC object");
    LibVLC::self = new LibVLC;

    QString path = self->vlcPath();
    if (!path.isEmpty()) {
        QList<QByteArray> args;

        QString pluginsPath = QLatin1Literal("--plugin-path=") %
                QDir::toNativeSeparators(QFileInfo(self->vlcPath()).dir().path());
#if defined(Q_OS_UNIX)
        pluginsPath.append("/vlc");
#elif defined(Q_OS_WIN)
        pluginsPath.append("\\plugins");
#endif
        args << QFile::encodeName(pluginsPath);

        // Ends up as something like $HOME/.config/Phonon/vlc.conf
        const QString configFileName = QSettings("Phonon", "vlc").fileName();
        if (QFile::exists(configFileName)) {
            args << QByteArray("--config=").append(QFile::encodeName(configFileName));
        }

        int debugLevel = 3 - (int) Debug::minimumDebugLevel();
        if (debugLevel > 0) {
            args << QByteArray("--verbose=").append(QString::number(debugLevel));
            args << QByteArray("--extraintf=logger");
#ifdef Q_WS_WIN
            QDir logFilePath(QString(qgetenv("APPDATA")).append("/vlc"));
#else
            QDir logFilePath(QDir::homePath().append("/.vlc"));
#endif //Q_WS_WIN
            logFilePath.mkdir("log");
            const QString logFile = logFilePath.path()
                    .append("/log/vlc-log-")
                    .append(QString::number(qApp->applicationPid()))
                    .append(".txt");
            args << QByteArray("--logfile=").append(QFile::encodeName(QDir::toNativeSeparators(logFile)));
        }

        args << "--reset-plugins-cache";
        args << "--no-media-library";
        args << "--no-osd";
        args << "--no-stats";
        args << "--no-video-title-show";
        args << "--album-art=0";
        args << "--no-xlib";

#ifndef Q_OS_MAC
        args << "--no-one-instance";
#endif

        // Build const char* array
        QVarLengthArray<const char*, 64> vlcArgs(args.size());
        for (int i = 0; i < args.size(); ++i) {
            vlcArgs[i] = args.at(i).constData();
        }

        // Create and initialize a libvlc instance (it should be done only once)
        self->m_vlcInstance = libvlc_new(vlcArgs.size(), vlcArgs.constData());
        if (!self->m_vlcInstance) {
            fatal() << "libVLC:" << LibVLC::errorMessage();
            return false;
        }
        return true;
    }
    return false;
}

const char *LibVLC::errorMessage()
{
    return libvlc_errmsg();
}

#if defined(Q_OS_UNIX)
bool LibVLC::libGreaterThan(const QString &lhs, const QString &rhs)
{
    const QStringList lhsparts = lhs.split(QLatin1Char('.'));
    const QStringList rhsparts = rhs.split(QLatin1Char('.'));
    Q_ASSERT(lhsparts.count() > 1 && rhsparts.count() > 1);

    for (int i = 1; i < rhsparts.count(); ++i) {
        if (lhsparts.count() <= i) {
            // left hand side is shorter, so it's less than rhs
            return false;
        }

        bool ok = false;
        int b = 0;
        int a = lhsparts.at(i).toInt(&ok);
        if (ok) {
            b = rhsparts.at(i).toInt(&ok);
        }
        if (ok) {
            // both toInt succeeded
            if (a == b) {
                continue;
            }
            return a > b;
        } else {
            // compare as strings;
            if (lhsparts.at(i) == rhsparts.at(i)) {
                continue;
            }
            return lhsparts.at(i) > rhsparts.at(i);
        }
    }

    // they compared strictly equally so far
    // lhs cannot be less than rhs
    return true;
}
#endif

QStringList LibVLC::findAllLibVlcPaths()
{
    QStringList paths;

#ifdef Q_OS_UNIX
    paths = QString::fromLatin1(qgetenv("LD_LIBRARY_PATH"))
            .split(QLatin1Char(':'), QString::SkipEmptyParts);
    paths << QLatin1String(PHONON_LIB_INSTALL_DIR) << QLatin1String("/usr/lib") << QLatin1String("/usr/local/lib");

#if defined(Q_WS_MAC)
    paths
            << QCoreApplication::applicationDirPath()
            << QCoreApplication::applicationDirPath() % QLatin1Literal("/../Frameworks")
            << QCoreApplication::applicationDirPath() % QLatin1Literal("/../PlugIns")
            << QCoreApplication::applicationDirPath() % QLatin1Literal("/lib");
#endif

    QStringList foundVlcs;
    foreach (const QString & path, paths) {
        QDir dir = QDir(path);
        QStringList entryList = dir.entryList(QStringList() << QLatin1String("libvlc.*"), QDir::Files);

        qSort(entryList.begin(), entryList.end(), LibVLC::libGreaterThan);
        foreach(const QString & entry, entryList) {
            if (entry.contains(".debug")) {
                continue;
            }
            foundVlcs << path % QLatin1Char('/') % entry;
        }
    }

    return foundVlcs;
#elif defined(Q_OS_WIN)
    // Current application path has highest priority.
    // Application could be delivered with own copy of qt, phonon, LibVLC, vlc and vlc plugins.
    QString appDirVlc =
            QDir::toNativeSeparators(QCoreApplication::applicationDirPath()
                                     % QLatin1Char('\\')
                                     % QLatin1Literal("libvlc.dll"));
    if (QFile::exists(appDirVlc)) {
        paths << appDirVlc;
    }

    // Read VLC version and installation directory from Windows registry
    QSettings settings(QSettings::SystemScope, "VideoLAN", "VLC");
    QString vlcVersion = settings.value("Version").toString();
    QString vlcInstallDir = settings.value("InstallDir").toString();
    if (vlcVersion.startsWith(QLatin1String("1.1")) && !vlcInstallDir.isEmpty()) {
        paths << vlcInstallDir % QLatin1Char('\\') % QLatin1Literal("libvlc.dll");
        return paths;
    } else {
        //If nothing is found in the registry try %PATH%
        QStringList searchPaths = QString::fromLatin1(qgetenv("PATH"))
                                  .split(QLatin1Char(';'), QString::SkipEmptyParts);

        QStringList foundVlcs;
        foreach(const QString & sp, searchPaths) {
            QDir dir = QDir(sp);
            QStringList entryList = dir.entryList(QStringList() << QLatin1String("libvlc.dll"), QDir::Files);
            foreach(const QString & entry, entryList){
                foundVlcs << sp % QLatin1Char('\\') % entry;
            }
        }
        paths << foundVlcs;
        return paths;
    }
#endif
}

QString LibVLC::vlcPath()
{
    static QString path;
    if (!path.isEmpty()) {
        return path;
    }

    m_vlcLibrary = new QLibrary();
    QStringList paths = LibVLC::findAllLibVlcPaths();
    foreach(path, paths) {
        m_vlcLibrary->setFileName(path);

        if (!m_vlcLibrary->resolve("libvlc_exception_init")) { //"libvlc_exception_init" not contained in 1.1+
            return path;
        } else {
            debug() << "Cannot resolve the symbol or load VLC library";
        }
        warning() << m_vlcLibrary->errorString();
    }

    vlcUnload();

    return QString();
}

void LibVLC::vlcUnload()
{
    m_vlcLibrary->unload();
    delete m_vlcLibrary;
    m_vlcLibrary = 0;
}
<commit_msg>Consider also lib64 directories when looking for libvlc<commit_after>/*
    Copyright (C) 2011 vlc-phonon AUTHORS

    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, see <http://www.gnu.org/licenses/>.
*/

#include "libvlc.h"

#include <QtCore/QByteArray>
#include <QtCore/QCoreApplication>
#include <QtCore/QDebug>
#include <QtCore/QDir>
#include <QtCore/QLibrary>
#include <QtCore/QSettings>
#include <QtCore/QString>
#include <QtCore/QStringBuilder>
#include <QtCore/QVarLengthArray>

#include <vlc/libvlc.h>

#include "debug.h"

LibVLC *LibVLC::self;

LibVLC::LibVLC() :
    m_vlcInstance(0)
{
}

LibVLC::~LibVLC()
{
    libvlc_release(m_vlcInstance);
    vlcUnload();
    self = 0;
}

bool LibVLC::init()
{
    Q_ASSERT_X(!self, "LibVLC", "there should be only one LibVLC object");
    LibVLC::self = new LibVLC;

    QString path = self->vlcPath();
    if (!path.isEmpty()) {
        QList<QByteArray> args;

        QString pluginsPath = QLatin1Literal("--plugin-path=") %
                QDir::toNativeSeparators(QFileInfo(self->vlcPath()).dir().path());
#if defined(Q_OS_UNIX)
        pluginsPath.append("/vlc");
#elif defined(Q_OS_WIN)
        pluginsPath.append("\\plugins");
#endif
        args << QFile::encodeName(pluginsPath);

        // Ends up as something like $HOME/.config/Phonon/vlc.conf
        const QString configFileName = QSettings("Phonon", "vlc").fileName();
        if (QFile::exists(configFileName)) {
            args << QByteArray("--config=").append(QFile::encodeName(configFileName));
        }

        int debugLevel = 3 - (int) Debug::minimumDebugLevel();
        if (debugLevel > 0) {
            args << QByteArray("--verbose=").append(QString::number(debugLevel));
            args << QByteArray("--extraintf=logger");
#ifdef Q_WS_WIN
            QDir logFilePath(QString(qgetenv("APPDATA")).append("/vlc"));
#else
            QDir logFilePath(QDir::homePath().append("/.vlc"));
#endif //Q_WS_WIN
            logFilePath.mkdir("log");
            const QString logFile = logFilePath.path()
                    .append("/log/vlc-log-")
                    .append(QString::number(qApp->applicationPid()))
                    .append(".txt");
            args << QByteArray("--logfile=").append(QFile::encodeName(QDir::toNativeSeparators(logFile)));
        }

        args << "--reset-plugins-cache";
        args << "--no-media-library";
        args << "--no-osd";
        args << "--no-stats";
        args << "--no-video-title-show";
        args << "--album-art=0";
        args << "--no-xlib";

#ifndef Q_OS_MAC
        args << "--no-one-instance";
#endif

        // Build const char* array
        QVarLengthArray<const char*, 64> vlcArgs(args.size());
        for (int i = 0; i < args.size(); ++i) {
            vlcArgs[i] = args.at(i).constData();
        }

        // Create and initialize a libvlc instance (it should be done only once)
        self->m_vlcInstance = libvlc_new(vlcArgs.size(), vlcArgs.constData());
        if (!self->m_vlcInstance) {
            fatal() << "libVLC:" << LibVLC::errorMessage();
            return false;
        }
        return true;
    }
    return false;
}

const char *LibVLC::errorMessage()
{
    return libvlc_errmsg();
}

#if defined(Q_OS_UNIX)
bool LibVLC::libGreaterThan(const QString &lhs, const QString &rhs)
{
    const QStringList lhsparts = lhs.split(QLatin1Char('.'));
    const QStringList rhsparts = rhs.split(QLatin1Char('.'));
    Q_ASSERT(lhsparts.count() > 1 && rhsparts.count() > 1);

    for (int i = 1; i < rhsparts.count(); ++i) {
        if (lhsparts.count() <= i) {
            // left hand side is shorter, so it's less than rhs
            return false;
        }

        bool ok = false;
        int b = 0;
        int a = lhsparts.at(i).toInt(&ok);
        if (ok) {
            b = rhsparts.at(i).toInt(&ok);
        }
        if (ok) {
            // both toInt succeeded
            if (a == b) {
                continue;
            }
            return a > b;
        } else {
            // compare as strings;
            if (lhsparts.at(i) == rhsparts.at(i)) {
                continue;
            }
            return lhsparts.at(i) > rhsparts.at(i);
        }
    }

    // they compared strictly equally so far
    // lhs cannot be less than rhs
    return true;
}
#endif

QStringList LibVLC::findAllLibVlcPaths()
{
    QStringList paths;

#ifdef Q_OS_UNIX
    paths = QString::fromLatin1(qgetenv("LD_LIBRARY_PATH"))
            .split(QLatin1Char(':'), QString::SkipEmptyParts);
    paths << QLatin1String(PHONON_LIB_INSTALL_DIR) << QLatin1String("/usr/lib") << QLatin1String("/usr/local/lib");
    paths << QLatin1String("/usr/lib64") << QLatin1String("/usr/local/lib64");

#if defined(Q_WS_MAC)
    paths
            << QCoreApplication::applicationDirPath()
            << QCoreApplication::applicationDirPath() % QLatin1Literal("/../Frameworks")
            << QCoreApplication::applicationDirPath() % QLatin1Literal("/../PlugIns")
            << QCoreApplication::applicationDirPath() % QLatin1Literal("/lib");
#endif

    QStringList foundVlcs;
    foreach (const QString & path, paths) {
        QDir dir = QDir(path);
        QStringList entryList = dir.entryList(QStringList() << QLatin1String("libvlc.*"), QDir::Files);

        qSort(entryList.begin(), entryList.end(), LibVLC::libGreaterThan);
        foreach(const QString & entry, entryList) {
            if (entry.contains(".debug")) {
                continue;
            }
            foundVlcs << path % QLatin1Char('/') % entry;
        }
    }

    return foundVlcs;
#elif defined(Q_OS_WIN)
    // Current application path has highest priority.
    // Application could be delivered with own copy of qt, phonon, LibVLC, vlc and vlc plugins.
    QString appDirVlc =
            QDir::toNativeSeparators(QCoreApplication::applicationDirPath()
                                     % QLatin1Char('\\')
                                     % QLatin1Literal("libvlc.dll"));
    if (QFile::exists(appDirVlc)) {
        paths << appDirVlc;
    }

    // Read VLC version and installation directory from Windows registry
    QSettings settings(QSettings::SystemScope, "VideoLAN", "VLC");
    QString vlcVersion = settings.value("Version").toString();
    QString vlcInstallDir = settings.value("InstallDir").toString();
    if (vlcVersion.startsWith(QLatin1String("1.1")) && !vlcInstallDir.isEmpty()) {
        paths << vlcInstallDir % QLatin1Char('\\') % QLatin1Literal("libvlc.dll");
        return paths;
    } else {
        //If nothing is found in the registry try %PATH%
        QStringList searchPaths = QString::fromLatin1(qgetenv("PATH"))
                                  .split(QLatin1Char(';'), QString::SkipEmptyParts);

        QStringList foundVlcs;
        foreach(const QString & sp, searchPaths) {
            QDir dir = QDir(sp);
            QStringList entryList = dir.entryList(QStringList() << QLatin1String("libvlc.dll"), QDir::Files);
            foreach(const QString & entry, entryList){
                foundVlcs << sp % QLatin1Char('\\') % entry;
            }
        }
        paths << foundVlcs;
        return paths;
    }
#endif
}

QString LibVLC::vlcPath()
{
    static QString path;
    if (!path.isEmpty()) {
        return path;
    }

    m_vlcLibrary = new QLibrary();
    QStringList paths = LibVLC::findAllLibVlcPaths();
    foreach(path, paths) {
        m_vlcLibrary->setFileName(path);

        if (!m_vlcLibrary->resolve("libvlc_exception_init")) { //"libvlc_exception_init" not contained in 1.1+
            return path;
        } else {
            debug() << "Cannot resolve the symbol or load VLC library";
        }
        warning() << m_vlcLibrary->errorString();
    }

    vlcUnload();

    return QString();
}

void LibVLC::vlcUnload()
{
    m_vlcLibrary->unload();
    delete m_vlcLibrary;
    m_vlcLibrary = 0;
}
<|endoftext|>


<commit_before>/**
 * \file AnnAnnOculusInterfaceHelper.hpp
 * \brief Simple class for accessing Oculus Rift data
 * \author A. Brainville (Ybalrid)
 */

#pragma once

#include "systemMacro.h"

//Oculus VR API
#include <OVR_CAPI.h>
#include <Extras/OVR_Math.h>
#include <Ogre.h>
#include <AnnException.hpp>

///Communicate with the Rift runtime (initialize OVR and get the info)
class AnnDllExport AnnOculusInterfaceHelper
{
public:
	///Construct an AnnOculusInterfaceHelper object. This create an Oculus Session for communication with the Oculus Runtime
	AnnOculusInterfaceHelper();

	///Destructor of Oculus Interface
	~AnnOculusInterfaceHelper();

	///Return the active HmdDesc object
	ovrHmdDesc getHmdDesc() const;

	///Return the current oculus session
	ovrSession getSession() const;

	///Return the eye's height of the current user
	float getUserEyeHeight() const;

	///Recenter the tracking origin
	void recenterTrackingOrigin() const;

	///Set the performance HUD mode
	void setPerfHudMode(ovrPerfHudMode mode) const;

	///get HMD resolution in the Oculus format
	ovrSizei getHmdResolution() const;

	///get HMD Refresh rate. e.g. 90 (or 89.99) for an Oculus Rift CV1
	float getHmdDisplayRefreshRate() const;

	///Set the reference point to be a point on the ground, not the "zero" position of the headset
	void setTrackingOriginToFloorLevel() const;

private:
	///Print every known characteristics about the hardware to the log output
	void logHardwareReport() const;

	///Abort, display error, log it and crash the game
	void abortOnFailure();

	///Oculus session for the application
	ovrSession session;

	///Description of the HMD
	ovrHmdDesc hmdDesc;

	///Graphics device identifier (internal for the Rift SDK)
	ovrGraphicsLuid luid;
};
<commit_msg>Put the oculus helper class inside the Annwvyn namespace<commit_after>/**
 * \file AnnOculusInterfaceHelper.hpp
 * \brief Simple class for accessing Oculus Rift data
 * \author A. Brainville (Ybalrid)
 */

#pragma once

#include "systemMacro.h"

//Oculus VR API
#include <OVR_CAPI.h>
#include <Extras/OVR_Math.h>
#include <Ogre.h>
#include <AnnException.hpp>

namespace Annwvyn
{

	///Communicate with the Rift runtime (initialize OVR and get the info)
	class AnnDllExport AnnOculusInterfaceHelper
	{
	public:
		///Construct an AnnOculusInterfaceHelper object. This create an Oculus Session for communication with the Oculus Runtime
		AnnOculusInterfaceHelper();

		///Destructor of Oculus Interface
		~AnnOculusInterfaceHelper();

		///Return the active HmdDesc object
		ovrHmdDesc getHmdDesc() const;

		///Return the current oculus session
		ovrSession getSession() const;

		///Return the eye's height of the current user
		float getUserEyeHeight() const;

		///Recenter the tracking origin
		void recenterTrackingOrigin() const;

		///Set the performance HUD mode
		void setPerfHudMode(ovrPerfHudMode mode) const;

		///get HMD resolution in the Oculus format
		ovrSizei getHmdResolution() const;

		///get HMD Refresh rate. e.g. 90 (or 89.99) for an Oculus Rift CV1
		float getHmdDisplayRefreshRate() const;

		///Set the reference point to be a point on the ground, not the "zero" position of the headset
		void setTrackingOriginToFloorLevel() const;

	private:
		///Print every known characteristics about the hardware to the log output
		void logHardwareReport() const;

		///Abort, display error, log it and crash the game
		void abortOnFailure();

		///Oculus session for the application
		ovrSession session;

		///Description of the HMD
		ovrHmdDesc hmdDesc;

		///Graphics device identifier (internal for the Rift SDK)
		ovrGraphicsLuid luid;
	};
}
<|endoftext|>


<commit_before>/*******************************************************************************
 * Copyright (c) 2015 Wojciech Migda
 * All rights reserved
 * Distributed under the terms of the GNU LGPL v3
 *******************************************************************************
 *
 * Filename: linreg.hpp
 *
 * Description:
 *      description
 *
 * Authors:
 *          Wojciech Migda (wm)
 *
 *******************************************************************************
 * History:
 * --------
 * Date         Who  Ticket     Description
 * ----------   ---  ---------  ------------------------------------------------
 * 2015-02-22   wm              Initial version
 *
 ******************************************************************************/

#ifndef LINREG_HPP_
#define LINREG_HPP_

#include "array2d.hpp"
#include "fmincg.hpp"
#include "num.hpp"

#include <valarray>
#include <utility>
#include <cassert>

namespace num
{

template<typename _ValueType>
void
linreg_cost_grad(
    /// out
    _ValueType & out_cost,
    std::valarray<_ValueType> & out_grad,
    std::valarray<_ValueType> & tcol,
    /// in
    const std::valarray<_ValueType> theta,
    const array2d<_ValueType> X,
    const std::valarray<_ValueType> y,
    const _ValueType C
)
{
    typedef _ValueType value_type;
    typedef std::valarray<value_type> vector;

    const shape_type X_shape = X.shape();

    assert(y.size() == X_shape.first);
    assert(out_grad.size() == X_shape.second);
    assert(theta.size() == X_shape.second);

    assert(tcol.size() >= X_shape.first);

    vector & H = tcol;

    //    H = (theta' * X')' - y;
    for (size_type r{0}; r < X_shape.first; ++r)
    {
        H[r] = (X[X.row(r)] * theta).sum();
    }
    H -= y;

    //  sigma_i = sum(H .* H);
    const value_type Sigma = (H * H).sum();

    //  J = (sigma_i + sum(theta_for_reg .* theta_for_reg) / C) / (2 * m);
    out_cost = (Sigma + (theta[std::slice(1, X_shape.second - 1, 1)] * theta[std::slice(1, X_shape.second - 1, 1)]).sum() / C) / (2.0 * X_shape.first);

    //  theta_for_reg = [0; theta(2:end)];
    //  grad = theta_for_reg' / C;
    out_grad = theta / C;
    out_grad[0] = 0.0;
    //  grad += (H)' * X;
    for (size_type r{0}; r < X_shape.second; ++r)
    {
        out_grad[r] += (X[X.column(r)] * H).sum();
    }
    //  grad /= m;
    out_grad /= X_shape.first;
}

template<typename _ValueType>
std::pair<_ValueType, std::valarray<_ValueType>>
linreg_cost_grad(
    const std::valarray<_ValueType> theta,
    const array2d<_ValueType> X,
    const std::valarray<_ValueType> y,
    const _ValueType C)
{
    typedef _ValueType value_type;
    typedef std::valarray<value_type> vector;

    const shape_type X_shape = X.shape();

    vector temp(X_shape.first);

    const double cost;
    const vector grad(X_shape.first);

    linreg_cost_grad(cost, grad, temp, theta, X, y, C);

    return std::make_pair(cost, grad);
}

template<typename _ValueType>
class LinearRegression
{
public:
    typedef _ValueType value_type;
    typedef std::valarray<value_type> vector_type;
    typedef array2d<value_type> array_type;

    LinearRegression(
        array_type && X,
        vector_type && y,
        vector_type && theta0,
        value_type C,
        size_type max_iter
    );

    vector_type
    fit(void) const;

    vector_type
    predict(const array_type & X, const vector_type & theta) const;

    vector_type
    predict(array_type && X, vector_type && theta) const;

private:
    const array_type m_X;
    const vector_type m_y;
    const vector_type m_theta0;
    const value_type m_C;
    const size_type m_max_iter;
};

template<typename _ValueType>
LinearRegression<_ValueType>::LinearRegression(
    array_type && X,
    vector_type && y,
    vector_type && theta0,
    value_type C,
    size_type max_iter
)
:
    m_X{std::move(X)},
    m_y{std::move(y)},
    m_theta0{m_theta0.size() == m_X.shape().second ? std::move(theta0) : vector_type(m_X.shape().second)},
    m_C{C},
    m_max_iter{max_iter}
{
}

template<typename _ValueType>
typename LinearRegression<_ValueType>::vector_type
LinearRegression<_ValueType>::fit(void) const
{
    vector_type tcol(m_y.size());

    std::function<std::pair<value_type, vector_type> (vector_type)>

    /* NOTE: Capturing member variables is always done via capturing this */
    cost_fn = [this, &tcol](const vector_type theta) -> std::pair<value_type, vector_type>
    {
        value_type cost;
        vector_type grad(theta.size());

        num::linreg_cost_grad(cost, grad, tcol, theta, this->m_X, this->m_y, this->m_C);

        return std::make_pair(cost, grad);
    };

    const vector_type theta = num::fmincg(cost_fn, m_theta0, m_max_iter, true);

    return theta;
}

template<typename _ValueType>
typename LinearRegression<_ValueType>::vector_type
LinearRegression<_ValueType>::predict(const array_type & X, const vector_type & theta) const
{
    assert(theta.size() == X.shape().second);

    vector_type H(X.shape().first);

    for (size_type r{0}; r < X.shape().first; ++r)
    {
        H[r] = (X[X.row(r)] * theta).sum();
    }

    return H;
}

template<typename _ValueType>
typename LinearRegression<_ValueType>::vector_type
LinearRegression<_ValueType>::predict(array_type && X, vector_type && theta) const
{
    return predict(X, theta);
}

} // namespace num

#endif /* LINREG_HPP_ */
<commit_msg>verbose off<commit_after>/*******************************************************************************
 * Copyright (c) 2015 Wojciech Migda
 * All rights reserved
 * Distributed under the terms of the GNU LGPL v3
 *******************************************************************************
 *
 * Filename: linreg.hpp
 *
 * Description:
 *      description
 *
 * Authors:
 *          Wojciech Migda (wm)
 *
 *******************************************************************************
 * History:
 * --------
 * Date         Who  Ticket     Description
 * ----------   ---  ---------  ------------------------------------------------
 * 2015-02-22   wm              Initial version
 *
 ******************************************************************************/

#ifndef LINREG_HPP_
#define LINREG_HPP_

#include "array2d.hpp"
#include "fmincg.hpp"
#include "num.hpp"

#include <valarray>
#include <utility>
#include <cassert>

namespace num
{

template<typename _ValueType>
void
linreg_cost_grad(
    /// out
    _ValueType & out_cost,
    std::valarray<_ValueType> & out_grad,
    std::valarray<_ValueType> & tcol,
    /// in
    const std::valarray<_ValueType> theta,
    const array2d<_ValueType> X,
    const std::valarray<_ValueType> y,
    const _ValueType C
)
{
    typedef _ValueType value_type;
    typedef std::valarray<value_type> vector;

    const shape_type X_shape = X.shape();

    assert(y.size() == X_shape.first);
    assert(out_grad.size() == X_shape.second);
    assert(theta.size() == X_shape.second);

    assert(tcol.size() >= X_shape.first);

    vector & H = tcol;

    //    H = (theta' * X')' - y;
    for (size_type r{0}; r < X_shape.first; ++r)
    {
        H[r] = (X[X.row(r)] * theta).sum();
    }
    H -= y;

    //  sigma_i = sum(H .* H);
    const value_type Sigma = (H * H).sum();

    //  J = (sigma_i + sum(theta_for_reg .* theta_for_reg) / C) / (2 * m);
    out_cost = (Sigma + (theta[std::slice(1, X_shape.second - 1, 1)] * theta[std::slice(1, X_shape.second - 1, 1)]).sum() / C) / (2.0 * X_shape.first);

    //  theta_for_reg = [0; theta(2:end)];
    //  grad = theta_for_reg' / C;
    out_grad = theta / C;
    out_grad[0] = 0.0;
    //  grad += (H)' * X;
    for (size_type r{0}; r < X_shape.second; ++r)
    {
        out_grad[r] += (X[X.column(r)] * H).sum();
    }
    //  grad /= m;
    out_grad /= X_shape.first;
}

template<typename _ValueType>
std::pair<_ValueType, std::valarray<_ValueType>>
linreg_cost_grad(
    const std::valarray<_ValueType> theta,
    const array2d<_ValueType> X,
    const std::valarray<_ValueType> y,
    const _ValueType C)
{
    typedef _ValueType value_type;
    typedef std::valarray<value_type> vector;

    const shape_type X_shape = X.shape();

    vector temp(X_shape.first);

    const double cost;
    const vector grad(X_shape.first);

    linreg_cost_grad(cost, grad, temp, theta, X, y, C);

    return std::make_pair(cost, grad);
}

template<typename _ValueType>
class LinearRegression
{
public:
    typedef _ValueType value_type;
    typedef std::valarray<value_type> vector_type;
    typedef array2d<value_type> array_type;

    LinearRegression(
        array_type && X,
        vector_type && y,
        vector_type && theta0,
        value_type C,
        size_type max_iter
    );

    vector_type
    fit(void) const;

    vector_type
    predict(const array_type & X, const vector_type & theta) const;

    vector_type
    predict(array_type && X, vector_type && theta) const;

private:
    const array_type m_X;
    const vector_type m_y;
    const vector_type m_theta0;
    const value_type m_C;
    const size_type m_max_iter;
};

template<typename _ValueType>
LinearRegression<_ValueType>::LinearRegression(
    array_type && X,
    vector_type && y,
    vector_type && theta0,
    value_type C,
    size_type max_iter
)
:
    m_X{std::move(X)},
    m_y{std::move(y)},
    m_theta0{m_theta0.size() == m_X.shape().second ? std::move(theta0) : vector_type(m_X.shape().second)},
    m_C{C},
    m_max_iter{max_iter}
{
}

template<typename _ValueType>
typename LinearRegression<_ValueType>::vector_type
LinearRegression<_ValueType>::fit(void) const
{
    vector_type tcol(m_y.size());

    std::function<std::pair<value_type, vector_type> (vector_type)>

    /* NOTE: Capturing member variables is always done via capturing this */
    cost_fn = [this, &tcol](const vector_type theta) -> std::pair<value_type, vector_type>
    {
        value_type cost;
        vector_type grad(theta.size());

        num::linreg_cost_grad(cost, grad, tcol, theta, this->m_X, this->m_y, this->m_C);

        return std::make_pair(cost, grad);
    };

    const vector_type theta = num::fmincg(cost_fn, m_theta0, m_max_iter, false);

    return theta;
}

template<typename _ValueType>
typename LinearRegression<_ValueType>::vector_type
LinearRegression<_ValueType>::predict(const array_type & X, const vector_type & theta) const
{
    assert(theta.size() == X.shape().second);

    vector_type H(X.shape().first);

    for (size_type r{0}; r < X.shape().first; ++r)
    {
        H[r] = (X[X.row(r)] * theta).sum();
    }

    return H;
}

template<typename _ValueType>
typename LinearRegression<_ValueType>::vector_type
LinearRegression<_ValueType>::predict(array_type && X, vector_type && theta) const
{
    return predict(X, theta);
}

} // namespace num

#endif /* LINREG_HPP_ */
<|endoftext|>


<commit_before>#ifndef ARABICA_TEXT_COALESCER_HPP
#define ARABICA_TEXT_COALESCER_HPP

#include <SAX/ArabicaConfig.h>
#include <SAX/helpers/XMLFilterImpl.h>
#include <Utils/StringAdaptor.h>

namespace SAX
{

/**
  Parsers are not required to report text in contiguous lumps.  It's perfectly legal to
  report a block of text in one, two or many calls to characters(...).  Sometimes this isn't
  an issue, and sometimes it makes things a little awkward.
  This filter buffers up multiple calls to characters(...) and reports text in a single lump.
 */
template<class string_type, class string_adaptor = Arabica::default_string_adaptor<string_type> >
class TextCoalescer : public basic_XMLFilterImpl<string_type>
{
  typedef basic_XMLFilterImpl<string_type> XMLFilterT;

public:
  typedef basic_XMLReader<string_type> XMLReaderT;
  typedef basic_Attributes<string_type> AttributesT;

  TextCoalescer() :
    XMLFilterT(0)
  {
  } // basic_TextCoalescer

  TextCoalescer(XMLReaderT& parent) :
    XMLFilterT(parent)
  {
  } // basic_TextCoalescer

  virtual void startElement(const string_type& namespaceURI, const string_type& localName,
                            const string_type& qName, const AttributesT& atts)
  {
    flush();
    XMLFilterT::startElement(namespaceURI, localName, qName, atts);
  } // startElement

  virtual void endElement(const string_type& namespaceURI, const string_type& localName,
                          const string_type& qName)
  {
    flush();
    XMLFilterT::endElement(namespaceURI, localName, qName);
  }  // endElement

  virtual void characters(const string_type& ch)
  {
    string_adaptor::append(buffer_, ch);
  } // characters

  virtual void ignorableWhitespace(const string_type& ch)
  {
    string_adaptor::append(buffer_, ch);
  } // ignorableWhitespace

  virtual void processingInstruction(const string_type& target, const string_type& data)
  {
    flush();
    XMLFilterT::processingInstruction(target, data);
  } // processingInstruction

  virtual void startCDATA()
  {
    flush();
    XMLFilterT::startCDATA();
  } // startCDATA

  virtual void endCDATA()
  {
    flush();
    XMLFilterT::endCDATA();
  } // endCDATA

  virtual void comment(const string_type& text)
  {
    flush();
    XMLFilterT::comment(text);
  } // comment

private:
  void flush()
  {
    if(string_adaptor::empty(buffer_))
      return;

    XMLFilterT::characters(buffer_);
    buffer_ = string_adaptor::empty_string();
  } // flush
  string_type buffer_;
}; // class basic_TextCoalescer

} // namespace SAX
#endif
<commit_msg>corrected default constructor<commit_after>#ifndef ARABICA_TEXT_COALESCER_HPP
#define ARABICA_TEXT_COALESCER_HPP

#include <SAX/ArabicaConfig.h>
#include <SAX/helpers/XMLFilterImpl.h>
#include <Utils/StringAdaptor.h>

namespace SAX
{

/**
  Parsers are not required to report text in contiguous lumps.  It's perfectly legal to
  report a block of text in one, two or many calls to characters(...).  Sometimes this isn't
  an issue, and sometimes it makes things a little awkward.
  This filter buffers up multiple calls to characters(...) and reports text in a single lump.
 */
template<class string_type, class string_adaptor = Arabica::default_string_adaptor<string_type> >
class TextCoalescer : public basic_XMLFilterImpl<string_type>
{
  typedef basic_XMLFilterImpl<string_type> XMLFilterT;

public:
  typedef basic_XMLReader<string_type> XMLReaderT;
  typedef basic_Attributes<string_type> AttributesT;

  TextCoalescer() :
    XMLFilterT()
  {
  } // basic_TextCoalescer

  TextCoalescer(XMLReaderT& parent) :
    XMLFilterT(parent)
  {
  } // basic_TextCoalescer

  virtual void startElement(const string_type& namespaceURI, const string_type& localName,
                            const string_type& qName, const AttributesT& atts)
  {
    flush();
    XMLFilterT::startElement(namespaceURI, localName, qName, atts);
  } // startElement

  virtual void endElement(const string_type& namespaceURI, const string_type& localName,
                          const string_type& qName)
  {
    flush();
    XMLFilterT::endElement(namespaceURI, localName, qName);
  }  // endElement

  virtual void characters(const string_type& ch)
  {
    string_adaptor::append(buffer_, ch);
  } // characters

  virtual void ignorableWhitespace(const string_type& ch)
  {
    string_adaptor::append(buffer_, ch);
  } // ignorableWhitespace

  virtual void processingInstruction(const string_type& target, const string_type& data)
  {
    flush();
    XMLFilterT::processingInstruction(target, data);
  } // processingInstruction

  virtual void startCDATA()
  {
    flush();
    XMLFilterT::startCDATA();
  } // startCDATA

  virtual void endCDATA()
  {
    flush();
    XMLFilterT::endCDATA();
  } // endCDATA

  virtual void comment(const string_type& text)
  {
    flush();
    XMLFilterT::comment(text);
  } // comment

private:
  void flush()
  {
    if(string_adaptor::empty(buffer_))
      return;

    XMLFilterT::characters(buffer_);
    buffer_ = string_adaptor::empty_string();
  } // flush
  string_type buffer_;
}; // class basic_TextCoalescer

} // namespace SAX
#endif
<|endoftext|>


<commit_before>#ifndef COMPASS_RT_X86_LLVM_CPUID_H_
#define COMPASS_RT_X86_LLVM_CPUID_H_

#include "detail/ct/detect_compiler.hpp"

#ifdef COMPASS_CT_COMP_CLANG

#include <array>
#include <bitset>
#include <cstdint>

#include "detail/tags.hpp"
#include "detail/definitions.hpp"
#include "detail/rt/x86/cpuid_common.hpp"

namespace compass {

  namespace runtime {

    static std::array<std::uint32_t,4> cpuid_to_int(std::uint32_t in_eax = 0,
                                                    std::uint32_t in_ebx = 0,
                                                    std::uint32_t in_ecx = 0,
                                                    std::uint32_t in_edx = 0){

      static std::array<std::uint32_t,4> value = {~0u};

      int cpuid_rvalue = extended_get_cpud(&value[0],in_eax,in_ecx);

      if(cpuid_rvalue < 1){
        value = {0,0,0,0};
        return value;
      } else {
        return value;
      }
    }

  };

};
#endif /* COMPASS_CT_COMP_CLANG */
#endif /* COMPASS_CT_LLVM_IMPL_H_ */
<commit_msg>fixed wrong function name<commit_after>#ifndef COMPASS_RT_X86_LLVM_CPUID_H_
#define COMPASS_RT_X86_LLVM_CPUID_H_

#include "detail/ct/detect_compiler.hpp"

#ifdef COMPASS_CT_COMP_CLANG

#include <array>
#include <bitset>
#include <cstdint>

#include "detail/tags.hpp"
#include "detail/definitions.hpp"
#include "detail/rt/x86/cpuid_common.hpp"

namespace compass {

  namespace runtime {

    static std::array<std::uint32_t,4> cpuid_to_int(std::uint32_t in_eax = 0,
                                                    std::uint32_t in_ebx = 0,
                                                    std::uint32_t in_ecx = 0,
                                                    std::uint32_t in_edx = 0){

      static std::array<std::uint32_t,4> value = {~0u};

      int cpuid_rvalue = extended_get_cpuid(&value[0],in_eax,in_ecx);

      if(cpuid_rvalue < 1){
        value = {0,0,0,0};
        return value;
      } else {
        return value;
      }
    }

  };

};
#endif /* COMPASS_CT_COMP_CLANG */
#endif /* COMPASS_CT_LLVM_IMPL_H_ */
<|endoftext|>