<commit_before>#include <QtNetwork/QTcpSocket>
#include <QFileInfo>
#include <QFile>
#include <QStringList>
#include <QDir>

#include "httpthread.h"

HTTPThread::HTTPThread(const int socketDescriptor, const QString &docRoot,
                       QObject *parent) :
    QThread(parent), socketDescriptor(socketDescriptor), docRoot(docRoot),
    responseStatusLine("HTTP/1.0 %1\r\n")
{
}

void HTTPThread::run()
{
    QTcpSocket socket;

    if(!socket.setSocketDescriptor(socketDescriptor)){
        qDebug() << "Setting the sd has failed: " << socket.errorString();
        emit error(socket.error());

        return;
    }

    QString request = readRequest(&socket);
    qDebug() << request;

    QByteArray response = processRequestData(parseHTTPRequest(request));

    //TODO: construct the response in a nice data structure and put it toghether here
    //also be good and send a Content-Length field (bytes)
    socket.write(response, response.size());

    if(!socket.waitForBytesWritten()){
        qDebug() << "Could not write byts to socket: " << socket.errorString();
        emit error(socket.error());
    }

    socket.close();
}

QString HTTPThread::readRequest(QTcpSocket *socket){
    QString request;

    //TODO: what if is a POST?

    do{
        if(!socket->waitForReadyRead()){
            qDebug() << "Error while waiting for client data: "
                     << socket->errorString();
            emit error(socket->error());

            return request;
        }

        request.append(QString(socket->readAll()));
    }while(-1 == request.lastIndexOf("\n\n") &&
           -1 == request.lastIndexOf("\r\n\r\n"));

    return request;
}

RequestData HTTPThread::parseHTTPRequest(QString request)
{
    RequestData requestData;
    requestData.valid = false;

    //TODO: what if I encounter \r\n in the URL or in the POST data?
    //TODO: be tolerant and replace "\r" with "" and then work with "\n"
    QStringList parts = request.split("\r\n\r\n", QString::SkipEmptyParts);

    if(parts.isEmpty()){
        return requestData;
    }

    QStringList fields = parts[0].split("\r\n", QString::SkipEmptyParts);

    QStringList statusLine = fields[0].split(" ");

    if(3 != statusLine.size()){
        return requestData;
    }

    QStringList protocol = statusLine[2].split("/");
    bool ok;

    if(2 != protocol.size()){
        return requestData;
    }

    double ver = protocol[1].toDouble(&ok);

    if("HTTP" != protocol[0] || !ok || ver < 0.9 || ver > 1.1){
        return requestData;
    }

    requestData.method = statusLine[0];
    requestData.url.setUrl(statusLine[1]);
    requestData.protocol = protocol[0];
    requestData.protocolVersion = ver;

    fields.removeAt(0);
    int spacePos;
    foreach(QString line, fields){
        spacePos = line.indexOf(" ");

        requestData.fields.insert(line.left(spacePos-1),
                           QStringList(line.right(line.size()-spacePos-1)));
    }

    if(requestData.fields.contains("Host")){
        requestData.fields["Host"] = requestData.fields["Host"][0].split(":");
    }

    if("POST" == requestData.method && 2 == parts.size() &&
            !parts[1].isEmpty()){
        requestData.postData = parsePostBody(parts[1]);
        //TODO: if it's empty error out
    }

    qDebug() << "Request data:\n\tStatusLine:\n\t\tMethod: "
             << requestData.method << "\n\t\tUrl: "
             << requestData.url << "\n\t\tProtocol: "
             << requestData.protocol << "\n\t\tVer: "
             <<requestData.protocolVersion
             << "\n\tFields: " << requestData.fields
             << "\n\tpost: " << requestData.postData;

    requestData.valid = true;
    return requestData;
}

QHash<QString, QString> HTTPThread::parsePostBody(QString postBody)
{
    // what if a radiobox is checked and sent?
    // what if: "option_set", with no "=" sign, is it possible?
    // what if the data contains "&"?
    QHash<QString, QString> retval;

    QStringList pairs = postBody.split("&", QString::SkipEmptyParts); //TODO: ???

    foreach(QString pair, pairs){
        QStringList keyVal = pair.split("="); //TODO: ???
        retval.insert(keyVal[0], keyVal[1]); //TODO: ???
    }

    return retval;
}

QByteArray HTTPThread::processRequestData(const RequestData &requestData)
{
    //TODO: add support for different Host values
    //TODO: URL rewriting?

    QByteArray response = responseStatusLine.arg("200 OK").toUtf8();

    if(!requestData.valid){
        return responseStatusLine.arg("400 Bad request\r\n").toAscii();
    }

    if("GET" == requestData.method || "POST" == requestData.method){
        //serve static files

        QString fullPath = docRoot + requestData.url.path();
        QFileInfo f(fullPath);

        qDebug() << requestData.method << " " << fullPath;

        if(f.exists() && f.isReadable()){
            if(f.isDir()){
                response = serveStaticDir(response, f.absoluteFilePath());
            }
            else{
                response = serveStaticFile(response, f.absoluteFilePath());

                if(response.isEmpty()){
                    response = responseStatusLine.arg(
                                "500 Internal Server Error\r\n").toAscii();
                }
            }
        }

        /* TODO: load HTTPSCripts via HTTPScriptLoader (.so and .dll files) ?
         * -> evolve this into FastCGI? read more
         *
         * or at least create a mapping of path -> method
         *
         *What's below isn't good because I have to modify the daemon every
         *time I want new functionality and the "login", "check", etc. methods are not a semantic part of HTTPThread
         */
        else if("/patrat" == requestData.url.path()){
            response = square(response, requestData);
        }
        else if("/login" == requestData.url.path()){
            response = login(response, requestData);
        }
        else if("/verifica" == requestData.url.path()){
            response = check(response, requestData);
        }
        else if(!f.exists()){
            response = responseStatusLine.arg("404 Not Found\r\n").toAscii();
        }
        else if(!f.isReadable()){
            qDebug() << "Not readable!";
            response = responseStatusLine.arg("403 Forbidden\r\n").toAscii() +
                    "Permission denied\n";
        }
    }
    else{
        response = responseStatusLine.arg("501 Not Implemented\r\n").toAscii();
        qDebug() << "Unsupported HTTP method!";
    }

    return response;
    return responseStatusLine.arg("200 OK\r\n").toAscii();
}

QByteArray HTTPThread::serveStaticFile(const QByteArray &partialResponse,
                                       const QString &filePath)
{
    //TODO: set the mime type
    QFile file(filePath);

    if(!file.open( QIODevice::ReadOnly)){
        qDebug() << "Cannot open";
        return "";
    }

    return partialResponse + "\r\n" + file.readAll();
}

QByteArray HTTPThread::serveStaticDir(const QByteArray &partialResponse,
                                      const QString &dirPath)
{
    QDir dir(dirPath);
    QStringList dirList = dir.entryList();

    if(dirList.isEmpty()){
        return responseStatusLine.arg("404 Not Found\r\n").toAscii();
    }

    //TODO: format as HTML
    return partialResponse + "Content-Type: text/plain\r\n\r\n" +
            dirList.join("\n").toUtf8();
}

QByteArray HTTPThread::square(const QByteArray &partialResponse,
                              const RequestData &requestData)
{
    if("GET" != requestData.method || !requestData.url.hasQueryItem("a")){
        return responseStatusLine.arg("400 Bad Request\r\n").toAscii();
    }

    QString numToSquare = requestData.url.queryItemValue("a");
    QString body;

    bool ok;
    double n = numToSquare.toDouble(&ok);

    if(!ok){
        body = "a-ul trebuie sa fie numar!\n";
    }
    else{
        body = numToSquare + "^2 = " + QString::number(n*n) + "\n";
    }

    return partialResponse + "\r\n" + body.toAscii();
}

QByteArray HTTPThread::login(const QByteArray &partialResponse,
                             const RequestData &requestData)
{
    return partialResponse + "\r\n"
            "<form method=\"POST\">"
            "Username: <input type=\"text\" name=\"username\">"
            "Password: <input type=\"password\" name=\"pass\">"
            "<INPUT type=\"submit\" value=\"Auth\">"
            "</form>";
}

QByteArray HTTPThread::check(const QByteArray &partialResponse,
                             const QHash<QString, QStringList> &requestData)
{
    return partialResponse + "\r\n";
}
<commit_msg>finished the test methods HTTPThread::login() and HTTPThread::check()<commit_after>#include <QtNetwork/QTcpSocket>
#include <QFileInfo>
#include <QFile>
#include <QStringList>
#include <QDir>

#include "httpthread.h"

HTTPThread::HTTPThread(const int socketDescriptor, const QString &docRoot,
                       QObject *parent) :
    QThread(parent), socketDescriptor(socketDescriptor), docRoot(docRoot),
    responseStatusLine("HTTP/1.0 %1\r\n")
{
}

void HTTPThread::run()
{
    QTcpSocket socket;

    if(!socket.setSocketDescriptor(socketDescriptor)){
        qDebug() << "Setting the sd has failed: " << socket.errorString();
        emit error(socket.error());

        return;
    }

    QString request = readRequest(&socket);
    qDebug() << request;

    QByteArray response = processRequestData(parseHTTPRequest(request));

    //TODO: construct the response in a nice data structure and put it toghether here
    //also be good and send a Content-Length field (bytes)
    socket.write(response, response.size());

    if(!socket.waitForBytesWritten()){
        qDebug() << "Could not write byts to socket: " << socket.errorString();
        emit error(socket.error());
    }

    socket.close();
}

QString HTTPThread::readRequest(QTcpSocket *socket){
    QString request;

    //TODO: what if is a POST?

    do{
        if(!socket->waitForReadyRead()){
            qDebug() << "Error while waiting for client data: "
                     << socket->errorString();
            emit error(socket->error());

            return request;
        }

        request.append(QString(socket->readAll()));
    }while(-1 == request.lastIndexOf("\n\n") &&
           -1 == request.lastIndexOf("\r\n\r\n"));

    return request;
}

RequestData HTTPThread::parseHTTPRequest(QString request)
{
    RequestData requestData;
    requestData.valid = false;

    //TODO: what if I encounter \r\n in the URL or in the POST data?
    //TODO: be tolerant and replace "\r" with "" and then work with "\n"
    QStringList parts = request.split("\r\n\r\n", QString::SkipEmptyParts);

    if(parts.isEmpty()){
        return requestData;
    }

    QStringList fields = parts[0].split("\r\n", QString::SkipEmptyParts);

    QStringList statusLine = fields[0].split(" ");

    if(3 != statusLine.size()){
        return requestData;
    }

    QStringList protocol = statusLine[2].split("/");
    bool ok;

    if(2 != protocol.size()){
        return requestData;
    }

    double ver = protocol[1].toDouble(&ok);

    if("HTTP" != protocol[0] || !ok || ver < 0.9 || ver > 1.1){
        return requestData;
    }

    requestData.method = statusLine[0];
    requestData.url.setUrl(statusLine[1]);
    requestData.protocol = protocol[0];
    requestData.protocolVersion = ver;

    fields.removeAt(0);
    int spacePos;
    foreach(QString line, fields){
        spacePos = line.indexOf(" ");

        requestData.fields.insert(line.left(spacePos-1),
                           QStringList(line.right(line.size()-spacePos-1)));
    }

    if(requestData.fields.contains("Host")){
        requestData.fields["Host"] = requestData.fields["Host"][0].split(":");
    }

    if("POST" == requestData.method && 2 == parts.size() &&
            !parts[1].isEmpty()){
        requestData.postData = parsePostBody(parts[1]);
        //TODO: if it's empty error out
    }

    qDebug() << "Request data:\n\tStatusLine:\n\t\tMethod: "
             << requestData.method << "\n\t\tUrl: "
             << requestData.url << "\n\t\tProtocol: "
             << requestData.protocol << "\n\t\tVer: "
             <<requestData.protocolVersion
             << "\n\tFields: " << requestData.fields
             << "\n\tpost: " << requestData.postData;

    requestData.valid = true;
    return requestData;
}

QHash<QString, QString> HTTPThread::parsePostBody(QString postBody)
{
    // what if a radiobox is checked and sent?
    // what if: "option_set", with no "=" sign, is it possible?
    // what if the data contains "&"?
    QHash<QString, QString> retval;

    QStringList pairs = postBody.split("&", QString::SkipEmptyParts); //TODO: ???

    foreach(QString pair, pairs){
        QStringList keyVal = pair.split("="); //TODO: ???
        retval.insert(keyVal[0], keyVal[1]); //TODO: ???
    }

    return retval;
}

QByteArray HTTPThread::processRequestData(const RequestData &requestData)
{
    //TODO: add support for different Host values
    //TODO: URL rewriting?

    QByteArray response = responseStatusLine.arg("200 OK").toUtf8();

    if(!requestData.valid){
        return responseStatusLine.arg("400 Bad request\r\n").toAscii();
    }

    if("GET" == requestData.method || "POST" == requestData.method){
        //serve static files

        QString fullPath = docRoot + requestData.url.path();
        QFileInfo f(fullPath);

        qDebug() << requestData.method << " " << fullPath;

        if(f.exists() && f.isReadable()){
            if(f.isDir()){
                response = serveStaticDir(response, f.absoluteFilePath());
            }
            else{
                response = serveStaticFile(response, f.absoluteFilePath());

                if(response.isEmpty()){
                    response = responseStatusLine.arg(
                                "500 Internal Server Error\r\n").toAscii();
                }
            }
        }

        /* TODO: load HTTPSCripts via HTTPScriptLoader (.so and .dll files) ?
         * -> evolve this into FastCGI? read more
         *
         * or at least create a mapping of path -> method
         *
         *What's below isn't good because I have to modify the daemon every
         *time I want new functionality and the "login", "check", etc. methods are not a semantic part of HTTPThread
         */
        else if("/patrat" == requestData.url.path()){
            response = square(response, requestData);
        }
        else if("/login" == requestData.url.path()){
            response = login(response, requestData);
        }
        else if("/verifica" == requestData.url.path()){
            response = check(response, requestData);
        }
        else if(!f.exists()){
            response = responseStatusLine.arg("404 Not Found\r\n").toAscii();
        }
        else if(!f.isReadable()){
            qDebug() << "Not readable!";
            response = responseStatusLine.arg("403 Forbidden\r\n").toAscii() +
                    "Permission denied\n";
        }
    }
    else{
        response = responseStatusLine.arg("501 Not Implemented\r\n").toAscii();
        qDebug() << "Unsupported HTTP method!";
    }

    return response;
    return responseStatusLine.arg("200 OK\r\n").toAscii();
}

QByteArray HTTPThread::serveStaticFile(const QByteArray &partialResponse,
                                       const QString &filePath)
{
    //TODO: set the mime type
    QFile file(filePath);

    if(!file.open( QIODevice::ReadOnly)){
        qDebug() << "Cannot open";
        return "";
    }

    return partialResponse + "\r\n" + file.readAll();
}

QByteArray HTTPThread::serveStaticDir(const QByteArray &partialResponse,
                                      const QString &dirPath)
{
    QDir dir(dirPath);
    QStringList dirList = dir.entryList();

    if(dirList.isEmpty()){
        return responseStatusLine.arg("404 Not Found\r\n").toAscii();
    }

    //TODO: format as HTML
    return partialResponse + "Content-Type: text/plain\r\n\r\n" +
            dirList.join("\n").toUtf8();
}

QByteArray HTTPThread::square(const QByteArray &partialResponse,
                              const RequestData &requestData)
{
    if("GET" != requestData.method || !requestData.url.hasQueryItem("a")){
        return responseStatusLine.arg("400 Bad Request\r\n").toAscii();
    }

    QString numToSquare = requestData.url.queryItemValue("a");
    QString body;

    bool ok;
    double n = numToSquare.toDouble(&ok);

    if(!ok){
        body = "a-ul trebuie sa fie numar!\n";
    }
    else{
        body = numToSquare + "^2 = " + QString::number(n*n) + "\n";
    }

    return partialResponse + "\r\n" + body.toAscii();
}

QByteArray HTTPThread::login(const QByteArray &partialResponse,
                             const RequestData &requestData)
{
    QString page = "\r\n"
            "<form method=\"POST\">"
            "%1"
            "Username: <input type=\"text\" name=\"username\">"
            "Password: <input type=\"password\" name=\"pass\">"
            "<INPUT type=\"submit\" value=\"Auth\">"
            "</form>";

    if("GET" == requestData.method){
        return partialResponse + page.arg("").toAscii();
    }

    if("POST" == requestData.method && !requestData.postData.isEmpty()){
        if(requestData.postData.contains("username") &&
                "Ion" == requestData.postData["username"] &&
                requestData.postData.contains("pass") &&
                "1234" == requestData.postData["pass"]){

            return partialResponse + "Set-Cookie: loggedin=1\r\n\r\nYou're logged in!";
        }

        return partialResponse +
                page.arg("Login failed, try again!
").toAscii();
    }

    return responseStatusLine.arg("400 Bad request\r\n").toAscii();
}

QByteArray HTTPThread::check(const QByteArray &partialResponse,
                             const RequestData &requestData)
{
    if("GET" != requestData.method){
        return responseStatusLine.arg("400 Bad request\r\n").toAscii();
    }

    if(requestData.fields.contains("Cookie") &&
            "loggedin=1" == requestData.fields["Cookie"][0]){

        return partialResponse + "\r\nYou're logged in!";
    }

    return partialResponse + "\r\nYou're not logged in!";;
}
<|endoftext|>


<commit_before>#pragma once

#include "../base/assert.hpp"
#include "../base/base.hpp"
#include "../base/math.hpp"
#include "../base/stl_add.hpp"

#include "../std/iterator.hpp"

template <typename IsVisibleF>
bool FindSingleStripForIndex(size_t i, size_t n, IsVisibleF isVisible)
{
  // Searching for a strip only in a single direction, because the opposite direction
  // is traversed from the last vertex of the possible strip.
  size_t a = my::PrevModN(i, n);
  size_t b = my::NextModN(i, n);
  for (size_t j = 2; j < n; ++j)
  {
    ASSERT_NOT_EQUAL ( a, b, () );
    if (!isVisible(a, b))
      return false;
    if (j & 1)
      a = my::PrevModN(a, n);
    else
      b = my::NextModN(b, n);
  }

  ASSERT_EQUAL ( a, b, () );
  return true;
}

// If polygon with n vertices is a single strip, return the start index of the strip or n otherwise.
template <typename IsVisibleF>
size_t FindSingleStrip(size_t n, IsVisibleF isVisible)
{
  for (size_t i = 0; i < n; ++i)
  {
    if (FindSingleStripForIndex(i, n, isVisible))
      return i;
  }

  return n;
}

#ifdef DEBUG
template <typename IterT> bool TestPolygonPreconditions(IterT beg, IterT end)
{
  ASSERT_GREATER ( distance(beg, end), 2, () );
  ASSERT ( !AlmostEqual(*beg, *(--end)), () );
  return true;
}
#endif

/// Is polygon [beg, end) has CCW orientation.
template <typename IterT> bool IsPolygonCCW(IterT beg, IterT end)
{
  ASSERT ( TestPolygonPreconditions(beg, end), () );

  // find the most down (left) point
  double minY = numeric_limits<double>::max();
  IterT iRes;
  for (IterT i = beg; i != end; ++i)
  {
    if ((*i).y < minY || ((*i).y == minY && (*i).x < (*iRes).x))
    {
      iRes = i;
      minY = (*i).y;
    }
  }

  double cp = CrossProduct(*iRes - *PrevIterInCycle(iRes, beg, end),
                           *NextIterInCycle(iRes, beg, end) - *iRes);
  if (cp != 0.0)
    return (cp > 0.0);

  // fid the most up (left) point
  double maxY = numeric_limits<double>::min();
  for (IterT i = beg; i != end; ++i)
  {
    if ((*i).y > maxY || ((*i).y == maxY && (*i).x < (*iRes).x))
    {
      iRes = i;
      maxY = (*i).y;
    }
  }

  cp =  CrossProduct(*iRes - *PrevIterInCycle(iRes, beg, end),
                     *NextIterInCycle(iRes, beg, end) - *iRes);
  ASSERT_NOT_EQUAL ( cp, 0.0, () );
  return (cp > 0.0);
}

/// Is segment (v, v1) in cone (vPrev, v, vNext)?
/// @precondition Orientation CCW!!!
template <typename PointT> bool IsSegmentInCone(PointT v, PointT v1, PointT vPrev, PointT vNext)
{
  PointT const diff = v1 - v;
  PointT const edgeL = vPrev - v;
  PointT const edgeR = vNext - v;
  double const cpLR = CrossProduct(edgeR, edgeL);

  if (my::AlmostEqual(cpLR,  0.0))
  {
    // Points vPrev, v, vNext placed on one line;
    // use property that polygon has CCW orientation.
    return CrossProduct(vNext - vPrev, v1 - vPrev) > 0.0;
  }

  if (cpLR > 0)
  {
    // vertex is convex
    return CrossProduct(diff, edgeR) < 0 && CrossProduct(diff, edgeL) > 0.0;
  }
  else
  {
    // vertex is reflex
    return CrossProduct(diff, edgeR) < 0 || CrossProduct(diff, edgeL) > 0.0;
  }
}

/// Is diagonal (i0, i1) visible in polygon [beg, end).
/// @precondition Orientation CCW!!
template <typename IterT>
bool IsDiagonalVisible(IterT beg, IterT end, IterT i0, IterT i1)
{
  ASSERT ( IsPolygonCCW(beg, end), () );
  ASSERT ( TestPolygonPreconditions(beg, end), () );
  ASSERT ( i0 != i1, () );

  IterT const prev = PrevIterInCycle(i0, beg, end);
  IterT const next = NextIterInCycle(i0, beg, end);
  if (prev == i1 || next == i1)
    return true;

  if (!IsSegmentInCone(*i0, *i1, *prev, *next))
    return false;

  for (IterT j0 = beg, j1 = PrevIterInCycle(beg, beg, end); j0 != end; j1 = j0++)
    if (j0 != i0 && j0 != i1 && j1 != i0 && j1 != i1 && SegmentsIntersect(*i0, *i1, *j0, *j1))
      return false;

  return true;
}

template <typename IterT> class IsDiagonalVisibleFunctor
{
  IterT m_Beg, m_End;
public:
  IsDiagonalVisibleFunctor(IterT beg, IterT end) : m_Beg(beg), m_End(end) {}

  bool operator () (size_t a, size_t b) const
  {
    return IsDiagonalVisible(m_Beg, m_End, m_Beg + a, m_Beg + b);
  }
};

namespace detail
{
  template <typename F> class StripEmitter
  {
    F & m_f;
    int m_order;

  public:
    StripEmitter(F & f) : m_f(f), m_order(0) {}

    bool operator () (size_t a, size_t b)
    {
      if (m_order == 0)
      {
        m_f(b);
        m_f(a);
        m_order = 1;
      }
      else
      {
        m_f(m_order == 1 ? b : a);
        m_order = -m_order;
      }
      return true;
    }
  };
}

/// Make single strip for the range of points [beg, end), started with index = i.
template <typename F>
void MakeSingleStripFromIndex(size_t i, size_t n, F f)
{
  ASSERT_LESS ( i, n, () );
  f(i);
  FindSingleStripForIndex(i, n, detail::StripEmitter<F>(f));
}
<commit_msg>Add extended assert in IsPolygonCCW.<commit_after>#pragma once

#include "../base/assert.hpp"
#include "../base/base.hpp"
#include "../base/math.hpp"
#include "../base/stl_add.hpp"

#include "../std/iterator.hpp"

template <typename IsVisibleF>
bool FindSingleStripForIndex(size_t i, size_t n, IsVisibleF isVisible)
{
  // Searching for a strip only in a single direction, because the opposite direction
  // is traversed from the last vertex of the possible strip.
  size_t a = my::PrevModN(i, n);
  size_t b = my::NextModN(i, n);
  for (size_t j = 2; j < n; ++j)
  {
    ASSERT_NOT_EQUAL ( a, b, () );
    if (!isVisible(a, b))
      return false;
    if (j & 1)
      a = my::PrevModN(a, n);
    else
      b = my::NextModN(b, n);
  }

  ASSERT_EQUAL ( a, b, () );
  return true;
}

// If polygon with n vertices is a single strip, return the start index of the strip or n otherwise.
template <typename IsVisibleF>
size_t FindSingleStrip(size_t n, IsVisibleF isVisible)
{
  for (size_t i = 0; i < n; ++i)
  {
    if (FindSingleStripForIndex(i, n, isVisible))
      return i;
  }

  return n;
}

#ifdef DEBUG
template <typename IterT> bool TestPolygonPreconditions(IterT beg, IterT end)
{
  ASSERT_GREATER ( distance(beg, end), 2, () );
  ASSERT ( !AlmostEqual(*beg, *(--end)), () );
  return true;
}
#endif

/// Is polygon [beg, end) has CCW orientation.
template <typename IterT> bool IsPolygonCCW(IterT beg, IterT end)
{
  ASSERT ( TestPolygonPreconditions(beg, end), () );

  // find the most down (left) point
  double minY = numeric_limits<double>::max();
  IterT iRes;
  for (IterT i = beg; i != end; ++i)
  {
    if ((*i).y < minY || ((*i).y == minY && (*i).x < (*iRes).x))
    {
      iRes = i;
      minY = (*i).y;
    }
  }

  double cp = CrossProduct(*iRes - *PrevIterInCycle(iRes, beg, end),
                           *NextIterInCycle(iRes, beg, end) - *iRes);
  if (cp != 0.0)
    return (cp > 0.0);

  // find the most up (left) point
  double maxY = numeric_limits<double>::min();
  for (IterT i = beg; i != end; ++i)
  {
    if ((*i).y > maxY || ((*i).y == maxY && (*i).x < (*iRes).x))
    {
      iRes = i;
      maxY = (*i).y;
    }
  }

  IterT iPrev = PrevIterInCycle(iRes, beg, end);
  IterT iNext = NextIterInCycle(iRes, beg, end);
  cp =  CrossProduct(*iRes - *iPrev, *iNext - *iRes);

  ASSERT_NOT_EQUAL ( cp, 0.0, (*iPrev, *iRes, *iNext) );
  return (cp > 0.0);
}

/// Is segment (v, v1) in cone (vPrev, v, vNext)?
/// @precondition Orientation CCW!!!
template <typename PointT> bool IsSegmentInCone(PointT v, PointT v1, PointT vPrev, PointT vNext)
{
  PointT const diff = v1 - v;
  PointT const edgeL = vPrev - v;
  PointT const edgeR = vNext - v;
  double const cpLR = CrossProduct(edgeR, edgeL);

  if (my::AlmostEqual(cpLR,  0.0))
  {
    // Points vPrev, v, vNext placed on one line;
    // use property that polygon has CCW orientation.
    return CrossProduct(vNext - vPrev, v1 - vPrev) > 0.0;
  }

  if (cpLR > 0)
  {
    // vertex is convex
    return CrossProduct(diff, edgeR) < 0 && CrossProduct(diff, edgeL) > 0.0;
  }
  else
  {
    // vertex is reflex
    return CrossProduct(diff, edgeR) < 0 || CrossProduct(diff, edgeL) > 0.0;
  }
}

/// Is diagonal (i0, i1) visible in polygon [beg, end).
/// @precondition Orientation CCW!!
template <typename IterT>
bool IsDiagonalVisible(IterT beg, IterT end, IterT i0, IterT i1)
{
  ASSERT ( IsPolygonCCW(beg, end), () );
  ASSERT ( TestPolygonPreconditions(beg, end), () );
  ASSERT ( i0 != i1, () );

  IterT const prev = PrevIterInCycle(i0, beg, end);
  IterT const next = NextIterInCycle(i0, beg, end);
  if (prev == i1 || next == i1)
    return true;

  if (!IsSegmentInCone(*i0, *i1, *prev, *next))
    return false;

  for (IterT j0 = beg, j1 = PrevIterInCycle(beg, beg, end); j0 != end; j1 = j0++)
    if (j0 != i0 && j0 != i1 && j1 != i0 && j1 != i1 && SegmentsIntersect(*i0, *i1, *j0, *j1))
      return false;

  return true;
}

template <typename IterT> class IsDiagonalVisibleFunctor
{
  IterT m_Beg, m_End;
public:
  IsDiagonalVisibleFunctor(IterT beg, IterT end) : m_Beg(beg), m_End(end) {}

  bool operator () (size_t a, size_t b) const
  {
    return IsDiagonalVisible(m_Beg, m_End, m_Beg + a, m_Beg + b);
  }
};

namespace detail
{
  template <typename F> class StripEmitter
  {
    F & m_f;
    int m_order;

  public:
    StripEmitter(F & f) : m_f(f), m_order(0) {}

    bool operator () (size_t a, size_t b)
    {
      if (m_order == 0)
      {
        m_f(b);
        m_f(a);
        m_order = 1;
      }
      else
      {
        m_f(m_order == 1 ? b : a);
        m_order = -m_order;
      }
      return true;
    }
  };
}

/// Make single strip for the range of points [beg, end), started with index = i.
template <typename F>
void MakeSingleStripFromIndex(size_t i, size_t n, F f)
{
  ASSERT_LESS ( i, n, () );
  f(i);
  FindSingleStripForIndex(i, n, detail::StripEmitter<F>(f));
}
<|endoftext|>


<commit_before>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/scoped_ptr.h"
#include "media/base/data_buffer.h"
#include "media/base/mock_ffmpeg.h"
#include "media/base/mock_task.h"
#include "media/filters/ffmpeg_video_decode_engine.h"
#include "media/filters/ffmpeg_video_decoder.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"

using ::testing::_;
using ::testing::DoAll;
using ::testing::Return;
using ::testing::ReturnNull;
using ::testing::SetArgumentPointee;
using ::testing::StrictMock;

namespace media {

static const int kWidth = 320;
static const int kHeight = 240;
static const AVRational kTimeBase = { 1, 100 };

ACTION_P(SaveInitializeResult, engine) {
  engine->info_ = arg0;
}

class FFmpegVideoDecodeEngineTest : public testing::Test,
                                    public VideoDecodeEngine::EventHandler {
 protected:
  FFmpegVideoDecodeEngineTest() {
    // Setup FFmpeg structures.
    frame_buffer_.reset(new uint8[kWidth * kHeight]);
    memset(&yuv_frame_, 0, sizeof(yuv_frame_));

    // DecodeFrame will check these pointers as non-NULL value.
    yuv_frame_.data[0] = yuv_frame_.data[1] = yuv_frame_.data[2]
        = frame_buffer_.get();
    yuv_frame_.linesize[0] = kWidth;
    yuv_frame_.linesize[1] = yuv_frame_.linesize[2] = kWidth >> 1;

    memset(&codec_context_, 0, sizeof(codec_context_));
    codec_context_.width = kWidth;
    codec_context_.height = kHeight;
    codec_context_.time_base = kTimeBase;

    memset(&codec_, 0, sizeof(codec_));
    memset(&stream_, 0, sizeof(stream_));
    stream_.codec = &codec_context_;
    stream_.r_frame_rate.num = kTimeBase.den;
    stream_.r_frame_rate.den = kTimeBase.num;

    buffer_ = new DataBuffer(1);

    // Initialize MockFFmpeg.
    MockFFmpeg::set(&mock_ffmpeg_);

    test_engine_ = new FFmpegVideoDecodeEngine();
    test_engine_->SetCodecContextForTest(&codec_context_);

    VideoFrame::CreateFrame(VideoFrame::YV12,
                            kWidth,
                            kHeight,
                            StreamSample::kInvalidTimestamp,
                            StreamSample::kInvalidTimestamp,
                            &video_frame_);
  }

  ~FFmpegVideoDecodeEngineTest() {
    test_engine_ = NULL;
    MockFFmpeg::set(NULL);
  }

  void Initialize() {
    EXPECT_CALL(*MockFFmpeg::get(), AVCodecFindDecoder(CODEC_ID_NONE))
        .WillOnce(Return(&codec_));
    EXPECT_CALL(*MockFFmpeg::get(), AVCodecAllocFrame())
        .WillOnce(Return(&yuv_frame_));
    EXPECT_CALL(*MockFFmpeg::get(), AVCodecThreadInit(&codec_context_, 2))
        .WillOnce(Return(0));
    EXPECT_CALL(*MockFFmpeg::get(), AVCodecOpen(&codec_context_, &codec_))
        .WillOnce(Return(0));
    EXPECT_CALL(*MockFFmpeg::get(), AVFree(&yuv_frame_))
        .Times(1);

    config_.codec_ = kCodecH264;
    config_.opaque_context_ = &stream_;
    config_.width_ = kWidth;
    config_.height_ = kHeight;
    EXPECT_CALL(*this, OnInitializeComplete(_))
       .WillOnce(SaveInitializeResult(this));
    test_engine_->Initialize(MessageLoop::current(), this, config_);
    EXPECT_TRUE(info_.success_);
  }

 public:
  MOCK_METHOD1(OnFillBufferCallback,
               void(scoped_refptr<VideoFrame> video_frame));
  MOCK_METHOD1(OnEmptyBufferCallback,
               void(scoped_refptr<Buffer> buffer));
  MOCK_METHOD1(OnInitializeComplete,
               void(const VideoCodecInfo& info));
  MOCK_METHOD0(OnUninitializeComplete, void());
  MOCK_METHOD0(OnFlushComplete, void());
  MOCK_METHOD0(OnSeekComplete, void());
  MOCK_METHOD0(OnError, void());
  MOCK_METHOD1(OnFormatChange, void(VideoStreamInfo stream_info));

  scoped_refptr<VideoFrame> video_frame_;
  VideoCodecConfig config_;
  VideoCodecInfo info_;
 protected:
  scoped_refptr<FFmpegVideoDecodeEngine> test_engine_;
  scoped_array<uint8_t> frame_buffer_;
  StrictMock<MockFFmpeg> mock_ffmpeg_;

  AVFrame yuv_frame_;
  AVCodecContext codec_context_;
  AVStream stream_;
  AVCodec codec_;
  scoped_refptr<DataBuffer> buffer_;

};

TEST_F(FFmpegVideoDecodeEngineTest, Initialize_Normal) {
  Initialize();
}

TEST_F(FFmpegVideoDecodeEngineTest, Initialize_FindDecoderFails) {
  // Test avcodec_find_decoder() returning NULL.
  EXPECT_CALL(*MockFFmpeg::get(), AVCodecFindDecoder(CODEC_ID_NONE))
      .WillOnce(ReturnNull());
  EXPECT_CALL(*MockFFmpeg::get(), AVCodecAllocFrame())
      .WillOnce(Return(&yuv_frame_));
  EXPECT_CALL(*MockFFmpeg::get(), AVFree(&yuv_frame_))
      .Times(1);

  config_.codec_ = kCodecH264;
  config_.opaque_context_ = &stream_;
  config_.width_ = kWidth;
  config_.height_ = kHeight;
  EXPECT_CALL(*this, OnInitializeComplete(_))
     .WillOnce(SaveInitializeResult(this));
  test_engine_->Initialize(MessageLoop::current(), this, config_);
  EXPECT_FALSE(info_.success_);
}

TEST_F(FFmpegVideoDecodeEngineTest, Initialize_InitThreadFails) {
  // Test avcodec_thread_init() failing.
  EXPECT_CALL(*MockFFmpeg::get(), AVCodecFindDecoder(CODEC_ID_NONE))
      .WillOnce(Return(&codec_));
  EXPECT_CALL(*MockFFmpeg::get(), AVCodecAllocFrame())
      .WillOnce(Return(&yuv_frame_));
  EXPECT_CALL(*MockFFmpeg::get(), AVCodecThreadInit(&codec_context_, 2))
      .WillOnce(Return(-1));
  EXPECT_CALL(*MockFFmpeg::get(), AVFree(&yuv_frame_))
      .Times(1);

  config_.codec_ = kCodecH264;
  config_.opaque_context_ = &stream_;
  config_.width_ = kWidth;
  config_.height_ = kHeight;
  EXPECT_CALL(*this, OnInitializeComplete(_))
     .WillOnce(SaveInitializeResult(this));
  test_engine_->Initialize(MessageLoop::current(), this, config_);
  EXPECT_FALSE(info_.success_);
}

TEST_F(FFmpegVideoDecodeEngineTest, Initialize_OpenDecoderFails) {
  // Test avcodec_open() failing.
  EXPECT_CALL(*MockFFmpeg::get(), AVCodecFindDecoder(CODEC_ID_NONE))
      .WillOnce(Return(&codec_));
  EXPECT_CALL(*MockFFmpeg::get(), AVCodecAllocFrame())
      .WillOnce(Return(&yuv_frame_));
  EXPECT_CALL(*MockFFmpeg::get(), AVCodecThreadInit(&codec_context_, 2))
      .WillOnce(Return(0));
  EXPECT_CALL(*MockFFmpeg::get(), AVCodecOpen(&codec_context_, &codec_))
      .WillOnce(Return(-1));
  EXPECT_CALL(*MockFFmpeg::get(), AVFree(&yuv_frame_))
      .Times(1);

  config_.codec_ = kCodecH264;
  config_.opaque_context_ = &stream_;
  config_.width_ = kWidth;
  config_.height_ = kHeight;
  EXPECT_CALL(*this, OnInitializeComplete(_))
     .WillOnce(SaveInitializeResult(this));
  test_engine_->Initialize(MessageLoop::current(), this, config_);
  EXPECT_FALSE(info_.success_);
}

ACTION_P2(DemuxComplete, engine, buffer) {
  engine->EmptyThisBuffer(buffer);
}

ACTION_P(DecodeComplete, decoder) {
  decoder->video_frame_ = arg0;
}

TEST_F(FFmpegVideoDecodeEngineTest, DecodeFrame_Normal) {
  Initialize();

  // We rely on FFmpeg for timestamp and duration reporting.  The one tricky
  // bit is calculating the duration when |repeat_pict| > 0.
  const base::TimeDelta kTimestamp = base::TimeDelta::FromMicroseconds(123);
  const base::TimeDelta kDuration = base::TimeDelta::FromMicroseconds(15000);
  yuv_frame_.repeat_pict = 1;
  yuv_frame_.reordered_opaque = kTimestamp.InMicroseconds();

  // Expect a bunch of avcodec calls.
  EXPECT_CALL(mock_ffmpeg_, AVInitPacket(_));
  EXPECT_CALL(mock_ffmpeg_,
              AVCodecDecodeVideo2(&codec_context_, &yuv_frame_, _, _))
      .WillOnce(DoAll(SetArgumentPointee<2>(1),  // Simulate 1 byte frame.
                      Return(0)));

  EXPECT_CALL(*this, OnEmptyBufferCallback(_))
      .WillOnce(DemuxComplete(test_engine_.get(), buffer_));
  EXPECT_CALL(*this, OnFillBufferCallback(_))
      .WillOnce(DecodeComplete(this));
  test_engine_->FillThisBuffer(video_frame_);

  // |video_frame_| timestamp is 0 because we set the timestamp based off
  // the buffer timestamp.
  EXPECT_EQ(0, video_frame_->GetTimestamp().ToInternalValue());
  EXPECT_EQ(kDuration.ToInternalValue(),
            video_frame_->GetDuration().ToInternalValue());
}

TEST_F(FFmpegVideoDecodeEngineTest, DecodeFrame_0ByteFrame) {
  Initialize();

  // Expect a bunch of avcodec calls.
  EXPECT_CALL(mock_ffmpeg_, AVInitPacket(_))
      .Times(2);
  EXPECT_CALL(mock_ffmpeg_,
              AVCodecDecodeVideo2(&codec_context_, &yuv_frame_, _, _))
      .WillOnce(DoAll(SetArgumentPointee<2>(0),  // Simulate 0 byte frame.
                      Return(0)))
      .WillOnce(DoAll(SetArgumentPointee<2>(1),  // Simulate 1 byte frame.
                      Return(0)));

  EXPECT_CALL(*this, OnEmptyBufferCallback(_))
      .WillOnce(DemuxComplete(test_engine_.get(), buffer_))
      .WillOnce(DemuxComplete(test_engine_.get(), buffer_));
  EXPECT_CALL(*this, OnFillBufferCallback(_))
      .WillOnce(DecodeComplete(this));
  test_engine_->FillThisBuffer(video_frame_);

  EXPECT_TRUE(video_frame_.get());
}

TEST_F(FFmpegVideoDecodeEngineTest, DecodeFrame_DecodeError) {
  Initialize();

  // Expect a bunch of avcodec calls.
  EXPECT_CALL(mock_ffmpeg_, AVInitPacket(_));
  EXPECT_CALL(mock_ffmpeg_,
              AVCodecDecodeVideo2(&codec_context_, &yuv_frame_, _, _))
      .WillOnce(Return(-1));

  EXPECT_CALL(*this, OnEmptyBufferCallback(_))
      .WillOnce(DemuxComplete(test_engine_.get(), buffer_));
  EXPECT_CALL(*this, OnFillBufferCallback(_))
      .WillOnce(DecodeComplete(this));
  test_engine_->FillThisBuffer(video_frame_);

  EXPECT_FALSE(video_frame_.get());
}

TEST_F(FFmpegVideoDecodeEngineTest, GetSurfaceFormat) {
  // YV12 formats.
  codec_context_.pix_fmt = PIX_FMT_YUV420P;
  EXPECT_EQ(VideoFrame::YV12, test_engine_->GetSurfaceFormat());
  codec_context_.pix_fmt = PIX_FMT_YUVJ420P;
  EXPECT_EQ(VideoFrame::YV12, test_engine_->GetSurfaceFormat());

  // YV16 formats.
  codec_context_.pix_fmt = PIX_FMT_YUV422P;
  EXPECT_EQ(VideoFrame::YV16, test_engine_->GetSurfaceFormat());
  codec_context_.pix_fmt = PIX_FMT_YUVJ422P;
  EXPECT_EQ(VideoFrame::YV16, test_engine_->GetSurfaceFormat());

  // Invalid value.
  codec_context_.pix_fmt = PIX_FMT_NONE;
  EXPECT_EQ(VideoFrame::INVALID, test_engine_->GetSurfaceFormat());
}

}  // namespace media
<commit_msg>there are 2 threads for AVCodecThreadInit BUG=NONE TEST=NONE<commit_after>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/scoped_ptr.h"
#include "media/base/data_buffer.h"
#include "media/base/mock_ffmpeg.h"
#include "media/base/mock_task.h"
#include "media/filters/ffmpeg_video_decode_engine.h"
#include "media/filters/ffmpeg_video_decoder.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"

using ::testing::_;
using ::testing::DoAll;
using ::testing::Return;
using ::testing::ReturnNull;
using ::testing::SetArgumentPointee;
using ::testing::StrictMock;

namespace media {

static const int kWidth = 320;
static const int kHeight = 240;
static const AVRational kTimeBase = { 1, 100 };

ACTION_P(SaveInitializeResult, engine) {
  engine->info_ = arg0;
}

class FFmpegVideoDecodeEngineTest : public testing::Test,
                                    public VideoDecodeEngine::EventHandler {
 protected:
  FFmpegVideoDecodeEngineTest() {
    // Setup FFmpeg structures.
    frame_buffer_.reset(new uint8[kWidth * kHeight]);
    memset(&yuv_frame_, 0, sizeof(yuv_frame_));

    // DecodeFrame will check these pointers as non-NULL value.
    yuv_frame_.data[0] = yuv_frame_.data[1] = yuv_frame_.data[2]
        = frame_buffer_.get();
    yuv_frame_.linesize[0] = kWidth;
    yuv_frame_.linesize[1] = yuv_frame_.linesize[2] = kWidth >> 1;

    memset(&codec_context_, 0, sizeof(codec_context_));
    codec_context_.width = kWidth;
    codec_context_.height = kHeight;
    codec_context_.time_base = kTimeBase;

    memset(&codec_, 0, sizeof(codec_));
    memset(&stream_, 0, sizeof(stream_));
    stream_.codec = &codec_context_;
    stream_.r_frame_rate.num = kTimeBase.den;
    stream_.r_frame_rate.den = kTimeBase.num;

    buffer_ = new DataBuffer(1);

    // Initialize MockFFmpeg.
    MockFFmpeg::set(&mock_ffmpeg_);

    test_engine_ = new FFmpegVideoDecodeEngine();
    test_engine_->SetCodecContextForTest(&codec_context_);

    VideoFrame::CreateFrame(VideoFrame::YV12,
                            kWidth,
                            kHeight,
                            StreamSample::kInvalidTimestamp,
                            StreamSample::kInvalidTimestamp,
                            &video_frame_);
  }

  ~FFmpegVideoDecodeEngineTest() {
    test_engine_ = NULL;
    MockFFmpeg::set(NULL);
  }

  void Initialize() {
    EXPECT_CALL(*MockFFmpeg::get(), AVCodecFindDecoder(CODEC_ID_NONE))
        .WillOnce(Return(&codec_));
    EXPECT_CALL(*MockFFmpeg::get(), AVCodecAllocFrame())
        .WillOnce(Return(&yuv_frame_));
    EXPECT_CALL(*MockFFmpeg::get(), AVCodecThreadInit(&codec_context_, 2))
        .WillOnce(Return(0));
    EXPECT_CALL(*MockFFmpeg::get(), AVCodecOpen(&codec_context_, &codec_))
        .WillOnce(Return(0));
    EXPECT_CALL(*MockFFmpeg::get(), AVFree(&yuv_frame_))
        .Times(1);

    config_.codec_ = kCodecH264;
    config_.opaque_context_ = &stream_;
    config_.width_ = kWidth;
    config_.height_ = kHeight;
    EXPECT_CALL(*this, OnInitializeComplete(_))
       .WillOnce(SaveInitializeResult(this));
    test_engine_->Initialize(MessageLoop::current(), this, config_);
    EXPECT_TRUE(info_.success_);
  }

 public:
  MOCK_METHOD1(OnFillBufferCallback,
               void(scoped_refptr<VideoFrame> video_frame));
  MOCK_METHOD1(OnEmptyBufferCallback,
               void(scoped_refptr<Buffer> buffer));
  MOCK_METHOD1(OnInitializeComplete,
               void(const VideoCodecInfo& info));
  MOCK_METHOD0(OnUninitializeComplete, void());
  MOCK_METHOD0(OnFlushComplete, void());
  MOCK_METHOD0(OnSeekComplete, void());
  MOCK_METHOD0(OnError, void());
  MOCK_METHOD1(OnFormatChange, void(VideoStreamInfo stream_info));

  scoped_refptr<VideoFrame> video_frame_;
  VideoCodecConfig config_;
  VideoCodecInfo info_;
 protected:
  scoped_refptr<FFmpegVideoDecodeEngine> test_engine_;
  scoped_array<uint8_t> frame_buffer_;
  StrictMock<MockFFmpeg> mock_ffmpeg_;

  AVFrame yuv_frame_;
  AVCodecContext codec_context_;
  AVStream stream_;
  AVCodec codec_;
  scoped_refptr<DataBuffer> buffer_;

};

TEST_F(FFmpegVideoDecodeEngineTest, Initialize_Normal) {
  Initialize();
}

TEST_F(FFmpegVideoDecodeEngineTest, Initialize_FindDecoderFails) {
  // Test avcodec_find_decoder() returning NULL.
  EXPECT_CALL(*MockFFmpeg::get(), AVCodecFindDecoder(CODEC_ID_NONE))
      .WillOnce(ReturnNull());
  EXPECT_CALL(*MockFFmpeg::get(), AVCodecAllocFrame())
      .WillOnce(Return(&yuv_frame_));
  EXPECT_CALL(*MockFFmpeg::get(), AVFree(&yuv_frame_))
      .Times(1);

  config_.codec_ = kCodecH264;
  config_.opaque_context_ = &stream_;
  config_.width_ = kWidth;
  config_.height_ = kHeight;
  EXPECT_CALL(*this, OnInitializeComplete(_))
     .WillOnce(SaveInitializeResult(this));
  test_engine_->Initialize(MessageLoop::current(), this, config_);
  EXPECT_FALSE(info_.success_);
}

// Note There are 2 threads for FFmpeg-mt.
TEST_F(FFmpegVideoDecodeEngineTest, Initialize_InitThreadFails) {
  // Test avcodec_thread_init() failing.
  EXPECT_CALL(*MockFFmpeg::get(), AVCodecFindDecoder(CODEC_ID_NONE))
      .WillOnce(Return(&codec_));
  EXPECT_CALL(*MockFFmpeg::get(), AVCodecAllocFrame())
      .WillOnce(Return(&yuv_frame_));
  EXPECT_CALL(*MockFFmpeg::get(), AVCodecThreadInit(&codec_context_, 2))
      .WillOnce(Return(-1));
  EXPECT_CALL(*MockFFmpeg::get(), AVFree(&yuv_frame_))
      .Times(1);

  config_.codec_ = kCodecH264;
  config_.opaque_context_ = &stream_;
  config_.width_ = kWidth;
  config_.height_ = kHeight;
  EXPECT_CALL(*this, OnInitializeComplete(_))
     .WillOnce(SaveInitializeResult(this));
  test_engine_->Initialize(MessageLoop::current(), this, config_);
  EXPECT_FALSE(info_.success_);
}

TEST_F(FFmpegVideoDecodeEngineTest, Initialize_OpenDecoderFails) {
  // Test avcodec_open() failing.
  EXPECT_CALL(*MockFFmpeg::get(), AVCodecFindDecoder(CODEC_ID_NONE))
      .WillOnce(Return(&codec_));
  EXPECT_CALL(*MockFFmpeg::get(), AVCodecAllocFrame())
      .WillOnce(Return(&yuv_frame_));
  EXPECT_CALL(*MockFFmpeg::get(), AVCodecThreadInit(&codec_context_, 2))
      .WillOnce(Return(0));
  EXPECT_CALL(*MockFFmpeg::get(), AVCodecOpen(&codec_context_, &codec_))
      .WillOnce(Return(-1));
  EXPECT_CALL(*MockFFmpeg::get(), AVFree(&yuv_frame_))
      .Times(1);

  config_.codec_ = kCodecH264;
  config_.opaque_context_ = &stream_;
  config_.width_ = kWidth;
  config_.height_ = kHeight;
  EXPECT_CALL(*this, OnInitializeComplete(_))
     .WillOnce(SaveInitializeResult(this));
  test_engine_->Initialize(MessageLoop::current(), this, config_);
  EXPECT_FALSE(info_.success_);
}

ACTION_P2(DemuxComplete, engine, buffer) {
  engine->EmptyThisBuffer(buffer);
}

ACTION_P(DecodeComplete, decoder) {
  decoder->video_frame_ = arg0;
}

TEST_F(FFmpegVideoDecodeEngineTest, DecodeFrame_Normal) {
  Initialize();

  // We rely on FFmpeg for timestamp and duration reporting.  The one tricky
  // bit is calculating the duration when |repeat_pict| > 0.
  const base::TimeDelta kTimestamp = base::TimeDelta::FromMicroseconds(123);
  const base::TimeDelta kDuration = base::TimeDelta::FromMicroseconds(15000);
  yuv_frame_.repeat_pict = 1;
  yuv_frame_.reordered_opaque = kTimestamp.InMicroseconds();

  // Expect a bunch of avcodec calls.
  EXPECT_CALL(mock_ffmpeg_, AVInitPacket(_));
  EXPECT_CALL(mock_ffmpeg_,
              AVCodecDecodeVideo2(&codec_context_, &yuv_frame_, _, _))
      .WillOnce(DoAll(SetArgumentPointee<2>(1),  // Simulate 1 byte frame.
                      Return(0)));

  EXPECT_CALL(*this, OnEmptyBufferCallback(_))
      .WillOnce(DemuxComplete(test_engine_.get(), buffer_));
  EXPECT_CALL(*this, OnFillBufferCallback(_))
      .WillOnce(DecodeComplete(this));
  test_engine_->FillThisBuffer(video_frame_);

  // |video_frame_| timestamp is 0 because we set the timestamp based off
  // the buffer timestamp.
  EXPECT_EQ(0, video_frame_->GetTimestamp().ToInternalValue());
  EXPECT_EQ(kDuration.ToInternalValue(),
            video_frame_->GetDuration().ToInternalValue());
}

TEST_F(FFmpegVideoDecodeEngineTest, DecodeFrame_0ByteFrame) {
  Initialize();

  // Expect a bunch of avcodec calls.
  EXPECT_CALL(mock_ffmpeg_, AVInitPacket(_))
      .Times(2);
  EXPECT_CALL(mock_ffmpeg_,
              AVCodecDecodeVideo2(&codec_context_, &yuv_frame_, _, _))
      .WillOnce(DoAll(SetArgumentPointee<2>(0),  // Simulate 0 byte frame.
                      Return(0)))
      .WillOnce(DoAll(SetArgumentPointee<2>(1),  // Simulate 1 byte frame.
                      Return(0)));

  EXPECT_CALL(*this, OnEmptyBufferCallback(_))
      .WillOnce(DemuxComplete(test_engine_.get(), buffer_))
      .WillOnce(DemuxComplete(test_engine_.get(), buffer_));
  EXPECT_CALL(*this, OnFillBufferCallback(_))
      .WillOnce(DecodeComplete(this));
  test_engine_->FillThisBuffer(video_frame_);

  EXPECT_TRUE(video_frame_.get());
}

TEST_F(FFmpegVideoDecodeEngineTest, DecodeFrame_DecodeError) {
  Initialize();

  // Expect a bunch of avcodec calls.
  EXPECT_CALL(mock_ffmpeg_, AVInitPacket(_));
  EXPECT_CALL(mock_ffmpeg_,
              AVCodecDecodeVideo2(&codec_context_, &yuv_frame_, _, _))
      .WillOnce(Return(-1));

  EXPECT_CALL(*this, OnEmptyBufferCallback(_))
      .WillOnce(DemuxComplete(test_engine_.get(), buffer_));
  EXPECT_CALL(*this, OnFillBufferCallback(_))
      .WillOnce(DecodeComplete(this));
  test_engine_->FillThisBuffer(video_frame_);

  EXPECT_FALSE(video_frame_.get());
}

TEST_F(FFmpegVideoDecodeEngineTest, GetSurfaceFormat) {
  // YV12 formats.
  codec_context_.pix_fmt = PIX_FMT_YUV420P;
  EXPECT_EQ(VideoFrame::YV12, test_engine_->GetSurfaceFormat());
  codec_context_.pix_fmt = PIX_FMT_YUVJ420P;
  EXPECT_EQ(VideoFrame::YV12, test_engine_->GetSurfaceFormat());

  // YV16 formats.
  codec_context_.pix_fmt = PIX_FMT_YUV422P;
  EXPECT_EQ(VideoFrame::YV16, test_engine_->GetSurfaceFormat());
  codec_context_.pix_fmt = PIX_FMT_YUVJ422P;
  EXPECT_EQ(VideoFrame::YV16, test_engine_->GetSurfaceFormat());

  // Invalid value.
  codec_context_.pix_fmt = PIX_FMT_NONE;
  EXPECT_EQ(VideoFrame::INVALID, test_engine_->GetSurfaceFormat());
}

}  // namespace media
<|endoftext|>


<commit_before>/**************************************************
 * Source Code for the Original Compiler for the
 * Programming Language Wake
 *
 * OtherStatement.cpp
 *
 * Licensed under the MIT license
 * See LICENSE.TXT for details
 *
 * Author: Michael Fairhurst
 * Revised By:
 *
 **************************************************/

#include "type.h"
#include "TypeAnalyzer.h"
#include "TypeParameterizer.h"
#include "ClassSpaceSymbolTable.h"
#include "ast/StatementNode.h"
#include "ast/OtherStatement.h"

void wake::ast::OtherStatement::typeCheck() {
	switch(tree->node_type) {
		// Ignoring these for now
		case NT_SWITCH:
		case NT_CURRIED:
		case NT_INCREMENT:
		case NT_DECREMENT:
		// These require a common-ancestor function
		case NT_TYPE_ARRAY:
		case NT_VALUES:
			throw string("Not supported yet");

		// These have tests so can't throw, but won't compile anyway as long as switch throws
		case NT_DEFAULTCASE:
		case NT_CASE:

		// these don't have types
		case NT_BLOCK:
		case NT_TRY:
			scopesymtable->pushScope();
			// FALL THROUGH!
		case NT_RETRIEVALS_STATEMENTS:
		case NT_BREAK:
		case NT_CONTINUE:
			try {
				for(boost::ptr_vector<StatementNode>::iterator it = children.begin(); it != children.end(); ++it) {
					it->typeCheck();
				}
				if(tree->node_type == NT_BLOCK || tree->node_type == NT_TRY) scopesymtable->popScope();
			} catch(SemanticError *e) {
				if(tree->node_type == NT_BLOCK || tree->node_type == NT_TRY) scopesymtable->popScope();
				throw e;
			}
	}
}
<commit_msg>Typecheck the expressions in a for loop incr<commit_after>/**************************************************
 * Source Code for the Original Compiler for the
 * Programming Language Wake
 *
 * OtherStatement.cpp
 *
 * Licensed under the MIT license
 * See LICENSE.TXT for details
 *
 * Author: Michael Fairhurst
 * Revised By:
 *
 **************************************************/

#include "type.h"
#include "TypeAnalyzer.h"
#include "TypeParameterizer.h"
#include "ClassSpaceSymbolTable.h"
#include "ast/StatementNode.h"
#include "ast/OtherStatement.h"

void wake::ast::OtherStatement::typeCheck() {
	switch(tree->node_type) {
		// Ignoring these for now
		case NT_SWITCH:
		case NT_CURRIED:
		case NT_INCREMENT:
		case NT_DECREMENT:
		// These require a common-ancestor function
		case NT_TYPE_ARRAY:
		case NT_VALUES:
			throw string("Not supported yet");

		// These have tests so can't throw, but won't compile anyway as long as switch throws
		case NT_DEFAULTCASE:
		case NT_CASE:

		// these don't have types
		case NT_BLOCK:
		case NT_TRY:
			scopesymtable->pushScope();
			// FALL THROUGH!
		case NT_RETRIEVALS_STATEMENTS:
		case NT_EXPRESSIONS:
		case NT_BREAK:
		case NT_CONTINUE:
			try {
				for(boost::ptr_vector<StatementNode>::iterator it = children.begin(); it != children.end(); ++it) {
					it->typeCheck();
				}
				if(tree->node_type == NT_BLOCK || tree->node_type == NT_TRY) scopesymtable->popScope();
			} catch(SemanticError *e) {
				if(tree->node_type == NT_BLOCK || tree->node_type == NT_TRY) scopesymtable->popScope();
				throw e;
			}
	}
}
<|endoftext|>


<commit_before>// Copyright 2015 Alessio Sclocco <a.sclocco@vu.nl>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <string>
#include <map>
#include <vector>
#include <fstream>

#include <Observation.hpp>
#include <utils.hpp>

#ifndef INTEGRATION_HPP
#define INTEGRATION_HPP

namespace PulsarSearch {

class integrationSamplesDMsConf {
public:
  integrationSamplesDMsConf();
  ~integrationSamplesDMsConf();
  // Get
  unsigned int getNrSamplesPerBlock() const;
  unsigned int getNrSamplesPerThread() const;
  // Set
  void setNrSamplesPerBlock(unsigned int samples);
  void setNrSamplesPerThread(unsigned int samples);
  // utils
  std::string print() const;
private:
  unsigned int nrSamplesPerBlock;
  unsigned int nrSamplesPerThread;
};

typedef std::map< std::string, std::map < unsigned int, std::map< unsigned int, PulsarSearch::integrationSamplesDMsConf > > > tunedIntegrationSamplesDMsConf;

// Sequential
template< typename T > void integrationSamplesDMs(const AstroData::Observation & observation, const unsigned int integration, const unsigned int padding, const std::vector< T > & input, std::vector< T > & output);
// OpenCL
template< typename T > std::string * getIntegrationSamplesDMsOpenCL(const integrationSamplesDMsConf & conf, const AstroData::Observation & observation, const std::string & inputDataName, const unsigned int integration, const unsigned int padding);
// Read configuration files
void readTunedIntegrationSamplesDMsConf(tunedIntegrationSamplesDMsConf & tunedConf, const std::string & confFilename);

// Implementations
inline unsigned int integrationSamplesDMsConf::getNrSamplesPerBlock() const {
  return nrSamplesPerBlock;
}

inline unsigned int integrationSamplesDMsConf::getNrSamplesPerThread() const {
  return nrSamplesPerThread;
}

inline void integrationSamplesDMsConf::setNrSamplesPerBlock(unsigned int samples) {
  nrSamplesPerBlock = samples;
}

inline void integrationSamplesDMsConf::setNrSamplesPerThread(unsigned int samples) {
  nrSamplesPerThread = samples;
}

template< typename T > void integrationSamplesDMs(const AstroData::Observation & observation, const unsigned int integration, const unsigned int padding, const std::vector< T > & input, std::vector< T > & output) {
  for ( unsigned int dm = 0; dm < observation.getNrDMs(); dm++ ) {
    for ( unsigned int sample = 0; sample < observation.getNrSamplesPerSecond(); sample += integration ) {
      T integratedSample = 0;

      for ( unsigned int i = 0; i < integration; i++ ) {
        integratedSample += input[(dm * observation.getNrSamplesPerPaddedSecond(padding / sizeof(T))) + (sample + i)];
      }
      output[(dm * isa::utils::pad(observation.getNrSamplesPerSecond() / integration, padding / sizeof(T))) + (sample / integration)] = integratedSample / integration;
    }
  }
}

template< typename T > std::string * getIntegrationSamplesDMsOpenCL(const integrationSamplesDMsConf & conf, const AstroData::Observation & observation, const std::string & dataName, const unsigned int integration, const unsigned int padding) {
  std::string * code = new std::string();

  // Begin kernel's template
  *code = "__kernel void integrationSamplesDMs" + isa::utils::toString(integration) + "(__global const " + dataName + " * const restrict input, __global " + dataName + " * const restrict output) {\n"
    "unsigned int dm = get_group_id(1);\n"
    "__local " + dataName + " buffer[" + isa::utils::toString(integration * conf.getNrSamplesPerThread()) + "];\n"
    "<%DEFS%>"
    "\n"
    "// Load local memory\n"
    "unsigned int inLocalMemory = get_local_id(0);\n"
    "unsigned int inGlobalMemory = get_local_id(0) + (get_group_id(0) * " + isa::utils::toString(integration * conf.getNrSamplesPerThread()) + ");\n"
    "while ( inLocalMemory < " + isa::utils::toString(integration * conf.getNrSamplesPerThread()) + " ) {\n"
    "buffer[inLocalMemory] = input[(dm * " + isa::utils::toString(observation.getNrSamplesPerPaddedSecond(padding / sizeof(T))) + ") + inGlobalMemory];\n"
    "inGlobalMemory += " + isa::utils::toString(conf.getNrSamplesPerBlock()) + ";\n"
    "inLocalMemory += " + isa::utils::toString(conf.getNrSamplesPerBlock()) + ";\n"
    "}\n"
    "<%LOAD%>"
    "barrier(CLK_LOCAL_MEM_FENCE);\n"
    "// Reduce\n"
    "unsigned int threshold = " + isa::utils::toString(integration / 2) + ";\n"
    "for ( unsigned int sample = get_local_id(0); threshold > 0; threshold /= 2 ) {\n"
    "if ( sample < threshold ) {\n"
    "<%REDUCE%>"
    "}\n"
    "barrier(CLK_LOCAL_MEM_FENCE);\n"
    "}\n"
    "if ( get_local_id(0) < " + isa::utils::toString(conf.getNrSamplesPerThread()) + " ) {\n";
  if ( dataName == "float" ) {
    *code += "output[(dm * " + isa::utils::toString(isa::utils::pad(observation.getNrSamplesPerSecond() / integration, padding / sizeof(T))) + ") + ((get_group_id(0) * " + isa::utils::toString(conf.getNrSamplesPerThread()) + ") + get_local_id(0))] = buffer[get_local_id(0) * " + isa::utils::toString(integration) + "] * " + isa::utils::toString(1.0f / integration) + "f;\n";
  } else if ( dataName == "double" ) {
    *code += "output[(dm * " + isa::utils::toString(isa::utils::pad(observation.getNrSamplesPerSecond() / integration, padding / sizeof(T))) + ") + ((get_group_id(0) * " + isa::utils::toString(conf.getNrSamplesPerThread()) + ") + get_local_id(0))] = buffer[get_local_id(0) * " + isa::utils::toString(integration) + "] * " + isa::utils::toString(1.0 / integration) + ";\n";
  } else {
    *code += "output[(dm * " + isa::utils::toString(isa::utils::pad(observation.getNrSamplesPerSecond() / integration, padding / sizeof(T))) + ") + ((get_group_id(0) * " + isa::utils::toString(conf.getNrSamplesPerThread()) + ") + get_local_id(0))] = buffer[get_local_id(0) * " + isa::utils::toString(integration) + "] / " + isa::utils::toString(integration) + ";\n";
  }
  *code += "}\n"
    "}\n";
  std::string defs_sTemplate = dataName + " integratedSample<%NUM%> = 0;\n";
  std::string load_sTemplate = "integratedSample<%NUM%> = buffer[get_local_id(0) + <%OFFSET%>];\n"
  std::string reduce_sTemplate = "integratedSample<%NUM%> += buffer[(sample + <%OFFSET%>) + threshold];\n"
    "buffer[sample + <%OFFSET%>] = integratedSample<%NUM%>;\n";
  // End kernel's template

  std::string * defs_s = new std::string();
  std::string * load_s = new std::string();
  std::string * reduce_s = new std::string();

  for ( unsigned int sample = 0; sample < conf.getNrSamplesPerThread(); sample++ ) {
    std::string sample_s = isa::utils::toString(sample);
    std::string offset_s = isa::utils::toString(sample * integration);
    std::string * temp = 0;

    temp = isa::utils::replace(&defs_sTemplate, "<%NUM%>", sample_s);
    defs_s->append(*temp);
    delete temp;
    temp = isa::utils::replace(&load_sTemplate, "<%NUM%>", sample_s);
    if ( sample == 0 ) {
      std::string empty_s("");
      temp = isa::utils::replace(temp, " + <%OFFSET%>", empty_s, true);
    } else {
      temp = isa::utils::replace(temp, "<%OFFSET%>", offset_s, true);
    }
    load_s->append(*temp);
    delete temp;
    temp = isa::utils::replace(&reduce_sTemplate, "<%NUM%>", sample_s);
    if ( sample == 0 ) {
      std::string empty_s("");
      temp = isa::utils::replace(temp, " + <%OFFSET%>", empty_s, true);
    } else {
      temp = isa::utils::replace(temp, "<%OFFSET%>", offset_s, true);
    }
    reduce_s->append(*temp);
    delete temp;
  }
  code = isa::utils::replace(code, "<%DEFS%>", *defs_s, true);
  code = isa::utils::replace(code, "<%LOAD%>", *load_s, true);
  code = isa::utils::replace(code, "<%REDUCE%>", *reduce_s, true);
  delete defs_s;
  delete reduce_s;

  return code;
}

} // PulsarSearch

#endif // INTEGRATION_HPP

<commit_msg>Typo.<commit_after>// Copyright 2015 Alessio Sclocco <a.sclocco@vu.nl>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <string>
#include <map>
#include <vector>
#include <fstream>

#include <Observation.hpp>
#include <utils.hpp>

#ifndef INTEGRATION_HPP
#define INTEGRATION_HPP

namespace PulsarSearch {

class integrationSamplesDMsConf {
public:
  integrationSamplesDMsConf();
  ~integrationSamplesDMsConf();
  // Get
  unsigned int getNrSamplesPerBlock() const;
  unsigned int getNrSamplesPerThread() const;
  // Set
  void setNrSamplesPerBlock(unsigned int samples);
  void setNrSamplesPerThread(unsigned int samples);
  // utils
  std::string print() const;
private:
  unsigned int nrSamplesPerBlock;
  unsigned int nrSamplesPerThread;
};

typedef std::map< std::string, std::map < unsigned int, std::map< unsigned int, PulsarSearch::integrationSamplesDMsConf > > > tunedIntegrationSamplesDMsConf;

// Sequential
template< typename T > void integrationSamplesDMs(const AstroData::Observation & observation, const unsigned int integration, const unsigned int padding, const std::vector< T > & input, std::vector< T > & output);
// OpenCL
template< typename T > std::string * getIntegrationSamplesDMsOpenCL(const integrationSamplesDMsConf & conf, const AstroData::Observation & observation, const std::string & inputDataName, const unsigned int integration, const unsigned int padding);
// Read configuration files
void readTunedIntegrationSamplesDMsConf(tunedIntegrationSamplesDMsConf & tunedConf, const std::string & confFilename);

// Implementations
inline unsigned int integrationSamplesDMsConf::getNrSamplesPerBlock() const {
  return nrSamplesPerBlock;
}

inline unsigned int integrationSamplesDMsConf::getNrSamplesPerThread() const {
  return nrSamplesPerThread;
}

inline void integrationSamplesDMsConf::setNrSamplesPerBlock(unsigned int samples) {
  nrSamplesPerBlock = samples;
}

inline void integrationSamplesDMsConf::setNrSamplesPerThread(unsigned int samples) {
  nrSamplesPerThread = samples;
}

template< typename T > void integrationSamplesDMs(const AstroData::Observation & observation, const unsigned int integration, const unsigned int padding, const std::vector< T > & input, std::vector< T > & output) {
  for ( unsigned int dm = 0; dm < observation.getNrDMs(); dm++ ) {
    for ( unsigned int sample = 0; sample < observation.getNrSamplesPerSecond(); sample += integration ) {
      T integratedSample = 0;

      for ( unsigned int i = 0; i < integration; i++ ) {
        integratedSample += input[(dm * observation.getNrSamplesPerPaddedSecond(padding / sizeof(T))) + (sample + i)];
      }
      output[(dm * isa::utils::pad(observation.getNrSamplesPerSecond() / integration, padding / sizeof(T))) + (sample / integration)] = integratedSample / integration;
    }
  }
}

template< typename T > std::string * getIntegrationSamplesDMsOpenCL(const integrationSamplesDMsConf & conf, const AstroData::Observation & observation, const std::string & dataName, const unsigned int integration, const unsigned int padding) {
  std::string * code = new std::string();

  // Begin kernel's template
  *code = "__kernel void integrationSamplesDMs" + isa::utils::toString(integration) + "(__global const " + dataName + " * const restrict input, __global " + dataName + " * const restrict output) {\n"
    "unsigned int dm = get_group_id(1);\n"
    "__local " + dataName + " buffer[" + isa::utils::toString(integration * conf.getNrSamplesPerThread()) + "];\n"
    "<%DEFS%>"
    "\n"
    "// Load local memory\n"
    "unsigned int inLocalMemory = get_local_id(0);\n"
    "unsigned int inGlobalMemory = get_local_id(0) + (get_group_id(0) * " + isa::utils::toString(integration * conf.getNrSamplesPerThread()) + ");\n"
    "while ( inLocalMemory < " + isa::utils::toString(integration * conf.getNrSamplesPerThread()) + " ) {\n"
    "buffer[inLocalMemory] = input[(dm * " + isa::utils::toString(observation.getNrSamplesPerPaddedSecond(padding / sizeof(T))) + ") + inGlobalMemory];\n"
    "inGlobalMemory += " + isa::utils::toString(conf.getNrSamplesPerBlock()) + ";\n"
    "inLocalMemory += " + isa::utils::toString(conf.getNrSamplesPerBlock()) + ";\n"
    "}\n"
    "<%LOAD%>"
    "barrier(CLK_LOCAL_MEM_FENCE);\n"
    "// Reduce\n"
    "unsigned int threshold = " + isa::utils::toString(integration / 2) + ";\n"
    "for ( unsigned int sample = get_local_id(0); threshold > 0; threshold /= 2 ) {\n"
    "if ( sample < threshold ) {\n"
    "<%REDUCE%>"
    "}\n"
    "barrier(CLK_LOCAL_MEM_FENCE);\n"
    "}\n"
    "if ( get_local_id(0) < " + isa::utils::toString(conf.getNrSamplesPerThread()) + " ) {\n";
  if ( dataName == "float" ) {
    *code += "output[(dm * " + isa::utils::toString(isa::utils::pad(observation.getNrSamplesPerSecond() / integration, padding / sizeof(T))) + ") + ((get_group_id(0) * " + isa::utils::toString(conf.getNrSamplesPerThread()) + ") + get_local_id(0))] = buffer[get_local_id(0) * " + isa::utils::toString(integration) + "] * " + isa::utils::toString(1.0f / integration) + "f;\n";
  } else if ( dataName == "double" ) {
    *code += "output[(dm * " + isa::utils::toString(isa::utils::pad(observation.getNrSamplesPerSecond() / integration, padding / sizeof(T))) + ") + ((get_group_id(0) * " + isa::utils::toString(conf.getNrSamplesPerThread()) + ") + get_local_id(0))] = buffer[get_local_id(0) * " + isa::utils::toString(integration) + "] * " + isa::utils::toString(1.0 / integration) + ";\n";
  } else {
    *code += "output[(dm * " + isa::utils::toString(isa::utils::pad(observation.getNrSamplesPerSecond() / integration, padding / sizeof(T))) + ") + ((get_group_id(0) * " + isa::utils::toString(conf.getNrSamplesPerThread()) + ") + get_local_id(0))] = buffer[get_local_id(0) * " + isa::utils::toString(integration) + "] / " + isa::utils::toString(integration) + ";\n";
  }
  *code += "}\n"
    "}\n";
  std::string defs_sTemplate = dataName + " integratedSample<%NUM%> = 0;\n";
  std::string load_sTemplate = "integratedSample<%NUM%> = buffer[get_local_id(0) + <%OFFSET%>];\n";
  std::string reduce_sTemplate = "integratedSample<%NUM%> += buffer[(sample + <%OFFSET%>) + threshold];\n"
    "buffer[sample + <%OFFSET%>] = integratedSample<%NUM%>;\n";
  // End kernel's template

  std::string * defs_s = new std::string();
  std::string * load_s = new std::string();
  std::string * reduce_s = new std::string();

  for ( unsigned int sample = 0; sample < conf.getNrSamplesPerThread(); sample++ ) {
    std::string sample_s = isa::utils::toString(sample);
    std::string offset_s = isa::utils::toString(sample * integration);
    std::string * temp = 0;

    temp = isa::utils::replace(&defs_sTemplate, "<%NUM%>", sample_s);
    defs_s->append(*temp);
    delete temp;
    temp = isa::utils::replace(&load_sTemplate, "<%NUM%>", sample_s);
    if ( sample == 0 ) {
      std::string empty_s("");
      temp = isa::utils::replace(temp, " + <%OFFSET%>", empty_s, true);
    } else {
      temp = isa::utils::replace(temp, "<%OFFSET%>", offset_s, true);
    }
    load_s->append(*temp);
    delete temp;
    temp = isa::utils::replace(&reduce_sTemplate, "<%NUM%>", sample_s);
    if ( sample == 0 ) {
      std::string empty_s("");
      temp = isa::utils::replace(temp, " + <%OFFSET%>", empty_s, true);
    } else {
      temp = isa::utils::replace(temp, "<%OFFSET%>", offset_s, true);
    }
    reduce_s->append(*temp);
    delete temp;
  }
  code = isa::utils::replace(code, "<%DEFS%>", *defs_s, true);
  code = isa::utils::replace(code, "<%LOAD%>", *load_s, true);
  code = isa::utils::replace(code, "<%REDUCE%>", *reduce_s, true);
  delete defs_s;
  delete reduce_s;

  return code;
}

} // PulsarSearch

#endif // INTEGRATION_HPP

<|endoftext|>


<commit_before>#include "AlignmentOffsets.hpp"

#include <iostream>

void AlignmentOffsets::update_offset(int32_t const& opcode, uint32_t const& oplen) {
    //This code from SAMBLASTER
    if (opcode == BAM_CMATCH || opcode == BAM_CEQUAL || opcode == BAM_CDIFF) {
        raLen += oplen;
        qaLen += oplen;
        first = false;
    }
    else if (opcode == BAM_CSOFT_CLIP || opcode == BAM_CHARD_CLIP) {
        if (first) {
            sclip += oplen;
        }
        else {
            eclip += oplen;
        }
    }
    else if (opcode == BAM_CDEL || opcode == BAM_CREF_SKIP) {
        raLen += oplen;
    }
    else if (opcode == BAM_CINS)
    {
        qaLen += oplen;
    }
    else
    {
        // XXX This should be an exception
        std::cerr << "Unknown opcode '" << opcode << "%c'\n";
    }
}
<commit_msg>throw exception<commit_after>#include "AlignmentOffsets.hpp"

#include <boost/format.hpp>

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

using boost::format;

void AlignmentOffsets::update_offset(int32_t const& opcode, uint32_t const& oplen) {
    //This code from SAMBLASTER
    if (opcode == BAM_CMATCH || opcode == BAM_CEQUAL || opcode == BAM_CDIFF) {
        raLen += oplen;
        qaLen += oplen;
        first = false;
    }
    else if (opcode == BAM_CSOFT_CLIP || opcode == BAM_CHARD_CLIP) {
        if (first) {
            sclip += oplen;
        }
        else {
            eclip += oplen;
        }
    }
    else if (opcode == BAM_CDEL || opcode == BAM_CREF_SKIP) {
        raLen += oplen;
    }
    else if (opcode == BAM_CINS)
    {
        qaLen += oplen;
    }
    else
    {
        throw std::runtime_error(str(format(
                        "Unknown opcode %1%") % bam_cigar_opchr(opcode)));
    }
}
<|endoftext|>


<commit_before>// This file was automatically generated on 03 Feb 2016 at 00:06:56

/*
	Nazara Engine - Core module

	Copyright (C) 2015 Jérôme "Lynix" Leclercq (Lynix680@gmail.com)

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

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

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

#pragma once

#ifndef NAZARA_GLOBAL_CORE_HPP
#define NAZARA_GLOBAL_CORE_HPP

#include <Nazara/Core/AbstractHash.hpp>
#include <Nazara/Core/AbstractLogger.hpp>
#include <Nazara/Core/Algorithm.hpp>
#include <Nazara/Core/Bitset.hpp>
#include <Nazara/Core/ByteArray.hpp>
#include <Nazara/Core/ByteStream.hpp>
#include <Nazara/Core/CallOnExit.hpp>
#include <Nazara/Core/Clock.hpp>
#include <Nazara/Core/Color.hpp>
#include <Nazara/Core/ConditionVariable.hpp>
#include <Nazara/Core/Config.hpp>
#include <Nazara/Core/Core.hpp>
#include <Nazara/Core/Directory.hpp>
#include <Nazara/Core/DynLib.hpp>
#include <Nazara/Core/Endianness.hpp>
#include <Nazara/Core/Enums.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Core/ErrorFlags.hpp>
#include <Nazara/Core/File.hpp>
#include <Nazara/Core/FileLogger.hpp>
#include <Nazara/Core/Functor.hpp>
#include <Nazara/Core/GuillotineBinPack.hpp>
#include <Nazara/Core/HardwareInfo.hpp>
#include <Nazara/Core/Initializer.hpp>
#include <Nazara/Core/LockGuard.hpp>
#include <Nazara/Core/Log.hpp>
#include <Nazara/Core/MemoryHelper.hpp>
#include <Nazara/Core/MemoryManager.hpp>
#include <Nazara/Core/MemoryPool.hpp>
#include <Nazara/Core/MemoryStream.hpp>
#include <Nazara/Core/MemoryView.hpp>
#include <Nazara/Core/Mutex.hpp>
#include <Nazara/Core/ObjectLibrary.hpp>
#include <Nazara/Core/ObjectRef.hpp>
#include <Nazara/Core/OffsetOf.hpp>
#include <Nazara/Core/ParameterList.hpp>
#include <Nazara/Core/PluginManager.hpp>
#include <Nazara/Core/Primitive.hpp>
#include <Nazara/Core/PrimitiveList.hpp>
#include <Nazara/Core/RefCounted.hpp>
#include <Nazara/Core/Resource.hpp>
#include <Nazara/Core/ResourceLoader.hpp>
#include <Nazara/Core/ResourceManager.hpp>
#include <Nazara/Core/Semaphore.hpp>
#include <Nazara/Core/SerializationContext.hpp>
#include <Nazara/Core/Signal.hpp>
#include <Nazara/Core/SparsePtr.hpp>
#include <Nazara/Core/StdLogger.hpp>
#include <Nazara/Core/Stream.hpp>
#include <Nazara/Core/String.hpp>
#include <Nazara/Core/StringStream.hpp>
#include <Nazara/Core/TaskScheduler.hpp>
#include <Nazara/Core/Thread.hpp>
#include <Nazara/Core/Unicode.hpp>
#include <Nazara/Core/Updatable.hpp>

#endif // NAZARA_GLOBAL_CORE_HPP
<commit_msg>Core: Update global include<commit_after>// This file was automatically generated on 09 May 2016 at 17:07:09

/*
	Nazara Engine - Core module

	Copyright (C) 2015 Jérôme "Lynix" Leclercq (Lynix680@gmail.com)

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

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

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

#pragma once

#ifndef NAZARA_GLOBAL_CORE_HPP
#define NAZARA_GLOBAL_CORE_HPP

#include <Nazara/Core/AbstractHash.hpp>
#include <Nazara/Core/AbstractLogger.hpp>
#include <Nazara/Core/Algorithm.hpp>
#include <Nazara/Core/Bitset.hpp>
#include <Nazara/Core/ByteArray.hpp>
#include <Nazara/Core/ByteStream.hpp>
#include <Nazara/Core/CallOnExit.hpp>
#include <Nazara/Core/Clock.hpp>
#include <Nazara/Core/Color.hpp>
#include <Nazara/Core/ConditionVariable.hpp>
#include <Nazara/Core/Config.hpp>
#include <Nazara/Core/Core.hpp>
#include <Nazara/Core/Directory.hpp>
#include <Nazara/Core/DynLib.hpp>
#include <Nazara/Core/Endianness.hpp>
#include <Nazara/Core/Enums.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Core/ErrorFlags.hpp>
#include <Nazara/Core/File.hpp>
#include <Nazara/Core/FileLogger.hpp>
#include <Nazara/Core/Functor.hpp>
#include <Nazara/Core/GuillotineBinPack.hpp>
#include <Nazara/Core/HandledObject.hpp>
#include <Nazara/Core/HardwareInfo.hpp>
#include <Nazara/Core/Initializer.hpp>
#include <Nazara/Core/LockGuard.hpp>
#include <Nazara/Core/Log.hpp>
#include <Nazara/Core/MemoryHelper.hpp>
#include <Nazara/Core/MemoryManager.hpp>
#include <Nazara/Core/MemoryPool.hpp>
#include <Nazara/Core/MemoryStream.hpp>
#include <Nazara/Core/MemoryView.hpp>
#include <Nazara/Core/Mutex.hpp>
#include <Nazara/Core/ObjectHandle.hpp>
#include <Nazara/Core/ObjectLibrary.hpp>
#include <Nazara/Core/ObjectRef.hpp>
#include <Nazara/Core/OffsetOf.hpp>
#include <Nazara/Core/ParameterList.hpp>
#include <Nazara/Core/PluginManager.hpp>
#include <Nazara/Core/Primitive.hpp>
#include <Nazara/Core/PrimitiveList.hpp>
#include <Nazara/Core/RefCounted.hpp>
#include <Nazara/Core/Resource.hpp>
#include <Nazara/Core/ResourceLoader.hpp>
#include <Nazara/Core/ResourceManager.hpp>
#include <Nazara/Core/ResourceParameters.hpp>
#include <Nazara/Core/ResourceSaver.hpp>
#include <Nazara/Core/Semaphore.hpp>
#include <Nazara/Core/SerializationContext.hpp>
#include <Nazara/Core/Signal.hpp>
#include <Nazara/Core/SparsePtr.hpp>
#include <Nazara/Core/StdLogger.hpp>
#include <Nazara/Core/Stream.hpp>
#include <Nazara/Core/String.hpp>
#include <Nazara/Core/StringStream.hpp>
#include <Nazara/Core/TaskScheduler.hpp>
#include <Nazara/Core/Thread.hpp>
#include <Nazara/Core/Unicode.hpp>
#include <Nazara/Core/Updatable.hpp>

#endif // NAZARA_GLOBAL_CORE_HPP
<|endoftext|>


<commit_before>// Copyright 2012 Alessio Sclocco <a.sclocco@vu.nl>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <string>
#include <limits>

#include <utils.hpp>

#ifndef OBSERVATION_HPP
#define OBSERVATION_HPP

namespace AstroData {

class Observation {
public:
  Observation();
  ~Observation();

  // Getters
  // General observation parameters
  unsigned int getNrSeconds() const;
  unsigned int getNrStations() const;
  unsigned int getNrPaddedStations(unsigned int padding) const;
  unsigned int getNrBeams() const;
  unsigned int getNrPaddedBeams(unsigned int padding) const;
  unsigned int getNrSyntheticBeams() const;
  unsigned int getNrPaddedSyntheticBeams(const unsigned int padding) const;
  float getSamplingRate() const;
  unsigned int getNrSamplesPerBatch() const;
  unsigned int getNrSamplesPerPaddedBatch(unsigned int padding) const;
	// Frequency parameters
  unsigned int getNrSubbands() const;
  unsigned int getNrChannels() const;
  unsigned int getNrChannelsPerSubband() const;
  unsigned int getNrPaddedSubbands(unsigned int padding) const;
  unsigned int getNrPaddedChannels(unsigned int padding) const;
  unsigned int getNrZappedChannels() const;
  float getSubbandMinFreq() const;
  float getSubbandMaxFreq() const;
  float getSubbandBandwidth() const;
  float getMinFreq() const;
  float getMaxFreq() const;
  float getChannelBandwidth() const;
	// Dispersion measures
  unsigned int getNrSamplesPerBatchSubbanding() const;
  unsigned int getNrSamplesPerPaddedBatchSubbanding(unsigned int padding) const;
  unsigned int getNrDelaySecondsSubbanding() const;
  unsigned int getNrDelaySeconds() const;
  unsigned int getNrDMsSubbanding() const;
  unsigned int getNrDMs() const;
  unsigned int getNrPaddedDMsSubbanding(unsigned int padding) const;
  unsigned int getNrPaddedDMs(unsigned int padding) const;
  unsigned int getNrSamplesPerSubbandingDispersedChannel() const;
  unsigned int getNrSamplesPerDispersedChannel() const;
  unsigned int getNrSamplesPerPaddedSubbandingDispersedChannel(unsigned int padding) const;
  unsigned int getNrSamplesPerPaddedDispersedChannel(unsigned int padding) const;
  float getFirstDMSubbanding() const;
  float getFirstDM() const;
  float getLastDMSubbanding() const;
  float getLastDM() const;
  float getDMSubbandingStep() const;
  float getDMStep() const;
	// Periods
  unsigned int getNrPeriods() const;
  unsigned int getNrPaddedPeriods(unsigned int padding) const;
  unsigned int getFirstPeriod() const;
  unsigned int getLastPeriod() const;
  unsigned int getPeriodStep() const;
  unsigned int getNrBins() const;
  unsigned int getNrPaddedBins(unsigned int padding) const;

  // Setters
  // General observation parameters
  void setNrSeconds(const unsigned int seconds);
  void setNrStations(const unsigned int stations);
  void setNrBeams(const unsigned int beams);
  void setNrSyntheticBeams(const unsigned int beams);
  void setSamplingRate(const float sampling);
  void setNrSamplesPerBatch(const unsigned int samples);
  // Frequency parameters
  void setFrequencyRange(const unsigned int subbands, const unsigned int channels, const float baseFrequency, const float bandwidth);
  void setNrZappedChannels(const unsigned int zappedChannels);
  // Dispersion measures
  void setNrSamplesPerBatchSubbanding(const unsigned int samples);
  void setNrDelaySecondsSubbanding(const unsigned int seconds);
  void setNrDelaySeconds(const unsigned int seconds);
  void setNrSamplesPerSubbandingDispersedChannel(const unsigned int samples);
  void setNrSamplesPerDispersedChannel(const unsigned int samples);
  void setDMSubbandingRange(const unsigned int dms, const float baseDM, const float step);
  void setDMRange(const unsigned int dms, const float baseDM, const float step);
  // Periods
  void setPeriodRange(const unsigned int periods, const unsigned int basePeriod, const unsigned int step);
  void setNrBins(const unsigned int bins);

private:
  unsigned int nrSeconds;
  unsigned int nrStations;
  unsigned int nrBeams;
  unsigned int nrSyntheticBeams;
  float samplingRate;
  unsigned int nrSamplesPerBatch;
  unsigned int nrSamplesPerDispersedChannel;

  unsigned int nrSubbands;
  unsigned int nrChannels;
  unsigned int nrChannelsPerSubband;
  unsigned int nrZappedChannels;
  float subbandMinFreq;
  float subbandMaxFreq;
  float subbandBandwidth;
  float minFreq;
  float maxFreq;
  float channelBandwidth;

  unsigned int nrSamplesPerBatchSubbanding;
  unsigned int nrDelaySecondsSubbanding;
  unsigned int nrDelaySeconds;
  unsigned int nrDMsSubbanding;
  unsigned int nrDMs;
  float firstDMSubbanding;
  float firstDM;
  float lastDMSubbanding;
  float lastDM;
  float DMSubbandingStep;
  float DMStep;

  unsigned int nrPeriods;
  unsigned int firstPeriod;
  unsigned int lastPeriod;
  unsigned int periodStep;
  unsigned int nrBins;
};

// Implementations
inline unsigned int Observation::getNrSeconds() const {
	return nrSeconds;
}

inline unsigned int Observation::getNrStations() const {
	return nrStations;
}

inline unsigned int Observation::getNrPaddedStations(unsigned int padding) const {
	return isa::utils::pad(nrStations, padding);
}

inline unsigned int Observation::getNrBeams() const {
	return nrBeams;
}

inline unsigned int Observation::getNrPaddedBeams(unsigned int padding) const {
	return isa::utils::pad(nrBeams, padding);
}

inline unsigned int Observation::getNrSyntheticBeams() const {
  return nrSyntheticBeams;
}

inline unsigned int Observation::getNrPaddedSyntheticBeams(unsigned int padding) const {
  return isa::utils::pad(nrSyntheticBeams, padding);
}

inline unsigned int Observation::getNrSamplesPerBatch() const {
	return nrSamplesPerBatch;
}

inline float Observation::getSamplingRate() const {
	return samplingRate;
}

inline unsigned int Observation::getNrSamplesPerPaddedBatch(unsigned int padding) const {
	return isa::utils::pad(nrSamplesPerBatch, padding);
}

inline unsigned int Observation::getNrSubbands() const {
  return nrSubbands;
}

inline unsigned int Observation::getNrChannels() const {
	return nrChannels;
}

inline unsigned int Observation::getNrPaddedSubbands(unsigned int padding) const {
	return isa::utils::pad(nrSubbands, padding);
}

inline unsigned int Observation::getNrPaddedChannels(unsigned int padding) const {
	return isa::utils::pad(nrChannels, padding);
}

inline unsigned int Observation::getNrZappedChannels() const {
  return nrZappedChannels;
}

inline unsigned int Observation::getNrSamplesPerPaddedDispersedChannel(unsigned int padding) const {
  return isa::utils::pad(nrSamplesPerDispersedChannel, padding);
}

inline float Observation::getSubbandMinFreq() const {
  return subbandMinFreq;
}

inline float Observation::getSubbandMaxFreq() const {
  return subbandMaxFreq;
}

inline float Observation::getSubbandBandwidth() const {
  return subbandBandwidth;
}

inline float Observation::getMinFreq() const {
	return minFreq;
}

inline float Observation::getMaxFreq() const {
	return maxFreq;
}

inline float Observation::getChannelBandwidth() const {
	return channelBandwidth;
}

inline unsigned int Observation::getNrSamplesPerDispersedChannel() const {
  return nrSamplesPerDispersedChannel;
}

inline unsigned int Observation::getNrSamplesPerBatchSubbanding() const {
  return nrSamplesPerBatchSubbanding;
}

inline unsigned int Observation::getNrSamplesPerPaddedBatchSubbanding(unsigned int padding) const {
	return isa::utils::pad(nrSamplesPerBatchSubbanding, padding);
}

inline unsigned int Observation::getNrDelaySecondsSubbanding() const {
  return nrDelaySecondsSubbanding;
}

inline unsigned int Observation::getNrDelaySeconds() const {
  return nrDelaySeconds;
}

inline unsigned int Observation::getNrDMsSubbanding() const {
	return nrDMsSubbanding;
}

inline unsigned int Observation::getNrDMs() const {
	return nrDMs;
}

inline unsigned int Observation::getNrPaddedDMsSubbanding(unsigned int padding) const {
	return isa::utils::pad(nrDMsSubbanding, padding);
}

inline unsigned int Observation::getNrPaddedDMs(unsigned int padding) const {
	return isa::utils::pad(nrDMs, padding);
}

inline float Observation::getFirstDMSubbanding() const {
	return firstDMSubbanding;
}

inline float Observation::getFirstDM() const {
	return firstDM;
}

inline float Observation::getLastDMSubbanding() const {
  return lastDMSubbanding;
}

inline float Observation::getLastDM() const {
  return lastDM;
}

inline float Observation::getDMSubbandingStep() const {
	return DMSubbandingStep;
}

inline float Observation::getDMStep() const {
	return DMStep;
}

inline unsigned int Observation::getNrPeriods() const {
	return nrPeriods;
}

inline unsigned int Observation::getNrPaddedPeriods(unsigned int padding) const {
	return isa::utils::pad(nrPeriods, padding);
}

inline unsigned int Observation::getNrBins() const {
	return nrBins;
}

inline unsigned int Observation::getNrPaddedBins(unsigned int padding) const {
	return isa::utils::pad(nrBins, padding);
}

inline unsigned int Observation::getFirstPeriod() const {
	return firstPeriod;
}

inline unsigned int Observation::getLastPeriod() const {
  return lastPeriod;
}

inline unsigned int Observation::getPeriodStep() const {
	return periodStep;
}

} // AstroData

#endif // OBSERVATION_HPP

<commit_msg>Missing variable.<commit_after>// Copyright 2012 Alessio Sclocco <a.sclocco@vu.nl>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <string>
#include <limits>

#include <utils.hpp>

#ifndef OBSERVATION_HPP
#define OBSERVATION_HPP

namespace AstroData {

class Observation {
public:
  Observation();
  ~Observation();

  // Getters
  // General observation parameters
  unsigned int getNrSeconds() const;
  unsigned int getNrStations() const;
  unsigned int getNrPaddedStations(unsigned int padding) const;
  unsigned int getNrBeams() const;
  unsigned int getNrPaddedBeams(unsigned int padding) const;
  unsigned int getNrSyntheticBeams() const;
  unsigned int getNrPaddedSyntheticBeams(const unsigned int padding) const;
  float getSamplingRate() const;
  unsigned int getNrSamplesPerBatch() const;
  unsigned int getNrSamplesPerPaddedBatch(unsigned int padding) const;
	// Frequency parameters
  unsigned int getNrSubbands() const;
  unsigned int getNrChannels() const;
  unsigned int getNrChannelsPerSubband() const;
  unsigned int getNrPaddedSubbands(unsigned int padding) const;
  unsigned int getNrPaddedChannels(unsigned int padding) const;
  unsigned int getNrZappedChannels() const;
  float getSubbandMinFreq() const;
  float getSubbandMaxFreq() const;
  float getSubbandBandwidth() const;
  float getMinFreq() const;
  float getMaxFreq() const;
  float getChannelBandwidth() const;
	// Dispersion measures
  unsigned int getNrSamplesPerBatchSubbanding() const;
  unsigned int getNrSamplesPerPaddedBatchSubbanding(unsigned int padding) const;
  unsigned int getNrDelaySecondsSubbanding() const;
  unsigned int getNrDelaySeconds() const;
  unsigned int getNrDMsSubbanding() const;
  unsigned int getNrDMs() const;
  unsigned int getNrPaddedDMsSubbanding(unsigned int padding) const;
  unsigned int getNrPaddedDMs(unsigned int padding) const;
  unsigned int getNrSamplesPerSubbandingDispersedChannel() const;
  unsigned int getNrSamplesPerDispersedChannel() const;
  unsigned int getNrSamplesPerPaddedSubbandingDispersedChannel(unsigned int padding) const;
  unsigned int getNrSamplesPerPaddedDispersedChannel(unsigned int padding) const;
  float getFirstDMSubbanding() const;
  float getFirstDM() const;
  float getLastDMSubbanding() const;
  float getLastDM() const;
  float getDMSubbandingStep() const;
  float getDMStep() const;
	// Periods
  unsigned int getNrPeriods() const;
  unsigned int getNrPaddedPeriods(unsigned int padding) const;
  unsigned int getFirstPeriod() const;
  unsigned int getLastPeriod() const;
  unsigned int getPeriodStep() const;
  unsigned int getNrBins() const;
  unsigned int getNrPaddedBins(unsigned int padding) const;

  // Setters
  // General observation parameters
  void setNrSeconds(const unsigned int seconds);
  void setNrStations(const unsigned int stations);
  void setNrBeams(const unsigned int beams);
  void setNrSyntheticBeams(const unsigned int beams);
  void setSamplingRate(const float sampling);
  void setNrSamplesPerBatch(const unsigned int samples);
  // Frequency parameters
  void setFrequencyRange(const unsigned int subbands, const unsigned int channels, const float baseFrequency, const float bandwidth);
  void setNrZappedChannels(const unsigned int zappedChannels);
  // Dispersion measures
  void setNrSamplesPerBatchSubbanding(const unsigned int samples);
  void setNrDelaySecondsSubbanding(const unsigned int seconds);
  void setNrDelaySeconds(const unsigned int seconds);
  void setNrSamplesPerSubbandingDispersedChannel(const unsigned int samples);
  void setNrSamplesPerDispersedChannel(const unsigned int samples);
  void setDMSubbandingRange(const unsigned int dms, const float baseDM, const float step);
  void setDMRange(const unsigned int dms, const float baseDM, const float step);
  // Periods
  void setPeriodRange(const unsigned int periods, const unsigned int basePeriod, const unsigned int step);
  void setNrBins(const unsigned int bins);

private:
  unsigned int nrSeconds;
  unsigned int nrStations;
  unsigned int nrBeams;
  unsigned int nrSyntheticBeams;
  float samplingRate;
  unsigned int nrSamplesPerBatchSubbanding;
  unsigned int nrSamplesPerBatch;
  unsigned int nrSamplesPerDispersedChannel;
  unsigned int nrSamplesPerSubbandingDispersedChannel;

  unsigned int nrSubbands;
  unsigned int nrChannels;
  unsigned int nrChannelsPerSubband;
  unsigned int nrZappedChannels;
  float subbandMinFreq;
  float subbandMaxFreq;
  float subbandBandwidth;
  float minFreq;
  float maxFreq;
  float channelBandwidth;

  unsigned int nrDelaySecondsSubbanding;
  unsigned int nrDelaySeconds;
  unsigned int nrDMsSubbanding;
  unsigned int nrDMs;
  float firstDMSubbanding;
  float firstDM;
  float lastDMSubbanding;
  float lastDM;
  float DMSubbandingStep;
  float DMStep;

  unsigned int nrPeriods;
  unsigned int firstPeriod;
  unsigned int lastPeriod;
  unsigned int periodStep;
  unsigned int nrBins;
};

// Implementations
inline unsigned int Observation::getNrSeconds() const {
	return nrSeconds;
}

inline unsigned int Observation::getNrStations() const {
	return nrStations;
}

inline unsigned int Observation::getNrPaddedStations(unsigned int padding) const {
	return isa::utils::pad(nrStations, padding);
}

inline unsigned int Observation::getNrBeams() const {
	return nrBeams;
}

inline unsigned int Observation::getNrPaddedBeams(unsigned int padding) const {
	return isa::utils::pad(nrBeams, padding);
}

inline unsigned int Observation::getNrSyntheticBeams() const {
  return nrSyntheticBeams;
}

inline unsigned int Observation::getNrPaddedSyntheticBeams(unsigned int padding) const {
  return isa::utils::pad(nrSyntheticBeams, padding);
}

inline unsigned int Observation::getNrSamplesPerBatch() const {
	return nrSamplesPerBatch;
}

inline float Observation::getSamplingRate() const {
	return samplingRate;
}

inline unsigned int Observation::getNrSamplesPerPaddedBatch(unsigned int padding) const {
	return isa::utils::pad(nrSamplesPerBatch, padding);
}

inline unsigned int Observation::getNrSubbands() const {
  return nrSubbands;
}

inline unsigned int Observation::getNrChannels() const {
	return nrChannels;
}

inline unsigned int Observation::getNrPaddedSubbands(unsigned int padding) const {
	return isa::utils::pad(nrSubbands, padding);
}

inline unsigned int Observation::getNrPaddedChannels(unsigned int padding) const {
	return isa::utils::pad(nrChannels, padding);
}

inline unsigned int Observation::getNrZappedChannels() const {
  return nrZappedChannels;
}

inline unsigned int Observation::getNrSamplesPerPaddedDispersedChannel(unsigned int padding) const {
  return isa::utils::pad(nrSamplesPerDispersedChannel, padding);
}

inline float Observation::getSubbandMinFreq() const {
  return subbandMinFreq;
}

inline float Observation::getSubbandMaxFreq() const {
  return subbandMaxFreq;
}

inline float Observation::getSubbandBandwidth() const {
  return subbandBandwidth;
}

inline float Observation::getMinFreq() const {
	return minFreq;
}

inline float Observation::getMaxFreq() const {
	return maxFreq;
}

inline float Observation::getChannelBandwidth() const {
	return channelBandwidth;
}

inline unsigned int Observation::getNrSamplesPerDispersedChannel() const {
  return nrSamplesPerDispersedChannel;
}

inline unsigned int Observation::getNrSamplesPerBatchSubbanding() const {
  return nrSamplesPerBatchSubbanding;
}

inline unsigned int Observation::getNrSamplesPerPaddedBatchSubbanding(unsigned int padding) const {
	return isa::utils::pad(nrSamplesPerBatchSubbanding, padding);
}

inline unsigned int Observation::getNrDelaySecondsSubbanding() const {
  return nrDelaySecondsSubbanding;
}

inline unsigned int Observation::getNrDelaySeconds() const {
  return nrDelaySeconds;
}

inline unsigned int Observation::getNrDMsSubbanding() const {
	return nrDMsSubbanding;
}

inline unsigned int Observation::getNrDMs() const {
	return nrDMs;
}

inline unsigned int Observation::getNrPaddedDMsSubbanding(unsigned int padding) const {
	return isa::utils::pad(nrDMsSubbanding, padding);
}

inline unsigned int Observation::getNrPaddedDMs(unsigned int padding) const {
	return isa::utils::pad(nrDMs, padding);
}

inline float Observation::getFirstDMSubbanding() const {
	return firstDMSubbanding;
}

inline float Observation::getFirstDM() const {
	return firstDM;
}

inline float Observation::getLastDMSubbanding() const {
  return lastDMSubbanding;
}

inline float Observation::getLastDM() const {
  return lastDM;
}

inline float Observation::getDMSubbandingStep() const {
	return DMSubbandingStep;
}

inline float Observation::getDMStep() const {
	return DMStep;
}

inline unsigned int Observation::getNrPeriods() const {
	return nrPeriods;
}

inline unsigned int Observation::getNrPaddedPeriods(unsigned int padding) const {
	return isa::utils::pad(nrPeriods, padding);
}

inline unsigned int Observation::getNrBins() const {
	return nrBins;
}

inline unsigned int Observation::getNrPaddedBins(unsigned int padding) const {
	return isa::utils::pad(nrBins, padding);
}

inline unsigned int Observation::getFirstPeriod() const {
	return firstPeriod;
}

inline unsigned int Observation::getLastPeriod() const {
  return lastPeriod;
}

inline unsigned int Observation::getPeriodStep() const {
	return periodStep;
}

} // AstroData

#endif // OBSERVATION_HPP

<|endoftext|>