<commit_before>#include "applesoftfile.h"
#include <QDebug>

ApplesoftFile::ApplesoftFile(QByteArray data) : GenericFile(data)
{
    if (m_tokens.size() == 0)
    {
        makeTokens();
    }

    if (!data.isEmpty())
    {
        setData(data);
    }
}

void ApplesoftFile::setData(QByteArray data)
{
    GenericFile::setData(data);

    quint8 addlo = m_data.at(0);
    quint8 addhi = m_data.at(1);
    m_length = addlo + (addhi * 256);
    m_data.remove(0,2);
    m_detokenized = detokenize();
}

QList<ApplesoftLine> ApplesoftFile::detokenize()
{
    QList<ApplesoftLine> retval;

/*
    qDebug() << "Length: " << m_length;
    for (int idx = 0; idx < m_length; idx += 8)
    {
        qDebug()
                 << QString("%1 (%2): %3 %4 %5 %6 %7 %8 %9 %10")
                .arg((quint16) idx + 0x801,4,16,QChar('0')).toUpper()
                .arg((quint16) idx + 0x801,4,10,QChar('0'))
                .arg((quint8) m_data[idx],2,16,QChar('0')).toUpper()
                .arg((quint8) m_data[idx+1],2,16,QChar('0')).toUpper()
                .arg((quint8) m_data[idx+2],2,16,QChar('0')).toUpper()
                .arg((quint8) m_data[idx+3],2,16,QChar('0')).toUpper()
                .arg((quint8) m_data[idx+4],2,16,QChar('0')).toUpper()
                .arg((quint8) m_data[idx+5],2,16,QChar('0')).toUpper()
                .arg((quint8) m_data[idx+6],2,16,QChar('0')).toUpper()
                .arg((quint8) m_data[idx+7],2,16,QChar('0')).toUpper();

    }
*/
    int idx = 0;
    quint8 val = 0;
    while (idx < m_data.length()) {
        ApplesoftLine line;
        line.next_address = (quint8) m_data[idx] + (((quint8) m_data[idx+1]) *256);
        line.tokens.append(m_data[idx]);
        line.tokens.append(m_data[idx+1]);
        idx++; idx++;
        line.linenum = (quint8) m_data[idx] + (((quint8) m_data[idx+1])*256);
        line.tokens.append(m_data[idx]);
        line.tokens.append(m_data[idx+1]);
        idx++; idx++;
        if (line.next_address == 0x00) { break; }
        do {
            val = m_data[idx++];
            line.tokens.append(val);
            if (val >= 0x80) {
                line.detokenized_line.append(" " + m_tokens[val]);
            } else {
                if (val >= 0x20) {
                    line.detokenized_line.append(val);
                } else if (val == 0x7F) {
                    QChar ch = QChar(0x2401);
                    line.detokenized_line.append(ch);
                }else if (val > 0x00) {
                    QChar ch = QChar(0x00 + val);
                    line.detokenized_line.append(ch);
                }
            }
        } while (val != 0x00);
        retval.append(line);
    }

    m_data_end = idx;

    if (idx < m_data.length()) {
        qDebug() << QString("%1 byte(s) unaccounted for.").arg(m_data.length() - idx);
    }

    return retval;
}

void ApplesoftFile::list() {
    foreach (ApplesoftLine line,detokenized()) {
        QString debugline = QString("%1  %2  %3").arg(line.next_address,4,16,QChar('0')).arg(line.linenum).arg(line.detokenized_line);
        qDebug() << debugline;
/*
        debugline = "";
        foreach (quint8 val, line.tokens) {
            debugline.append(QString("%1 ").arg(val,2,16,QChar('0')));
        }
        qDebug() << "  " << debugline;
        qDebug() << "\n";
*/
    }

    qDebug() << extraDataHexValues().join("\n");
}

QStringList ApplesoftFile::extraDataHexValues() {
    QStringList retval;

    QString debugline = "";
    int count = 0;
    foreach (quint8 val, extraData()) {
        debugline.append(QString("%1").arg(val,2,16,QChar('0')).toUpper());
        count++;
        if (count == 16) {
            retval.append(debugline);
            debugline = "";
            count = 0;
        } else {
            debugline.append(" ");
        }
    }
    if (!debugline.simplified().isEmpty()) {
        retval.append(debugline);
    }
    return retval;
}

QByteArray ApplesoftFile::extraData()
{
    return m_data.mid(m_data_end);
}

void ApplesoftFile::makeTokens()
{
    m_tokens[0x80] = "END ";     m_tokens[0x81] = "FOR ";     m_tokens[0x82] = "NEXT ";
    m_tokens[0x83] = "DATA ";    m_tokens[0x84] = "INPUT ";   m_tokens[0x85] = " DEL ";
    m_tokens[0x86] = "DIM ";     m_tokens[0x87] = "READ ";    m_tokens[0x88] = "GR ";
    m_tokens[0x89] = "TEXT ";    m_tokens[0x8A] = "PR# ";     m_tokens[0x8B] = "IN# ";
    m_tokens[0x8C] = "CALL ";    m_tokens[0x8D] = "PLOT ";    m_tokens[0x8E] = "HLIN ";
    m_tokens[0x8F] = "VLIN ";    m_tokens[0x90] = "HGR2 ";    m_tokens[0x91] = "HGR ";
    m_tokens[0x92] = "HCOLOR= "; m_tokens[0x93] = "HPLOT ";   m_tokens[0x94] = "DRAW ";
    m_tokens[0x95] = "XDRAW ";   m_tokens[0x96] = "HTAB ";    m_tokens[0x97] = "HOME ";
    m_tokens[0x98] = "ROT= ";    m_tokens[0x99] = "SCALE= ";  m_tokens[0x9A] = "SHLOAD ";
    m_tokens[0x9B] = "TRACE ";   m_tokens[0x9C] = "NOTRACE "; m_tokens[0x9D] = "NORMAL ";
    m_tokens[0x9E] = "INVERSE "; m_tokens[0x9F] = "FLASH ";   m_tokens[0xA0] = "COLOR= ";
    m_tokens[0xA1] = "POP ";     m_tokens[0xA2] = "VTAB ";    m_tokens[0xA3] = "HIMEM: ";
    m_tokens[0xA4] = "LOMEM: ";  m_tokens[0xA5] = "ONERR ";   m_tokens[0xA6] = "RESUME ";
    m_tokens[0xA7] = "RECALL ";  m_tokens[0xA8] = "STORE ";   m_tokens[0xA9] = "SPEED= ";
    m_tokens[0xAA] = "LET ";     m_tokens[0xAB] = "GOTO ";    m_tokens[0xAC] = "RUN ";
    m_tokens[0xAD] = "IF ";      m_tokens[0xAE] = "RESTORE "; m_tokens[0xAF] = "& ";
    m_tokens[0xB0] = "GOSUB ";   m_tokens[0xB1] = "RETURN ";  m_tokens[0xB2] = "REM ";
    m_tokens[0xB3] = "STOP ";    m_tokens[0xB4] = "ON ";      m_tokens[0xB5] = "WAIT ";
    m_tokens[0xB6] = "LOAD ";    m_tokens[0xB7] = "SAVE ";    m_tokens[0xB8] = "DEF ";
    m_tokens[0xB9] = "POKE ";    m_tokens[0xBA] = "PRINT ";   m_tokens[0xBB] = "CONT ";
    m_tokens[0xBC] = "LIST ";    m_tokens[0xBD] = "CLEAR ";   m_tokens[0xBE] = "GET ";
    m_tokens[0xBF] = "NEW ";     m_tokens[0xC0] = "TAB ";     m_tokens[0xC1] = " TO ";
    m_tokens[0xC2] = "FN ";      m_tokens[0xC3] = "SPC( ";    m_tokens[0xC4] = "THEN ";
    m_tokens[0xC5] = " AT ";     m_tokens[0xC6] = "NOT ";     m_tokens[0xC7] = " STEP ";
    m_tokens[0xC8] = "+ ";       m_tokens[0xC9] = "- ";       m_tokens[0xCA] = "* ";
    m_tokens[0xCB] = "/ ";       m_tokens[0xCC] = "^ ";       m_tokens[0xCD] = " AND";
    m_tokens[0xCE] = " OR";      m_tokens[0xCF] = "> ";       m_tokens[0xD0] = "= ";
    m_tokens[0xD1] = "< ";       m_tokens[0xD2] = "SGN ";     m_tokens[0xD3] = "INT ";
    m_tokens[0xD4] = "ABS ";     m_tokens[0xD5] = "USR ";     m_tokens[0xD6] = "FRE ";
    m_tokens[0xD7] = "SCRN ( ";  m_tokens[0xD8] = "PDL ";     m_tokens[0xD9] = "POS ";
    m_tokens[0xDA] = "SQR ";     m_tokens[0xDB] = "RND ";     m_tokens[0xDC] = "LOG ";
    m_tokens[0xDD] = "EXP ";     m_tokens[0xDE] = "COS ";     m_tokens[0xDF] = "SIN ";
    m_tokens[0xE0] = "TAN ";     m_tokens[0xE1] = "ATN ";     m_tokens[0xE2] = "PEEK ";
    m_tokens[0xE3] = "LEN ";     m_tokens[0xE4] = "STR$ ";    m_tokens[0xE5] = "VAL ";
    m_tokens[0xE6] = "ASC ";     m_tokens[0xE7] = "CHR$ ";    m_tokens[0xE8] = "LEFT$ ";
    m_tokens[0xE9] = "RIGHT$ ";  m_tokens[0xEA] = "MID$ ";    m_tokens[0xEB] = "{Token 0xEB} ";
    m_tokens[0xEC] = "{Token 0xEC} ";
    m_tokens[0xED] = "{Token 0xED} ";
    m_tokens[0xEE] = "{Token 0xEE} ";
    m_tokens[0xEF] = "{Token 0xEF} ";
    m_tokens[0xF0] = "{Token 0xF0} ";
    m_tokens[0xF1] = "{Token 0xF1} ";
    m_tokens[0xF2] = "{Token 0xF2} ";
    m_tokens[0xF3] = "{Token 0xF3} ";
    m_tokens[0xF4] = "{Token 0xF4} ";
    m_tokens[0xF5] = "{Token 0xF5} ";
    m_tokens[0xF6] = "{Token 0xF6} ";
    m_tokens[0xF7] = "{Token 0xF7} ";
    m_tokens[0xF8] = "{Token 0xF8} ";
    m_tokens[0xF9] = "{Token 0xF9} ";
    m_tokens[0xFA] = "{Token 0xFA} ";
    m_tokens[0xFB] = "{Token 0xFB} ";
    m_tokens[0xFC] = "{Token 0xFC} ";
    m_tokens[0xFD] = "{Token 0xFD} ";
    m_tokens[0xFE] = "{Token 0xFE} ";
    m_tokens[0xFF] = "{Token 0xFF} ";
}
<commit_msg>Udpated token values<commit_after>#include "applesoftfile.h"
#include <QDebug>

ApplesoftFile::ApplesoftFile(QByteArray data) : GenericFile(data)
{
    if (m_tokens.size() == 0)
    {
        makeTokens();
    }

    if (!data.isEmpty())
    {
        setData(data);
    }
}

void ApplesoftFile::setData(QByteArray data)
{
    GenericFile::setData(data);

    quint8 addlo = m_data.at(0);
    quint8 addhi = m_data.at(1);
    m_length = addlo + (addhi * 256);
    m_data.remove(0,2);
    m_detokenized = detokenize();
}

QList<ApplesoftLine> ApplesoftFile::detokenize()
{
    QList<ApplesoftLine> retval;

/*
    qDebug() << "Length: " << m_length;
    for (int idx = 0; idx < m_length; idx += 8)
    {
        qDebug()
                 << QString("%1 (%2): %3 %4 %5 %6 %7 %8 %9 %10")
                .arg((quint16) idx + 0x801,4,16,QChar('0')).toUpper()
                .arg((quint16) idx + 0x801,4,10,QChar('0'))
                .arg((quint8) m_data[idx],2,16,QChar('0')).toUpper()
                .arg((quint8) m_data[idx+1],2,16,QChar('0')).toUpper()
                .arg((quint8) m_data[idx+2],2,16,QChar('0')).toUpper()
                .arg((quint8) m_data[idx+3],2,16,QChar('0')).toUpper()
                .arg((quint8) m_data[idx+4],2,16,QChar('0')).toUpper()
                .arg((quint8) m_data[idx+5],2,16,QChar('0')).toUpper()
                .arg((quint8) m_data[idx+6],2,16,QChar('0')).toUpper()
                .arg((quint8) m_data[idx+7],2,16,QChar('0')).toUpper();

    }
*/
    int idx = 0;
    quint8 val = 0;
    while (idx < m_data.length()) {
        ApplesoftLine line;
        line.next_address = (quint8) m_data[idx] + (((quint8) m_data[idx+1]) *256);
        line.tokens.append(m_data[idx]);
        line.tokens.append(m_data[idx+1]);
        idx++; idx++;
        line.linenum = (quint8) m_data[idx] + (((quint8) m_data[idx+1])*256);
        line.tokens.append(m_data[idx]);
        line.tokens.append(m_data[idx+1]);
        idx++; idx++;
        if (line.next_address == 0x00) { break; }
        do {
            val = m_data[idx++];
            line.tokens.append(val);
            if (val >= 0x80) {
                line.detokenized_line.append(" " + m_tokens[val]);
            } else {
                if (val >= 0x20) {
                    line.detokenized_line.append(val);
                } else if (val == 0x7F) {
                    QChar ch = QChar(0x2401);
                    line.detokenized_line.append(ch);
                }else if (val > 0x00) {
                    QChar ch = QChar(0x00 + val);
                    line.detokenized_line.append(ch);
                }
            }
        } while (val != 0x00);
        retval.append(line);
    }

    m_data_end = idx;

    if (idx < m_data.length()) {
        qDebug() << QString("%1 byte(s) unaccounted for.").arg(m_data.length() - idx);
    }

    return retval;
}

void ApplesoftFile::list() {
    foreach (ApplesoftLine line,detokenized()) {
        QString debugline = QString("%1  %2  %3").arg(line.next_address,4,16,QChar('0')).arg(line.linenum).arg(line.detokenized_line);
        qDebug() << debugline;
/*
        debugline = "";
        foreach (quint8 val, line.tokens) {
            debugline.append(QString("%1 ").arg(val,2,16,QChar('0')));
        }
        qDebug() << "  " << debugline;
        qDebug() << "\n";
*/
    }

    qDebug() << extraDataHexValues().join("\n");
}

QStringList ApplesoftFile::extraDataHexValues() {
    QStringList retval;

    QString debugline = "";
    int count = 0;
    foreach (quint8 val, extraData()) {
        debugline.append(QString("%1").arg(val,2,16,QChar('0')).toUpper());
        count++;
        if (count == 16) {
            retval.append(debugline);
            debugline = "";
            count = 0;
        } else {
            debugline.append(" ");
        }
    }
    if (!debugline.simplified().isEmpty()) {
        retval.append(debugline);
    }
    return retval;
}

QByteArray ApplesoftFile::extraData()
{
    return m_data.mid(m_data_end);
}

void ApplesoftFile::makeTokens()
{
    m_tokens[0x80] = " END ";     m_tokens[0x81] = " FOR ";     m_tokens[0x82] = " NEXT ";
    m_tokens[0x83] = " DATA ";    m_tokens[0x84] = " INPUT ";   m_tokens[0x85] = " DEL ";
    m_tokens[0x86] = " DIM ";     m_tokens[0x87] = " READ ";    m_tokens[0x88] = " GR ";
    m_tokens[0x89] = " TEXT ";    m_tokens[0x8A] = " PR# ";     m_tokens[0x8B] = " IN# ";
    m_tokens[0x8C] = " CALL ";    m_tokens[0x8D] = " PLOT ";    m_tokens[0x8E] = " HLIN ";
    m_tokens[0x8F] = " VLIN ";    m_tokens[0x90] = " HGR2 ";    m_tokens[0x91] = " HGR ";
    m_tokens[0x92] = " HCOLOR= "; m_tokens[0x93] = " HPLOT ";   m_tokens[0x94] = " DRAW ";
    m_tokens[0x95] = " XDRAW ";   m_tokens[0x96] = " HTAB ";    m_tokens[0x97] = " HOME ";
    m_tokens[0x98] = " ROT= ";    m_tokens[0x99] = " SCALE= ";  m_tokens[0x9A] = " SHLOAD ";
    m_tokens[0x9B] = " TRACE ";   m_tokens[0x9C] = " NOTRACE "; m_tokens[0x9D] = " NORMAL ";
    m_tokens[0x9E] = " INVERSE "; m_tokens[0x9F] = " FLASH ";   m_tokens[0xA0] = " COLOR= ";
    m_tokens[0xA1] = " POP ";     m_tokens[0xA2] = " VTAB ";    m_tokens[0xA3] = " HIMEM: ";
    m_tokens[0xA4] = " LOMEM: ";  m_tokens[0xA5] = " ONERR ";   m_tokens[0xA6] = " RESUME ";
    m_tokens[0xA7] = " RECALL ";  m_tokens[0xA8] = " STORE ";   m_tokens[0xA9] = " SPEED= ";
    m_tokens[0xAA] = " LET ";     m_tokens[0xAB] = " GOTO ";    m_tokens[0xAC] = " RUN ";
    m_tokens[0xAD] = " IF ";      m_tokens[0xAE] = " RESTORE "; m_tokens[0xAF] = " & ";
    m_tokens[0xB0] = " GOSUB ";   m_tokens[0xB1] = " RETURN ";  m_tokens[0xB2] = " REM ";
    m_tokens[0xB3] = " STOP ";    m_tokens[0xB4] = " ON ";      m_tokens[0xB5] = " WAIT ";
    m_tokens[0xB6] = " LOAD ";    m_tokens[0xB7] = " SAVE ";    m_tokens[0xB8] = " DEF ";
    m_tokens[0xB9] = " POKE ";    m_tokens[0xBA] = " PRINT ";   m_tokens[0xBB] = " CONT ";
    m_tokens[0xBC] = " LIST ";    m_tokens[0xBD] = " CLEAR ";   m_tokens[0xBE] = " GET ";
    m_tokens[0xBF] = " NEW ";     m_tokens[0xC0] = " TAB ";     m_tokens[0xC1] = "  TO ";
    m_tokens[0xC2] = " FN ";      m_tokens[0xC3] = " SPC( ";    m_tokens[0xC4] = "  THEN ";
    m_tokens[0xC5] = " AT ";      m_tokens[0xC6] = "  NOT ";    m_tokens[0xC7] = "   STEP ";
    m_tokens[0xC8] = " +";        m_tokens[0xC9] = " -";        m_tokens[0xCA] = " *";
    m_tokens[0xCB] = " /";        m_tokens[0xCC] = " ^";        m_tokens[0xCD] = "  AND ";
    m_tokens[0xCE] = "  OR ";     m_tokens[0xCF] = " >";        m_tokens[0xD0] = " =";
    m_tokens[0xD1] = " <";        m_tokens[0xD2] = " SGN";      m_tokens[0xD3] = " INT";
    m_tokens[0xD4] = " ABS";      m_tokens[0xD5] = " USR";      m_tokens[0xD6] = " FRE";
    m_tokens[0xD7] = " SCRN( ";   m_tokens[0xD8] = " PDL";      m_tokens[0xD9] = " POS";
    m_tokens[0xDA] = " SQR";      m_tokens[0xDB] = " RND";      m_tokens[0xDC] = " LOG";
    m_tokens[0xDD] = " EXP";      m_tokens[0xDE] = " COS";      m_tokens[0xDF] = " SIN";
    m_tokens[0xE0] = " TAN";      m_tokens[0xE1] = " ATN";      m_tokens[0xE2] = " PEEK";
    m_tokens[0xE3] = " LEN";      m_tokens[0xE4] = " STR$";     m_tokens[0xE5] = " VAL";
    m_tokens[0xE6] = " ASC";      m_tokens[0xE7] = " CHR$";     m_tokens[0xE8] = " LEFT$ ";
    m_tokens[0xE9] = " RIGHT$ ";  m_tokens[0xEA] = " MID$ ";    m_tokens[0xEB] = "{Token 0xEB} ";
    m_tokens[0xEC] = "{Token 0xEC} ";
    m_tokens[0xED] = "{Token 0xED} ";
    m_tokens[0xEE] = "{Token 0xEE} ";
    m_tokens[0xEF] = "{Token 0xEF} ";
    m_tokens[0xF0] = "{Token 0xF0} ";
    m_tokens[0xF1] = "{Token 0xF1} ";
    m_tokens[0xF2] = "{Token 0xF2} ";
    m_tokens[0xF3] = "{Token 0xF3} ";
    m_tokens[0xF4] = "{Token 0xF4} ";
    m_tokens[0xF5] = "{Token 0xF5} ";
    m_tokens[0xF6] = "{Token 0xF6} ";
    m_tokens[0xF7] = "{Token 0xF7} ";
    m_tokens[0xF8] = "{Token 0xF8} ";
    m_tokens[0xF9] = "{Token 0xF9} ";
    m_tokens[0xFA] = "{Token 0xFA} ";
    m_tokens[0xFB] = "{Token 0xFB} ";
    m_tokens[0xFC] = "{Token 0xFC} ";
    m_tokens[0xFD] = "{Token 0xFD} ";
    m_tokens[0xFE] = "{Token 0xFE} ";
    m_tokens[0xFF] = "{Token 0xFF} ";
}
<|endoftext|>


<commit_before>/* Copyright (c) 2015-present Advanced Micro Devices, Inc.

 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. */

#include <hip/hip_runtime.h>

#include "hip_event.hpp"

namespace hip {

bool Event::ready() {
  if (event_->status() != CL_COMPLETE) {
    event_->notifyCmdQueue();
  }

  return (event_->status() == CL_COMPLETE);
}

hipError_t Event::query() {
  amd::ScopedLock lock(lock_);

  if (event_ == nullptr) {
    return hipErrorInvalidHandle;
  }

  return ready() ? hipSuccess : hipErrorNotReady;
}

hipError_t Event::synchronize() {
  amd::ScopedLock lock(lock_);

  if (event_ == nullptr) {
    return hipErrorInvalidHandle;
  }

  event_->awaitCompletion();

  return hipSuccess;
}

hipError_t Event::elapsedTime(Event& eStop, float& ms) {
  amd::ScopedLock startLock(lock_);

  if (this == &eStop) {
    if (event_ == nullptr) {
      return hipErrorInvalidHandle;
    }

    if (flags & hipEventDisableTiming) {
      return hipErrorInvalidHandle;
    }

    if (!ready()) {
      return hipErrorNotReady;
    }

    ms = 0.f;
    return hipSuccess;
  }
  amd::ScopedLock stopLock(eStop.lock_);

  if (event_ == nullptr ||
      eStop.event_  == nullptr) {
    return hipErrorInvalidHandle;
  }

  if ((flags | eStop.flags) & hipEventDisableTiming) {
    return hipErrorInvalidHandle;
  }

  if (!ready() || !eStop.ready()) {
    return hipErrorNotReady;
  }

  ms = static_cast<float>(static_cast<int64_t>(eStop.event_->profilingInfo().end_ -
                          event_->profilingInfo().start_))/1000000.f;

  return hipSuccess;
}

hipError_t Event::streamWait(amd::HostQueue* hostQueue, uint flags) {
  if ((event_ == nullptr) || (event_->command().queue() == hostQueue)) {
    return hipSuccess;
  }

  amd::ScopedLock lock(lock_);
  bool retain = false;

  if (!event_->notifyCmdQueue()) {
    return hipErrorLaunchOutOfResources;
  }
  amd::Command::EventWaitList eventWaitList;
  eventWaitList.push_back(event_);

  amd::Command* command = new amd::Marker(*hostQueue, false, eventWaitList);
  if (command == NULL) {
    return hipErrorOutOfMemory;
  }
  command->enqueue();
  command->release();

  return hipSuccess;
}

void Event::addMarker(amd::HostQueue* queue, amd::Command* command) {
  amd::ScopedLock lock(lock_);

  if (event_ == &command->event()) return;

  if (event_ != nullptr) {
    event_->release();
  }

  event_ = &command->event();
}

}

hipError_t ihipEventCreateWithFlags(hipEvent_t* event, unsigned flags) {
  if (event == nullptr) {
    return hipErrorInvalidValue;
  }

  unsigned supportedFlags = hipEventDefault | hipEventBlockingSync | hipEventDisableTiming |
                            hipEventReleaseToDevice | hipEventReleaseToSystem;
  const unsigned releaseFlags = (hipEventReleaseToDevice | hipEventReleaseToSystem);

  const bool illegalFlags =
      (flags & ~supportedFlags) ||             // can't set any unsupported flags.
      (flags & releaseFlags) == releaseFlags;  // can't set both release flags

  if (!illegalFlags) {
    hip::Event* e = new hip::Event(flags);

    if (e == nullptr) {
      return hipErrorOutOfMemory;
    }

    *event = reinterpret_cast<hipEvent_t>(e);
  } else {
    return hipErrorInvalidValue;
  }
  return hipSuccess;
}

hipError_t ihipEventQuery(hipEvent_t event) {
  if (event == nullptr) {
    return hipErrorInvalidHandle;
  }

  hip::Event* e = reinterpret_cast<hip::Event*>(event);

  return e->query();
}

hipError_t hipEventCreateWithFlags(hipEvent_t* event, unsigned flags) {
  HIP_INIT_API(hipEventCreateWithFlags, event, flags);

  HIP_RETURN(ihipEventCreateWithFlags(event, flags));
}

hipError_t hipEventCreate(hipEvent_t* event) {
  HIP_INIT_API(hipEventCreate, event);

  HIP_RETURN(ihipEventCreateWithFlags(event, 0));
}

hipError_t hipEventDestroy(hipEvent_t event) {
  HIP_INIT_API(hipEventDestroy, event);

  if (event == nullptr) {
    HIP_RETURN(hipErrorInvalidHandle);
  }

  delete reinterpret_cast<hip::Event*>(event);

  HIP_RETURN(hipSuccess);
}

hipError_t hipEventElapsedTime(float *ms, hipEvent_t start, hipEvent_t stop) {
  HIP_INIT_API(hipEventElapsedTime, ms, start, stop);

  if (start == nullptr || stop == nullptr) {
    HIP_RETURN(hipErrorInvalidHandle);
  }

  if (ms == nullptr) {
    HIP_RETURN(hipErrorInvalidValue);
  }

  hip::Event* eStart = reinterpret_cast<hip::Event*>(start);
  hip::Event* eStop  = reinterpret_cast<hip::Event*>(stop);

  HIP_RETURN(eStart->elapsedTime(*eStop, *ms));
}

hipError_t hipEventRecord(hipEvent_t event, hipStream_t stream) {
  HIP_INIT_API(hipEventRecord, event, stream);

  if (event == nullptr) {
    HIP_RETURN(hipErrorInvalidHandle);
  }

  hip::Event* e = reinterpret_cast<hip::Event*>(event);

  hip::Stream* s = reinterpret_cast<hip::Stream*>(stream);
  amd::HostQueue* queue = hip::getQueue(stream);

  amd::Command* command = (s != nullptr && (s->flags & hipStreamNonBlocking)) ?
    queue->getLastQueuedCommand(true) : nullptr;

  if (command == nullptr) {
    command = new amd::Marker(*queue, false);
    command->enqueue();
  }

  e->addMarker(queue, command);

  HIP_RETURN(hipSuccess);
}

hipError_t hipEventSynchronize(hipEvent_t event) {
  HIP_INIT_API(hipEventSynchronize, event);

  if (event == nullptr) {
    HIP_RETURN(hipErrorInvalidHandle);
  }

  hip::Event* e = reinterpret_cast<hip::Event*>(event);

  HIP_RETURN(e->synchronize());
}

hipError_t hipEventQuery(hipEvent_t event) {
  HIP_INIT_API(hipEventQuery, event);

  HIP_RETURN(ihipEventQuery(event));
}
<commit_msg>Wake up commandQueue before returning<commit_after>/* Copyright (c) 2015-present Advanced Micro Devices, Inc.

 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. */

#include <hip/hip_runtime.h>

#include "hip_event.hpp"

namespace hip {

bool Event::ready() {
  if (event_->status() != CL_COMPLETE) {
    event_->notifyCmdQueue();
  }

  return (event_->status() == CL_COMPLETE);
}

hipError_t Event::query() {
  amd::ScopedLock lock(lock_);

  if (event_ == nullptr) {
    return hipErrorInvalidHandle;
  }

  return ready() ? hipSuccess : hipErrorNotReady;
}

hipError_t Event::synchronize() {
  amd::ScopedLock lock(lock_);

  if (event_ == nullptr) {
    return hipErrorInvalidHandle;
  }

  event_->awaitCompletion();

  return hipSuccess;
}

hipError_t Event::elapsedTime(Event& eStop, float& ms) {
  amd::ScopedLock startLock(lock_);

  if (this == &eStop) {
    if (event_ == nullptr) {
      return hipErrorInvalidHandle;
    }

    if (flags & hipEventDisableTiming) {
      return hipErrorInvalidHandle;
    }

    if (!ready()) {
      return hipErrorNotReady;
    }

    ms = 0.f;
    return hipSuccess;
  }
  amd::ScopedLock stopLock(eStop.lock_);

  if (event_ == nullptr ||
      eStop.event_  == nullptr) {
    return hipErrorInvalidHandle;
  }

  if ((flags | eStop.flags) & hipEventDisableTiming) {
    return hipErrorInvalidHandle;
  }

  if (!ready() || !eStop.ready()) {
    return hipErrorNotReady;
  }

  ms = static_cast<float>(static_cast<int64_t>(eStop.event_->profilingInfo().end_ -
                          event_->profilingInfo().start_))/1000000.f;

  return hipSuccess;
}

hipError_t Event::streamWait(amd::HostQueue* hostQueue, uint flags) {
  // Effective no-op if event is NULL
  if (event_ == nullptr) {
    return hipSuccess;
  }

  amd::ScopedLock lock(lock_);

  if (event_->command().queue() == hostQueue) {
    // Wake up commandQueue thread
    if (!event_->notifyCmdQueue()) {
      return hipErrorLaunchOutOfResources;
    }
    return hipSuccess;
  }

  if (!event_->notifyCmdQueue()) {
    return hipErrorLaunchOutOfResources;
  }
  amd::Command::EventWaitList eventWaitList;
  eventWaitList.push_back(event_);

  amd::Command* command = new amd::Marker(*hostQueue, false, eventWaitList);
  if (command == NULL) {
    return hipErrorOutOfMemory;
  }
  command->enqueue();
  command->release();

  return hipSuccess;
}

void Event::addMarker(amd::HostQueue* queue, amd::Command* command) {
  amd::ScopedLock lock(lock_);

  if (event_ == &command->event()) return;

  if (event_ != nullptr) {
    event_->release();
  }

  event_ = &command->event();
}

}

hipError_t ihipEventCreateWithFlags(hipEvent_t* event, unsigned flags) {
  if (event == nullptr) {
    return hipErrorInvalidValue;
  }

  unsigned supportedFlags = hipEventDefault | hipEventBlockingSync | hipEventDisableTiming |
                            hipEventReleaseToDevice | hipEventReleaseToSystem;
  const unsigned releaseFlags = (hipEventReleaseToDevice | hipEventReleaseToSystem);

  const bool illegalFlags =
      (flags & ~supportedFlags) ||             // can't set any unsupported flags.
      (flags & releaseFlags) == releaseFlags;  // can't set both release flags

  if (!illegalFlags) {
    hip::Event* e = new hip::Event(flags);

    if (e == nullptr) {
      return hipErrorOutOfMemory;
    }

    *event = reinterpret_cast<hipEvent_t>(e);
  } else {
    return hipErrorInvalidValue;
  }
  return hipSuccess;
}

hipError_t ihipEventQuery(hipEvent_t event) {
  if (event == nullptr) {
    return hipErrorInvalidHandle;
  }

  hip::Event* e = reinterpret_cast<hip::Event*>(event);

  return e->query();
}

hipError_t hipEventCreateWithFlags(hipEvent_t* event, unsigned flags) {
  HIP_INIT_API(hipEventCreateWithFlags, event, flags);

  HIP_RETURN(ihipEventCreateWithFlags(event, flags));
}

hipError_t hipEventCreate(hipEvent_t* event) {
  HIP_INIT_API(hipEventCreate, event);

  HIP_RETURN(ihipEventCreateWithFlags(event, 0));
}

hipError_t hipEventDestroy(hipEvent_t event) {
  HIP_INIT_API(hipEventDestroy, event);

  if (event == nullptr) {
    HIP_RETURN(hipErrorInvalidHandle);
  }

  delete reinterpret_cast<hip::Event*>(event);

  HIP_RETURN(hipSuccess);
}

hipError_t hipEventElapsedTime(float *ms, hipEvent_t start, hipEvent_t stop) {
  HIP_INIT_API(hipEventElapsedTime, ms, start, stop);

  if (start == nullptr || stop == nullptr) {
    HIP_RETURN(hipErrorInvalidHandle);
  }

  if (ms == nullptr) {
    HIP_RETURN(hipErrorInvalidValue);
  }

  hip::Event* eStart = reinterpret_cast<hip::Event*>(start);
  hip::Event* eStop  = reinterpret_cast<hip::Event*>(stop);

  HIP_RETURN(eStart->elapsedTime(*eStop, *ms));
}

hipError_t hipEventRecord(hipEvent_t event, hipStream_t stream) {
  HIP_INIT_API(hipEventRecord, event, stream);

  if (event == nullptr) {
    HIP_RETURN(hipErrorInvalidHandle);
  }

  hip::Event* e = reinterpret_cast<hip::Event*>(event);

  hip::Stream* s = reinterpret_cast<hip::Stream*>(stream);
  amd::HostQueue* queue = hip::getQueue(stream);

  amd::Command* command = (s != nullptr && (s->flags & hipStreamNonBlocking)) ?
    queue->getLastQueuedCommand(true) : nullptr;

  if (command == nullptr) {
    command = new amd::Marker(*queue, false);
    command->enqueue();
  }

  e->addMarker(queue, command);

  HIP_RETURN(hipSuccess);
}

hipError_t hipEventSynchronize(hipEvent_t event) {
  HIP_INIT_API(hipEventSynchronize, event);

  if (event == nullptr) {
    HIP_RETURN(hipErrorInvalidHandle);
  }

  hip::Event* e = reinterpret_cast<hip::Event*>(event);

  HIP_RETURN(e->synchronize());
}

hipError_t hipEventQuery(hipEvent_t event) {
  HIP_INIT_API(hipEventQuery, event);

  HIP_RETURN(ihipEventQuery(event));
}
<|endoftext|>


<commit_before>#pragma ident "$Id$"

//============================================================================
//
//  This file is part of GPSTk, the GPS Toolkit.
//
//  The GPSTk is free software; you can redistribute it and/or modify
//  it under the terms of the GNU Lesser General Public License as published
//  by the Free Software Foundation; either version 2.1 of the License, or
//  any later version.
//
//  The GPSTk is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with GPSTk; if not, write to the Free Software Foundation,
//  Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
//  Copyright 2004, The University of Texas at Austin
//
//============================================================================

//============================================================================
//
//This software developed by Applied Research Laboratories at the University of
//Texas at Austin, under contract to an agency or agencies within the U.S.
//Department of Defense. The U.S. Government retains all rights to use,
//duplicate, distribute, disclose, or release this software.
//
//Pursuant to DoD Directive 523024
//
// DISTRIBUTION STATEMENT A: This software has been approved for public
//                           release, distribution is unlimited.
//
//=============================================================================

/** @file Translates between various similiar objects */

#include "StringUtils.hpp"
#include "RinexObsID.hpp"

#include "RinexConverters.hpp"

using namespace std;

namespace gpstk
{
   short snr2ssi(float x)
   {
      // These values were obtained from the comments in a RINEX obs file that was
      // generated from a TurboBinary file recorded on an AOA Benchmark  receiver
      if (x>316) return 9;
      if (x>100) return 8;
      if (x>31.6) return 7;
      if (x>10) return 6;
      if (x>3.2) return 5;
      if (x>0) return 4;
      return 0;
   }

   RinexObsData::RinexObsTypeMap makeRinexObsTypeMap(const MDPObsEpoch& moe) throw()
   {
      gpstk::RinexObsData::RinexObsTypeMap rotm;
      MDPObsEpoch::ObsMap ol=moe.obs;
      MDPObsEpoch::ObsMap::const_iterator j;

      // The C1 Rinex obs is easy
      j = ol.find(MDPObsEpoch::ObsKey(ccL1,rcCA));
      if (j!=ol.end())
      {
         rotm[gpstk::RinexObsHeader::C1].data = j->second.pseudorange;
         rotm[gpstk::RinexObsHeader::C1].lli = j->second.lockCount ? 1 : 0;
         rotm[gpstk::RinexObsHeader::C1].ssi = snr2ssi(j->second.snr);

         rotm[gpstk::RinexObsHeader::L1].data = j->second.phase;
         rotm[gpstk::RinexObsHeader::L1].lli = j->second.lockCount ? 1 : 0;
         rotm[gpstk::RinexObsHeader::L1].ssi = snr2ssi(j->second.snr);

         rotm[gpstk::RinexObsHeader::D1].data = j->second.doppler;
         rotm[gpstk::RinexObsHeader::D1].lli = j->second.lockCount ? 1 : 0;
         rotm[gpstk::RinexObsHeader::D1].ssi = snr2ssi(j->second.snr);

         rotm[gpstk::RinexObsHeader::S1].data = j->second.snr;
      }

      // Now get the P1, L1, D1, S1 obs
      j = ol.find(MDPObsEpoch::ObsKey(ccL1, rcYcode));
      if (j == ol.end())
         j = ol.find(MDPObsEpoch::ObsKey(ccL1, rcPcode));
      if (j == ol.end())
         j = ol.find(MDPObsEpoch::ObsKey(ccL1, rcCodeless));
      if (j != ol.end())
      {
         rotm[gpstk::RinexObsHeader::P1].data = j->second.pseudorange;
         rotm[gpstk::RinexObsHeader::P1].lli = j->second.lockCount ? 1 : 0;
         rotm[gpstk::RinexObsHeader::P1].ssi = snr2ssi(j->second.snr);

         rotm[gpstk::RinexObsHeader::L1].data = j->second.phase;
         rotm[gpstk::RinexObsHeader::L1].lli = j->second.lockCount ? 1 : 0;
         rotm[gpstk::RinexObsHeader::L1].ssi = snr2ssi(j->second.snr);

         rotm[gpstk::RinexObsHeader::D1].data = j->second.doppler;
         rotm[gpstk::RinexObsHeader::D1].lli = j->second.lockCount ? 1 : 0;
         rotm[gpstk::RinexObsHeader::D1].ssi = snr2ssi(j->second.snr);

         rotm[gpstk::RinexObsHeader::S1].data = j->second.snr;
      }

      // Now get the P2, L2, D2, S2 obs
      j = ol.find(MDPObsEpoch::ObsKey(ccL2, rcYcode));
      if (j == ol.end())
         j = ol.find(MDPObsEpoch::ObsKey(ccL2, rcPcode));
      if (j == ol.end())
         j = ol.find(MDPObsEpoch::ObsKey(ccL2, rcCodeless));
      if (j != ol.end())
      {
         rotm[gpstk::RinexObsHeader::P2].data = j->second.pseudorange;
         rotm[gpstk::RinexObsHeader::P2].lli = j->second.lockCount ? 0 : 1;
         rotm[gpstk::RinexObsHeader::P2].ssi = snr2ssi(j->second.snr);

         rotm[gpstk::RinexObsHeader::L2].data = j->second.phase;
         rotm[gpstk::RinexObsHeader::L2].lli = j->second.lockCount ? 0 : 1;
         rotm[gpstk::RinexObsHeader::L2].ssi = snr2ssi(j->second.snr);

         rotm[gpstk::RinexObsHeader::D2].data = j->second.doppler;
         rotm[gpstk::RinexObsHeader::D2].lli = j->second.lockCount ? 0 : 1;
         rotm[gpstk::RinexObsHeader::D2].ssi = snr2ssi(j->second.snr);

         rotm[gpstk::RinexObsHeader::S2].data = j->second.snr;
      }

      // Now get the C2
      j = ol.find(MDPObsEpoch::ObsKey(ccL2, rcCM));
      if (j == ol.end())
         j = ol.find(MDPObsEpoch::ObsKey(ccL2, rcCL));
      if (j == ol.end())
         j = ol.find(MDPObsEpoch::ObsKey(ccL2, rcCMCL));
      if (j != ol.end())
      {
         rotm[gpstk::RinexObsHeader::C2].data = j->second.pseudorange;
         rotm[gpstk::RinexObsHeader::C2].lli = j->second.lockCount ? 0 : 1;
         rotm[gpstk::RinexObsHeader::C2].ssi = snr2ssi(j->second.snr);
      }
      return rotm;
   }

   RinexObsData makeRinexObsData(const gpstk::MDPEpoch& mdp)
   {
      RinexObsData rod;

      rod.clockOffset=0;
      rod.numSvs = mdp.size();
      rod.epochFlag = 0;
      rod.time = mdp.begin()->second.time;

      for (MDPEpoch::const_iterator i=mdp.begin(); i!=mdp.end(); i++)
      {
         const MDPObsEpoch& moe = i->second;
         gpstk::SatID svid(moe.prn, gpstk::SatID::systemGPS);
         rod.obs[svid] = makeRinexObsTypeMap(moe);
      }
      return rod;
   }

   // Try to convert the given pages into an EngAlmanc object. Returns true
   // upon success. This routine is tuned for two different types of nav data.
   //
   // The first is for a receiver that outputs all 4/5 subframes from a given
   // code/carrier. Basically it looks for a 12.5 minute cycle that starts
   // with page 1 from subframe 4. It makes sure that there hasn't been a
   // cutover during it by checking that all sv pages (i.e. svid 1-32) have
   // the same toa as the last page 25 (svid 51). This mode is the default and
   // is set with the requireFull parameter.
   //
   // The second is for a receiver that only puts out a set of 4/5 subframes
   // that "should" be a complete almanac. Note that it doesn't output pages
   // for SVs that are set to the default data.
   //
   // The only receiver that this has been tested on is the Ashtech Z(Y)12.
   //
   // In the IS-GPS-200D, see pages 72-79, 82, 105
   bool makeEngAlmanac(EngAlmanac& alm,
                       const AlmanacPages& pages,
                       bool requireFull) throw()
   {
      AlmanacPages::const_iterator sf4p1  = pages.find(SubframePage(4,  1));
      AlmanacPages::const_iterator sf4p18 = pages.find(SubframePage(4, 18));
      AlmanacPages::const_iterator sf4p25 = pages.find(SubframePage(4, 25));
      AlmanacPages::const_iterator sf5p25 = pages.find(SubframePage(5, 25));

      // These pages are required for a reasonable alm
      if (sf4p18==pages.end() || sf4p25==pages.end() || sf5p25==pages.end())
         return false;

      long sf4p1sow=0;
      if (requireFull)
      {
         if (sf4p1==pages.end())
            return false;
         else
            sf4p1sow = sf4p1->second.getHOWTime();
      }

      int week=sf4p18->second.time.GPSfullweek();

      for (int p=1; p<=25; p++)
      {
         for (int sf=4; sf<=5; sf++)
         {
            AlmanacPages::const_iterator i = pages.find(SubframePage(sf, p));
            if (i == pages.end())
            {
               if (requireFull)
                  return false;
               else
                  continue;
            }

            // All pages have to be contingious for the full alm mode.
            if (requireFull)
            {
               long sow = i->second.getHOWTime();
               if (sow != sf4p1sow + (sf-4)*6 + (p-1)*30)
                  return false;
            }

            long sfa[10];
            long long_sfa[10];
            i->second.fillArray(sfa);
            copy( &sfa[0], &sfa[10], long_sfa);
            if (!alm.addSubframe(long_sfa, week))
               return false;
         }
      }
      return true;
   }

   // Try to convert the given pages into an EngEphemeris object. Returns true
   // upon success.
   bool makeEngEphemeris(EngEphemeris& eph, const EphemerisPages& pages)
   {
      EphemerisPages::const_iterator sf[4];

      sf[1] = pages.find(1);
      if (sf[1] == pages.end())
         return false;

      sf[2] = pages.find(2);
      if (sf[2] == pages.end())
         return false;

      sf[3] = pages.find(3);
      if (sf[3] == pages.end())
         return false;

      long t1 = sf[1]->second.getHOWTime();
      long t2 = sf[2]->second.getHOWTime();
      long t3 = sf[3]->second.getHOWTime();
      if (t2 != t1+6 || t3 != t1+12)
         return false;

      int prn = sf[1]->second.prn;
      int week = sf[1]->second.time.GPSfullweek();
      long sfa[10];
      long long_sfa[10];

      for (int i=1; i<=3; i++)
      {
         sf[i]->second.fillArray(sfa);
         for( int j = 0; j < 10; j++ )
            long_sfa[j] = static_cast<long>( sfa[j] );
         if (!eph.addSubframe(long_sfa, week, prn, 0))
            return false;
      }

      if (eph.isData(1) && eph.isData(2) && eph.isData(3))
         return true;

      return false;
   }
} // end of namespace gpstk
<commit_msg>A conditional expression was being used backwards in makeRinexObsTypeMap, causing the LLI to be set incorrectly for L2 observables. <commit_after>#pragma ident "$Id$"

//============================================================================
//
//  This file is part of GPSTk, the GPS Toolkit.
//
//  The GPSTk is free software; you can redistribute it and/or modify
//  it under the terms of the GNU Lesser General Public License as published
//  by the Free Software Foundation; either version 2.1 of the License, or
//  any later version.
//
//  The GPSTk is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with GPSTk; if not, write to the Free Software Foundation,
//  Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
//  Copyright 2004, The University of Texas at Austin
//
//============================================================================

//============================================================================
//
//This software developed by Applied Research Laboratories at the University of
//Texas at Austin, under contract to an agency or agencies within the U.S.
//Department of Defense. The U.S. Government retains all rights to use,
//duplicate, distribute, disclose, or release this software.
//
//Pursuant to DoD Directive 523024
//
// DISTRIBUTION STATEMENT A: This software has been approved for public
//                           release, distribution is unlimited.
//
//=============================================================================

/** @file Translates between various similiar objects */

#include "StringUtils.hpp"
#include "RinexObsID.hpp"

#include "RinexConverters.hpp"

using namespace std;

namespace gpstk
{
   short snr2ssi(float x)
   {
      // These values were obtained from the comments in a RINEX obs file that was
      // generated from a TurboBinary file recorded on an AOA Benchmark  receiver
      if (x>316) return 9;
      if (x>100) return 8;
      if (x>31.6) return 7;
      if (x>10) return 6;
      if (x>3.2) return 5;
      if (x>0) return 4;
      return 0;
   }

   RinexObsData::RinexObsTypeMap makeRinexObsTypeMap(const MDPObsEpoch& moe) throw()
   {
      gpstk::RinexObsData::RinexObsTypeMap rotm;
      MDPObsEpoch::ObsMap ol=moe.obs;
      MDPObsEpoch::ObsMap::const_iterator j;

      // The C1 Rinex obs is easy
      j = ol.find(MDPObsEpoch::ObsKey(ccL1,rcCA));
      if (j!=ol.end())
      {
         rotm[gpstk::RinexObsHeader::C1].data = j->second.pseudorange;
         rotm[gpstk::RinexObsHeader::C1].lli = j->second.lockCount ? 1 : 0;
         rotm[gpstk::RinexObsHeader::C1].ssi = snr2ssi(j->second.snr);

         rotm[gpstk::RinexObsHeader::L1].data = j->second.phase;
         rotm[gpstk::RinexObsHeader::L1].lli = j->second.lockCount ? 1 : 0;
         rotm[gpstk::RinexObsHeader::L1].ssi = snr2ssi(j->second.snr);

         rotm[gpstk::RinexObsHeader::D1].data = j->second.doppler;
         rotm[gpstk::RinexObsHeader::D1].lli = j->second.lockCount ? 1 : 0;
         rotm[gpstk::RinexObsHeader::D1].ssi = snr2ssi(j->second.snr);

         rotm[gpstk::RinexObsHeader::S1].data = j->second.snr;
      }

      // Now get the P1, L1, D1, S1 obs
      j = ol.find(MDPObsEpoch::ObsKey(ccL1, rcYcode));
      if (j == ol.end())
         j = ol.find(MDPObsEpoch::ObsKey(ccL1, rcPcode));
      if (j == ol.end())
         j = ol.find(MDPObsEpoch::ObsKey(ccL1, rcCodeless));
      if (j != ol.end())
      {
         rotm[gpstk::RinexObsHeader::P1].data = j->second.pseudorange;
         rotm[gpstk::RinexObsHeader::P1].lli  = j->second.lockCount ? 1 : 0;
         rotm[gpstk::RinexObsHeader::P1].ssi  = snr2ssi(j->second.snr);

         rotm[gpstk::RinexObsHeader::L1].data = j->second.phase;
         rotm[gpstk::RinexObsHeader::L1].lli  = j->second.lockCount ? 1 : 0;
         rotm[gpstk::RinexObsHeader::L1].ssi  = snr2ssi(j->second.snr);

         rotm[gpstk::RinexObsHeader::D1].data = j->second.doppler;
         rotm[gpstk::RinexObsHeader::D1].lli  = j->second.lockCount ? 1 : 0;
         rotm[gpstk::RinexObsHeader::D1].ssi  = snr2ssi(j->second.snr);

         rotm[gpstk::RinexObsHeader::S1].data = j->second.snr;
      }

      // Now get the P2, L2, D2, S2 obs
      j = ol.find(MDPObsEpoch::ObsKey(ccL2, rcYcode));
      if (j == ol.end())
         j = ol.find(MDPObsEpoch::ObsKey(ccL2, rcPcode));
      if (j == ol.end())
         j = ol.find(MDPObsEpoch::ObsKey(ccL2, rcCodeless));
      if (j != ol.end())
      {
         rotm[gpstk::RinexObsHeader::P2].data = j->second.pseudorange;
         rotm[gpstk::RinexObsHeader::P2].lli  = j->second.lockCount ? 1 : 0;
         rotm[gpstk::RinexObsHeader::P2].ssi  = snr2ssi(j->second.snr);

         rotm[gpstk::RinexObsHeader::L2].data = j->second.phase;
         rotm[gpstk::RinexObsHeader::L2].lli  = j->second.lockCount ? 1 : 0;
         rotm[gpstk::RinexObsHeader::L2].ssi  = snr2ssi(j->second.snr);

         rotm[gpstk::RinexObsHeader::D2].data = j->second.doppler;
         rotm[gpstk::RinexObsHeader::D2].lli  = j->second.lockCount ? 1 : 0;
         rotm[gpstk::RinexObsHeader::D2].ssi  = snr2ssi(j->second.snr);

         rotm[gpstk::RinexObsHeader::S2].data = j->second.snr;
      }

      // Now get the C2
      j = ol.find(MDPObsEpoch::ObsKey(ccL2, rcCM));
      if (j == ol.end())
         j = ol.find(MDPObsEpoch::ObsKey(ccL2, rcCL));
      if (j == ol.end())
         j = ol.find(MDPObsEpoch::ObsKey(ccL2, rcCMCL));
      if (j != ol.end())
      {
         rotm[gpstk::RinexObsHeader::C2].data = j->second.pseudorange;
         rotm[gpstk::RinexObsHeader::C2].lli  = j->second.lockCount ? 1 : 0;
         rotm[gpstk::RinexObsHeader::C2].ssi  = snr2ssi(j->second.snr);
      }
      return rotm;
   }

   RinexObsData makeRinexObsData(const gpstk::MDPEpoch& mdp)
   {
      RinexObsData rod;

      rod.clockOffset=0;
      rod.numSvs = mdp.size();
      rod.epochFlag = 0;
      rod.time = mdp.begin()->second.time;

      for (MDPEpoch::const_iterator i=mdp.begin(); i!=mdp.end(); i++)
      {
         const MDPObsEpoch& moe = i->second;
         gpstk::SatID svid(moe.prn, gpstk::SatID::systemGPS);
         rod.obs[svid] = makeRinexObsTypeMap(moe);
      }
      return rod;
   }

   // Try to convert the given pages into an EngAlmanc object. Returns true
   // upon success. This routine is tuned for two different types of nav data.
   //
   // The first is for a receiver that outputs all 4/5 subframes from a given
   // code/carrier. Basically it looks for a 12.5 minute cycle that starts
   // with page 1 from subframe 4. It makes sure that there hasn't been a
   // cutover during it by checking that all sv pages (i.e. svid 1-32) have
   // the same toa as the last page 25 (svid 51). This mode is the default and
   // is set with the requireFull parameter.
   //
   // The second is for a receiver that only puts out a set of 4/5 subframes
   // that "should" be a complete almanac. Note that it doesn't output pages
   // for SVs that are set to the default data.
   //
   // The only receiver that this has been tested on is the Ashtech Z(Y)12.
   //
   // In the IS-GPS-200D, see pages 72-79, 82, 105
   bool makeEngAlmanac(EngAlmanac& alm,
                       const AlmanacPages& pages,
                       bool requireFull) throw()
   {
      AlmanacPages::const_iterator sf4p1  = pages.find(SubframePage(4,  1));
      AlmanacPages::const_iterator sf4p18 = pages.find(SubframePage(4, 18));
      AlmanacPages::const_iterator sf4p25 = pages.find(SubframePage(4, 25));
      AlmanacPages::const_iterator sf5p25 = pages.find(SubframePage(5, 25));

      // These pages are required for a reasonable alm
      if (sf4p18==pages.end() || sf4p25==pages.end() || sf5p25==pages.end())
         return false;

      long sf4p1sow=0;
      if (requireFull)
      {
         if (sf4p1==pages.end())
            return false;
         else
            sf4p1sow = sf4p1->second.getHOWTime();
      }

      int week=sf4p18->second.time.GPSfullweek();

      for (int p=1; p<=25; p++)
      {
         for (int sf=4; sf<=5; sf++)
         {
            AlmanacPages::const_iterator i = pages.find(SubframePage(sf, p));
            if (i == pages.end())
            {
               if (requireFull)
                  return false;
               else
                  continue;
            }

            // All pages have to be contingious for the full alm mode.
            if (requireFull)
            {
               long sow = i->second.getHOWTime();
               if (sow != sf4p1sow + (sf-4)*6 + (p-1)*30)
                  return false;
            }

            long sfa[10];
            long long_sfa[10];
            i->second.fillArray(sfa);
            copy( &sfa[0], &sfa[10], long_sfa);
            if (!alm.addSubframe(long_sfa, week))
               return false;
         }
      }
      return true;
   }

   // Try to convert the given pages into an EngEphemeris object. Returns true
   // upon success.
   bool makeEngEphemeris(EngEphemeris& eph, const EphemerisPages& pages)
   {
      EphemerisPages::const_iterator sf[4];

      sf[1] = pages.find(1);
      if (sf[1] == pages.end())
         return false;

      sf[2] = pages.find(2);
      if (sf[2] == pages.end())
         return false;

      sf[3] = pages.find(3);
      if (sf[3] == pages.end())
         return false;

      long t1 = sf[1]->second.getHOWTime();
      long t2 = sf[2]->second.getHOWTime();
      long t3 = sf[3]->second.getHOWTime();
      if (t2 != t1+6 || t3 != t1+12)
         return false;

      int prn = sf[1]->second.prn;
      int week = sf[1]->second.time.GPSfullweek();
      long sfa[10];
      long long_sfa[10];

      for (int i=1; i<=3; i++)
      {
         sf[i]->second.fillArray(sfa);
         for( int j = 0; j < 10; j++ )
            long_sfa[j] = static_cast<long>( sfa[j] );
         if (!eph.addSubframe(long_sfa, week, prn, 0))
            return false;
      }

      if (eph.isData(1) && eph.isData(2) && eph.isData(3))
         return true;

      return false;
   }
} // end of namespace gpstk
<|endoftext|>


<commit_before><commit_msg>Cleaned up handling of GUI toggles.<commit_after><|endoftext|>


<commit_before>#include "Cache.h"

#include "preprocessor/llvm_includes_start.h"
#include <llvm/IR/Module.h>
#include <llvm/IR/LLVMContext.h>
#include <llvm/IR/Instructions.h>
#include <llvm/Support/Path.h>
#include <llvm/Support/FileSystem.h>
#include <llvm/Support/raw_os_ostream.h>
#include "preprocessor/llvm_includes_end.h"

#include "ExecutionEngine.h"
#include "Utils.h"

namespace dev
{
namespace eth
{
namespace jit
{

namespace
{
	llvm::MemoryBuffer* g_lastObject;
	ExecutionEngineListener* g_listener;
}

ObjectCache* Cache::getObjectCache(ExecutionEngineListener* _listener)
{
	static ObjectCache objectCache;
	g_listener = _listener;
	return &objectCache;
}

std::unique_ptr<llvm::Module> Cache::getObject(std::string const& id)
{
	if (g_listener)
		g_listener->stateChanged(ExecState::CacheLoad);

	DLOG(cache) << id << ": search\n";
	if (!CHECK(!g_lastObject))
		g_lastObject = nullptr;

	llvm::SmallString<256> cachePath;
	llvm::sys::path::system_temp_directory(false, cachePath);
	llvm::sys::path::append(cachePath, "evm_objs", id);

#if defined(__GNUC__) && !defined(NDEBUG)
	llvm::sys::fs::file_status st;
	auto err = llvm::sys::fs::status(cachePath.str(), st);
	if (err)
		return nullptr;
	auto mtime = st.getLastModificationTime().toEpochTime();

	std::tm tm;
	strptime(__DATE__ __TIME__, " %b %d %Y %H:%M:%S", &tm);
	auto btime = (uint64_t)std::mktime(&tm);
	if (btime > mtime)
		return nullptr;
#endif

	if (auto r = llvm::MemoryBuffer::getFile(cachePath.str(), -1, false))
		g_lastObject = llvm::MemoryBuffer::getMemBufferCopy(r.get()->getBuffer());
	else if (r.getError() != std::make_error_code(std::errc::no_such_file_or_directory))
		std::cerr << r.getError().message(); // TODO: Add log

	if (g_lastObject)  // if object found create fake module
	{
		DLOG(cache) << id << ": found\n";
		auto&& context = llvm::getGlobalContext();
		auto module = std::unique_ptr<llvm::Module>(new llvm::Module(id, context));
		auto mainFuncType = llvm::FunctionType::get(llvm::Type::getVoidTy(context), {}, false);
		auto mainFunc = llvm::Function::Create(mainFuncType, llvm::Function::ExternalLinkage, id, module.get());
		auto bb = llvm::BasicBlock::Create(context, {}, mainFunc);
		bb->getInstList().push_back(new llvm::UnreachableInst{context});
		return module;
	}
	DLOG(cache) << id << ": not found\n";
	return nullptr;
}

void ObjectCache::notifyObjectCompiled(llvm::Module const* _module, llvm::MemoryBuffer const* _object)
{
	if (g_listener)
		g_listener->stateChanged(ExecState::CacheWrite);

	auto&& id = _module->getModuleIdentifier();
	llvm::SmallString<256> cachePath;
	llvm::sys::path::system_temp_directory(false, cachePath);
	llvm::sys::path::append(cachePath, "evm_objs");

	if (llvm::sys::fs::create_directory(cachePath.str()))
		return; // TODO: Add log

	llvm::sys::path::append(cachePath, id);

	DLOG(cache) << id << ": write\n";
	std::string error;
	llvm::raw_fd_ostream cacheFile(cachePath.c_str(), error, llvm::sys::fs::F_None);
	cacheFile << _object->getBuffer();
}

llvm::MemoryBuffer* ObjectCache::getObject(llvm::Module const* _module)
{
	DLOG(cache) << _module->getModuleIdentifier() << ": use\n";
	auto o = g_lastObject;
	g_lastObject = nullptr;
	return o;
}

}
}
}
<commit_msg>Add library version stamp to cached objects<commit_after>#include "Cache.h"

#include "preprocessor/llvm_includes_start.h"
#include <llvm/IR/Module.h>
#include <llvm/IR/LLVMContext.h>
#include <llvm/IR/Instructions.h>
#include <llvm/Support/Path.h>
#include <llvm/Support/FileSystem.h>
#include <llvm/Support/raw_os_ostream.h>
#include "preprocessor/llvm_includes_end.h"

#include "ExecutionEngine.h"
#include "Utils.h"
#include "BuildInfo.gen.h"

namespace dev
{
namespace eth
{
namespace jit
{

namespace
{
	llvm::MemoryBuffer* g_lastObject;
	ExecutionEngineListener* g_listener;
	static const size_t c_versionStampLength = 32;

	llvm::StringRef getLibVersionStamp()
	{
		static auto version = llvm::SmallString<c_versionStampLength>{};
		if (version.empty())
		{
			version = EVMJIT_VERSION_FULL;
			version.resize(c_versionStampLength);
		}
		return version;
	}
}

ObjectCache* Cache::getObjectCache(ExecutionEngineListener* _listener)
{
	static ObjectCache objectCache;
	g_listener = _listener;
	return &objectCache;
}

std::unique_ptr<llvm::Module> Cache::getObject(std::string const& id)
{
	if (g_listener)
		g_listener->stateChanged(ExecState::CacheLoad);

	DLOG(cache) << id << ": search\n";
	if (!CHECK(!g_lastObject))
		g_lastObject = nullptr;

	llvm::SmallString<256> cachePath;
	llvm::sys::path::system_temp_directory(false, cachePath);
	llvm::sys::path::append(cachePath, "evm_objs", id);

	if (auto r = llvm::MemoryBuffer::getFile(cachePath.str(), -1, false))
	{
		auto& buf = r.get();
		auto objVersionStamp = buf->getBufferSize() >= c_versionStampLength ? llvm::StringRef{buf->getBufferEnd() - c_versionStampLength, c_versionStampLength} : llvm::StringRef{};
		if (objVersionStamp == getLibVersionStamp())
			g_lastObject = llvm::MemoryBuffer::getMemBufferCopy(r.get()->getBuffer());
		else
			DLOG(cache) << "Unmatched version: " << objVersionStamp.str() << ", expected " << getLibVersionStamp().str() << "\n";
	}
	else if (r.getError() != std::make_error_code(std::errc::no_such_file_or_directory))
	{
		DLOG(cache) << r.getError().message(); // TODO: Add warning log
	}

	if (g_lastObject)  // if object found create fake module
	{
		DLOG(cache) << id << ": found\n";
		auto&& context = llvm::getGlobalContext();
		auto module = std::unique_ptr<llvm::Module>(new llvm::Module(id, context));
		auto mainFuncType = llvm::FunctionType::get(llvm::Type::getVoidTy(context), {}, false);
		auto mainFunc = llvm::Function::Create(mainFuncType, llvm::Function::ExternalLinkage, id, module.get());
		auto bb = llvm::BasicBlock::Create(context, {}, mainFunc);
		bb->getInstList().push_back(new llvm::UnreachableInst{context});
		return module;
	}
	DLOG(cache) << id << ": not found\n";
	return nullptr;
}

void ObjectCache::notifyObjectCompiled(llvm::Module const* _module, llvm::MemoryBuffer const* _object)
{
	if (g_listener)
		g_listener->stateChanged(ExecState::CacheWrite);

	auto&& id = _module->getModuleIdentifier();
	llvm::SmallString<256> cachePath;
	llvm::sys::path::system_temp_directory(false, cachePath);
	llvm::sys::path::append(cachePath, "evm_objs");

	if (llvm::sys::fs::create_directory(cachePath.str()))
		DLOG(cache) << "Cannot create cache dir " << cachePath.str().str() << "\n";

	llvm::sys::path::append(cachePath, id);

	DLOG(cache) << id << ": write\n";
	std::string error;
	llvm::raw_fd_ostream cacheFile(cachePath.c_str(), error, llvm::sys::fs::F_None);
	cacheFile << _object->getBuffer() << getLibVersionStamp();
}

llvm::MemoryBuffer* ObjectCache::getObject(llvm::Module const* _module)
{
	DLOG(cache) << _module->getModuleIdentifier() << ": use\n";
	auto o = g_lastObject;
	g_lastObject = nullptr;
	return o;
}

}
}
}
<|endoftext|>


<commit_before>#include "matcher.h"

#include "3rd-party/catch.hpp"

#include "matchable.h"
#include "matcherexception.h"

using namespace newsboat;

struct testMatchable : public Matchable {
	virtual bool has_attribute(const std::string& attribname)
	{
		if (attribname == "abcd" || attribname == "AAAA" ||
			attribname == "tags")
			return true;
		return false;
	}

	virtual std::string get_attribute(const std::string& attribname)
	{
		if (attribname == "abcd")
			return "xyz";
		if (attribname == "AAAA")
			return "12345";
		if (attribname == "tags")
			return "foo bar baz quux";
		return "";
	}
};

TEST_CASE("Operator `=` checks if field has given value", "[Matcher]")
{
	testMatchable mock;
	Matcher m;

	m.parse("abcd = \"xyz\"");
	REQUIRE(m.matches(&mock));

	m.parse("abcd = \"uiop\"");
	REQUIRE_FALSE(m.matches(&mock));
}

TEST_CASE("Operator `!=` checks if field doesn't have given value", "[Matcher]")
{
	testMatchable mock;
	Matcher m;

	m.parse("abcd != \"uiop\"");
	REQUIRE(m.matches(&mock));

	m.parse("abcd != \"xyz\"");
	REQUIRE_FALSE(m.matches(&mock));
}

TEST_CASE("Operator `=~` checks if field matches given regex", "[Matcher]")
{
	testMatchable mock;
	Matcher m;

	m.parse("AAAA =~ \".\"");
	REQUIRE(m.matches(&mock));

	m.parse("AAAA =~ \"123\"");
	REQUIRE(m.matches(&mock));

	m.parse("AAAA =~ \"234\"");
	REQUIRE(m.matches(&mock));

	m.parse("AAAA =~ \"45\"");
	REQUIRE(m.matches(&mock));

	m.parse("AAAA =~ \"^12345$\"");
	REQUIRE(m.matches(&mock));

	m.parse("AAAA =~ \"^123456$\"");
	REQUIRE_FALSE(m.matches(&mock));
}

TEST_CASE("Matcher throws if expression contains undefined fields", "[Matcher]")
{
	testMatchable mock;
	Matcher m;

	m.parse("BBBB =~ \"foo\"");
	REQUIRE_THROWS_AS(m.matches(&mock), MatcherException);

	m.parse("BBBB # \"foo\"");
	REQUIRE_THROWS_AS(m.matches(&mock), MatcherException);

	m.parse("BBBB < 0");
	REQUIRE_THROWS_AS(m.matches(&mock), MatcherException);

	m.parse("BBBB > 0");
	REQUIRE_THROWS_AS(m.matches(&mock), MatcherException);

	m.parse("BBBB between 1:23");
	REQUIRE_THROWS_AS(m.matches(&mock), MatcherException);
}

TEST_CASE("Matcher throws if regex passed to `=~` or `!~` is invalid",
	"[Matcher]")
{
	testMatchable mock;
	Matcher m;

	m.parse("AAAA =~ \"[[\"");
	REQUIRE_THROWS_AS(m.matches(&mock), MatcherException);

	m.parse("AAAA !~ \"[[\"");
	REQUIRE_THROWS_AS(m.matches(&mock), MatcherException);
}

TEST_CASE("Operator `!~` checks if field doesn't match given regex",
	"[Matcher]")
{
	testMatchable mock;
	Matcher m;

	m.parse("AAAA !~ \".\"");
	REQUIRE_FALSE(m.matches(&mock));

	m.parse("AAAA !~ \"123\"");
	REQUIRE_FALSE(m.matches(&mock));

	m.parse("AAAA !~ \"234\"");
	REQUIRE_FALSE(m.matches(&mock));

	m.parse("AAAA !~ \"45\"");
	REQUIRE_FALSE(m.matches(&mock));

	m.parse("AAAA !~ \"^12345$\"");
	REQUIRE_FALSE(m.matches(&mock));
}

TEST_CASE("Operator `#` checks if \"tags\" field contains given value",
	"[Matcher]")
{
	testMatchable mock;
	Matcher m;

	m.parse("tags # \"foo\"");
	REQUIRE(m.matches(&mock));

	m.parse("tags # \"baz\"");
	REQUIRE(m.matches(&mock));

	m.parse("tags # \"quux\"");
	REQUIRE(m.matches(&mock));

	m.parse("tags # \"xyz\"");
	REQUIRE_FALSE(m.matches(&mock));

	m.parse("tags # \"foo bar\"");
	REQUIRE_FALSE(m.matches(&mock));

	m.parse("tags # \"foo\" and tags # \"bar\"");
	REQUIRE(m.matches(&mock));

	m.parse("tags # \"foo\" and tags # \"xyz\"");
	REQUIRE_FALSE(m.matches(&mock));

	m.parse("tags # \"foo\" or tags # \"xyz\"");
	REQUIRE(m.matches(&mock));
}

TEST_CASE("Operator `!#` checks if \"tags\" field doesn't contain given value",
	"[Matcher]")
{
	testMatchable mock;
	Matcher m;

	m.parse("tags !# \"nein\"");
	REQUIRE(m.matches(&mock));

	m.parse("tags !# \"foo\"");
	REQUIRE_FALSE(m.matches(&mock));
}

TEST_CASE(
	"Operators `>`, `>=`, `<` and `<=` comparee field's value to given "
	"value",
	"[Matcher]")
{
	testMatchable mock;
	Matcher m;

	m.parse("AAAA > 12344");
	REQUIRE(m.matches(&mock));

	m.parse("AAAA > 12345");
	REQUIRE_FALSE(m.matches(&mock));

	m.parse("AAAA >= 12345");
	REQUIRE(m.matches(&mock));

	m.parse("AAAA < 12345");
	REQUIRE_FALSE(m.matches(&mock));

	m.parse("AAAA <= 12345");
	REQUIRE(m.matches(&mock));
}

TEST_CASE("Operator `between` checks if field's value is in given range",
	"[Matcher]")
{
	testMatchable mock;
	Matcher m;

	m.parse("AAAA between 0:12345");
	REQUIRE(m.get_parse_error() == "");
	REQUIRE(m.matches(&mock));

	m.parse("AAAA between 12345:12345");
	REQUIRE(m.matches(&mock));

	m.parse("AAAA between 23:12344");
	REQUIRE_FALSE(m.matches(&mock));

	m.parse("AAAA between 0");
	REQUIRE_FALSE(m.matches(&mock));

	m.parse("AAAA between 12346:12344");
	REQUIRE(m.matches(&mock));
}

TEST_CASE("Invalid expression results in parsing error", "[Matcher]")
{
	Matcher m;

	REQUIRE_FALSE(m.parse("AAAA between 0:15:30"));
	REQUIRE(m.get_parse_error() != "");
}

TEST_CASE("get_expression() returns previously parsed expression", "[Matcher]")
{
	Matcher m2("AAAA between 1:30000");
	REQUIRE(m2.get_expression() == "AAAA between 1:30000");
}
<commit_msg>Give mock Matchable in Matcher tests a unique name<commit_after>#include "matcher.h"

#include "3rd-party/catch.hpp"

#include "matchable.h"
#include "matcherexception.h"

using namespace newsboat;

struct MatcherMockMatchable : public Matchable {
	virtual bool has_attribute(const std::string& attribname)
	{
		if (attribname == "abcd" || attribname == "AAAA" ||
			attribname == "tags") {
			return true;
		}
		return false;
	}

	virtual std::string get_attribute(const std::string& attribname)
	{
		if (attribname == "abcd") {
			return "xyz";
		} else if (attribname == "AAAA") {
			return "12345";
		} else if (attribname == "tags") {
			return "foo bar baz quux";
		}
		return "";
	}
};

TEST_CASE("Operator `=` checks if field has given value", "[Matcher]")
{
	MatcherMockMatchable mock;
	Matcher m;

	m.parse("abcd = \"xyz\"");
	REQUIRE(m.matches(&mock));

	m.parse("abcd = \"uiop\"");
	REQUIRE_FALSE(m.matches(&mock));
}

TEST_CASE("Operator `!=` checks if field doesn't have given value", "[Matcher]")
{
	MatcherMockMatchable mock;
	Matcher m;

	m.parse("abcd != \"uiop\"");
	REQUIRE(m.matches(&mock));

	m.parse("abcd != \"xyz\"");
	REQUIRE_FALSE(m.matches(&mock));
}

TEST_CASE("Operator `=~` checks if field matches given regex", "[Matcher]")
{
	MatcherMockMatchable mock;
	Matcher m;

	m.parse("AAAA =~ \".\"");
	REQUIRE(m.matches(&mock));

	m.parse("AAAA =~ \"123\"");
	REQUIRE(m.matches(&mock));

	m.parse("AAAA =~ \"234\"");
	REQUIRE(m.matches(&mock));

	m.parse("AAAA =~ \"45\"");
	REQUIRE(m.matches(&mock));

	m.parse("AAAA =~ \"^12345$\"");
	REQUIRE(m.matches(&mock));

	m.parse("AAAA =~ \"^123456$\"");
	REQUIRE_FALSE(m.matches(&mock));
}

TEST_CASE("Matcher throws if expression contains undefined fields", "[Matcher]")
{
	MatcherMockMatchable mock;
	Matcher m;

	m.parse("BBBB =~ \"foo\"");
	REQUIRE_THROWS_AS(m.matches(&mock), MatcherException);

	m.parse("BBBB # \"foo\"");
	REQUIRE_THROWS_AS(m.matches(&mock), MatcherException);

	m.parse("BBBB < 0");
	REQUIRE_THROWS_AS(m.matches(&mock), MatcherException);

	m.parse("BBBB > 0");
	REQUIRE_THROWS_AS(m.matches(&mock), MatcherException);

	m.parse("BBBB between 1:23");
	REQUIRE_THROWS_AS(m.matches(&mock), MatcherException);
}

TEST_CASE("Matcher throws if regex passed to `=~` or `!~` is invalid",
	"[Matcher]")
{
	MatcherMockMatchable mock;
	Matcher m;

	m.parse("AAAA =~ \"[[\"");
	REQUIRE_THROWS_AS(m.matches(&mock), MatcherException);

	m.parse("AAAA !~ \"[[\"");
	REQUIRE_THROWS_AS(m.matches(&mock), MatcherException);
}

TEST_CASE("Operator `!~` checks if field doesn't match given regex",
	"[Matcher]")
{
	MatcherMockMatchable mock;
	Matcher m;

	m.parse("AAAA !~ \".\"");
	REQUIRE_FALSE(m.matches(&mock));

	m.parse("AAAA !~ \"123\"");
	REQUIRE_FALSE(m.matches(&mock));

	m.parse("AAAA !~ \"234\"");
	REQUIRE_FALSE(m.matches(&mock));

	m.parse("AAAA !~ \"45\"");
	REQUIRE_FALSE(m.matches(&mock));

	m.parse("AAAA !~ \"^12345$\"");
	REQUIRE_FALSE(m.matches(&mock));
}

TEST_CASE("Operator `#` checks if \"tags\" field contains given value",
	"[Matcher]")
{
	MatcherMockMatchable mock;
	Matcher m;

	m.parse("tags # \"foo\"");
	REQUIRE(m.matches(&mock));

	m.parse("tags # \"baz\"");
	REQUIRE(m.matches(&mock));

	m.parse("tags # \"quux\"");
	REQUIRE(m.matches(&mock));

	m.parse("tags # \"xyz\"");
	REQUIRE_FALSE(m.matches(&mock));

	m.parse("tags # \"foo bar\"");
	REQUIRE_FALSE(m.matches(&mock));

	m.parse("tags # \"foo\" and tags # \"bar\"");
	REQUIRE(m.matches(&mock));

	m.parse("tags # \"foo\" and tags # \"xyz\"");
	REQUIRE_FALSE(m.matches(&mock));

	m.parse("tags # \"foo\" or tags # \"xyz\"");
	REQUIRE(m.matches(&mock));
}

TEST_CASE("Operator `!#` checks if \"tags\" field doesn't contain given value",
	"[Matcher]")
{
	MatcherMockMatchable mock;
	Matcher m;

	m.parse("tags !# \"nein\"");
	REQUIRE(m.matches(&mock));

	m.parse("tags !# \"foo\"");
	REQUIRE_FALSE(m.matches(&mock));
}

TEST_CASE(
	"Operators `>`, `>=`, `<` and `<=` comparee field's value to given "
	"value",
	"[Matcher]")
{
	MatcherMockMatchable mock;
	Matcher m;

	m.parse("AAAA > 12344");
	REQUIRE(m.matches(&mock));

	m.parse("AAAA > 12345");
	REQUIRE_FALSE(m.matches(&mock));

	m.parse("AAAA >= 12345");
	REQUIRE(m.matches(&mock));

	m.parse("AAAA < 12345");
	REQUIRE_FALSE(m.matches(&mock));

	m.parse("AAAA <= 12345");
	REQUIRE(m.matches(&mock));
}

TEST_CASE("Operator `between` checks if field's value is in given range",
	"[Matcher]")
{
	MatcherMockMatchable mock;
	Matcher m;

	m.parse("AAAA between 0:12345");
	REQUIRE(m.get_parse_error() == "");
	REQUIRE(m.matches(&mock));

	m.parse("AAAA between 12345:12345");
	REQUIRE(m.matches(&mock));

	m.parse("AAAA between 23:12344");
	REQUIRE_FALSE(m.matches(&mock));

	m.parse("AAAA between 0");
	REQUIRE_FALSE(m.matches(&mock));

	m.parse("AAAA between 12346:12344");
	REQUIRE(m.matches(&mock));
}

TEST_CASE("Invalid expression results in parsing error", "[Matcher]")
{
	Matcher m;

	REQUIRE_FALSE(m.parse("AAAA between 0:15:30"));
	REQUIRE(m.get_parse_error() != "");
}

TEST_CASE("get_expression() returns previously parsed expression", "[Matcher]")
{
	Matcher m2("AAAA between 1:30000");
	REQUIRE(m2.get_expression() == "AAAA between 1:30000");
}
<|endoftext|>


<commit_before>#ifndef __TEST_REQUIRE_HPP__
#define __TEST_REQUIRE_HPP__

namespace test
{

// bool, long, double, string, void*

class Comparison
{
public:
    Comparison( const char* expression );

protected:
    const char* m_Comparison;
};

class BoolComparison : public Comparison
{
public:
    BoolComparison( const char* expression, bool value );
    BoolComparison& is( bool value );
    BoolComparison& equals( bool value );

private:
    bool m_Value;
};

#define RequireThat( E ) RequireThat_(#E, E)
BoolComparison RequireThat_( const char* expression, bool value );

// ---- bool implementation ----

BoolComparison::BoolComparison( const char* expression, bool value ) :
    Comparison(expression),
    m_Value(value)
{
}

BoolComparison& BoolComparison::is( bool value )
{
    return equals(value);
}

BoolComparison& BoolComparison::equals( bool value )
{
    const char* expected = (value == true) ? "true" : "false";
    const char* got = (m_Value == true) ? "true" : "false";

    if(m_Value != value)
        testFail("Expected %s to be %s, but it was %s.",
            m_Comparison,
            expected,
            got);
    return *this;
}

BoolComparison RequireThat_( const char* expression, bool value )
{
    return BoolComparison(expression, value);
}

// ---- int implementation ----

IntComparison::IntComparison( const char* expression, long value ) :
    Comparison(expression),
    m_Value(value)
{
}

BoolComparison& BoolComparison::isTrue()
{
    return equals(true);
}

BoolComparison& BoolComparison::isFalse()
{
    return equals(false);
}

BoolComparison& BoolComparison::equals( bool value )
{
    const char* expected = (value == true) ? "true" : "false";
    const char* got = (m_Value == true) ? "true" : "false";

    if(m_Value != value)
        testFail("Expected %s to be %s, but it was %s.",
            m_Comparison,
            expected,
            got);
    return *this;
}

BoolComparison RequireThat_( const char* expression, bool value )
{
    return BoolComparison(expression, value);
}

}

#endif
<commit_msg>Extended require.hpp<commit_after>#ifndef __TEST_REQUIRE_HPP__
#define __TEST_REQUIRE_HPP__

namespace test
{

// bool, long, double, string, void*

class Requirement
{
public:
    Requirement( const char* expression );

protected:
    const char* m_Expression;
};

class BoolRequirement : public Requirement
{
public:
    BoolRequirement( const char* expression, bool value );
    BoolRequirement& is( bool value );
    BoolRequirement& isNot( bool value );
    BoolRequirement& equals( bool value );

private:
    bool m_Value;
};

class IntRequirement : public Requirement
{
public:
    IntRequirement( const char* expression, long value );
    IntRequirement& is( long value );
    IntRequirement& isNot( long value );
    IntRequirement& equals( long value );
    IntRequirement& isGreaterThan( long value );
    IntRequirement& isGreaterOrEqualTo( long value );
    IntRequirement& isSmallerThan( long value );
    IntRequirement& isSmallerOrEqualTo( long value );

private:
    long m_Value;
};

class FloatRequirement : public Requirement
{
public:
    FloatRequirement( const char* expression, double value );
    FloatRequirement& withEpsilon( double epsilon );
    FloatRequirement& is( double value );
    FloatRequirement& isNot( double value );
    FloatRequirement& equals( double value );
    FloatRequirement& isGreaterThan( double value );
    FloatRequirement& isGreaterOrEqualTo( double value );
    FloatRequirement& isSmallerThan( double value );
    FloatRequirement& isSmallerOrEqualTo( double value );

private:
    double m_Value;
    double m_Epsilon;
};

class StringRequirement : public Requirement
{
public:
    StringRequirement( const char* expression, const char* value );
    StringRequirement& is( const char* value );
    StringRequirement& isNot( const char* value );
    StringRequirement& equals( const char* value );
    StringRequirement& beginsWith( const char* value );
    StringRequirement& endsWith( const char* value );
    StringRequirement& contains( const char* value );
    StringRequirement& matches( const char* value );

private:
    const char* m_Value;
};

class PointerRequirement : public Requirement
{
public:
    StringRequirement( const char* expression, const void* value );
    StringRequirement& is( const void* value );
    StringRequirement& isNot( const void* value );
    StringRequirement& equals( const void* value );

private:
    const void* m_Value;
};

#define RequireThat( E ) RequireThat_(#E, E)
BoolRequirement RequireThat_( const char* expression, bool value );
IntRequirement RequireThat_( const char* expression, long value );
FloatRequirement RequireThat_( const char* expression, double value );
StringRequirement RequireThat_( const char* expression, const char* value );
PointerRequirement RequireThat_( const char* expression, const void* value );

// ---- bool implementation ----

BoolRequirement::BoolRequirement( const char* expression, bool value ) :
    Requirement(expression),
    m_Value(value)
{
}

BoolRequirement& BoolRequirement::is( bool value )
{
    const char* expected = (value == true) ? "true" : "false";
    const char* got = (m_Value == true) ? "true" : "false";

    if(m_Value != value)
        testAbortCase(TEST_FAIL_CASE, "Expected %s to be %s, but it was %s.",
            m_Expression,
            expected,
            got);
    return *this;
}

BoolRequirement& BoolRequirement::isNot( bool value )
{
    const char* expected = (value == true) ? "true" : "false";
    const char* got = (m_Value == true) ? "true" : "false";

    if(m_Value == value)
        testAbortCase(TEST_FAIL_CASE, "Expected %s to be %s, but it was %s.",
            m_Expression,
            expected,
            got);
    return *this;
}

BoolRequirement& BoolRequirement::equals( bool value )
{
    return is(value);
}

BoolRequirement RequireThat_( const char* expression, bool value )
{
    return BoolRequirement(expression, value);
}

// ---- int implementation ----

IntRequirement::IntRequirement( const char* expression, long value ) :
    Requirement(expression),
    m_Value(value)
{
}

IntRequirement( const char* expression, long value )
{

}

IntRequirement& IntRequirement::is( long value )
{
}

IntRequirement& IntRequirement::isNot( long value )
{
}

IntRequirement& IntRequirement::equals( long value )
{
}

IntRequirement& IntRequirement::isGreaterThan( long value )
{
}

IntRequirement& IntRequirement::isGreaterOrEqualTo( long value )
{
}

IntRequirement& IntRequirement::isSmallerThan( long value )
{
}

IntRequirement& IntRequirement::isSmallerOrEqualTo( long value )
{
}

}

#endif
<|endoftext|>


<commit_before>#include "viewer.hpp"

#include <SDL_ttf.h>
#include <SDL_image.h>

#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtx/intersect.hpp>
#include <glm/gtc/random.hpp>
#include <glm/gtx/string_cast.hpp>
#include <glm/gtx/rotate_vector.hpp>

#include <algorithm>
#include <iostream>

Viewer::~Viewer() {
    TTF_Quit();
    SDL_DestroyTexture(m_render_tex);
    SDL_DestroyRenderer(m_render);
    SDL_DestroyWindow(m_window);
    IMG_Quit();
    SDL_Quit();
}

int Viewer::init() {
    std::cout << "Start init" << std::endl;

    if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) != 0) {
        std::cerr << "SDL_Init error: " << SDL_GetError() << std::endl;
        return 1;
    }

    int width = 600;
    int height = 400;

    m_window = SDL_CreateWindow("trac0r", 100, 100, width, height, SDL_WINDOW_SHOWN);
    if (m_window == nullptr) {
        std::cerr << "SDL_CreateWindow error: " << SDL_GetError() << std::endl;
        SDL_Quit();
        return 1;
    }

    // m_render = SDL_CreateRenderer(m_window, -1, SDL_RENDERER_ACCELERATED |
    // SDL_RENDERER_PRESENTVSYNC);
    m_render = SDL_CreateRenderer(m_window, -1, SDL_RENDERER_ACCELERATED);
    m_render_tex = SDL_CreateTexture(m_render, SDL_PIXELFORMAT_ARGB8888,
                                     SDL_TEXTUREACCESS_STREAMING, width, height);
    m_pixels.resize(width * height, 0);

    if (m_render == nullptr) {
        SDL_DestroyWindow(m_window);
        std::cerr << "SDL_CreateRenderer error: " << SDL_GetError() << std::endl;
        SDL_Quit();
        return 1;
    }

    if (TTF_Init() != 0) {
        std::cerr << "SDL_ttf could not initialize! SDL_ttf error: " << SDL_GetError() << std::endl;
        return 1;
    }

    // Setup scene
    SDL_SetRelativeMouseMode(SDL_TRUE);
    setup_scene();

    std::cout << "Finish init" << std::endl;

    return 0;
}

void Viewer::setup_scene() {
    auto triangle = std::make_unique<Triangle>(glm::vec3{0.f, 5.f, 0.f}, glm::vec3{0.5f, 5.f, 0.f},
                                               glm::vec3{0.5f, 5.f, 0.5f}, glm::vec3{0.3, 0.3, 0.3},
                                               glm::vec3{0.2, 0.2, 0.2});
    m_scene.push_back(std::move(triangle));
    // for (auto i = 0; i < 2; i++) {
    //     auto triangle = std::make_unique<Triangle>(glm::ballRand(5.f), glm::ballRand(5.f),
    //     glm::ballRand(5.f), glm::vec3{0.8, 0.3, 0.3}, glm::vec3{0.5, 0.5, 0.5});
    //     m_scene.push_back(std::move(triangle));
    // }

    m_camera.pos = {0, 0, 0};
    m_camera.dir = {0, 1, 0};
    m_camera.up = {0, 0, 1};
    m_camera.fov = 90.f;
    m_camera.near_plane_dist = 0.1f;
    m_camera.far_plane_dist = 100.f;
}

glm::vec3 Viewer::intersect_scene(glm::vec3 &ray_pos, glm::vec3 &ray_dir, int depth) {
    const auto MAX_DEPTH = 5;

    if (depth == MAX_DEPTH)
        return {0, 0, 0};

    // check all triangles for collision
    bool collided = false;
    glm::vec3 ret_color;
    for (const auto &tri : m_scene) {
        glm::vec3 bary_pos;
        collided =
            glm::intersectRayTriangle(ray_pos, ray_dir, tri->m_v1, tri->m_v2, tri->m_v3, bary_pos);

        if (collided) {
            glm::vec3 new_ray_pos = ray_pos + ray_dir * bary_pos.z;
            auto new_ray_dir = tri->m_normal;
            new_ray_dir = glm::rotateX(tri->m_normal, glm::linearRand(-90.f, 90.f));
            new_ray_dir = glm::rotateY(tri->m_normal, glm::linearRand(-90.f, 90.f));

            float cos_theta = glm::dot(new_ray_dir, tri->m_normal);
            glm::vec3 brdf = 2.f * tri->m_reflectance * cos_theta;
            glm::vec3 reflected = intersect_scene(new_ray_pos, new_ray_dir, depth + 1);

            ret_color = tri->m_emittance + (brdf * reflected);
            break;
        }
    }

    if (collided) {
        return ret_color;
    } else {
        return {0, 0, 0};
    }
}

void Viewer::mainloop() {
    // Input
    SDL_Event e;
    while (SDL_PollEvent(&e)) {
        if (e.type == SDL_QUIT) {
            shutdown();
        }
        if (e.type == SDL_KEYDOWN) {
            if (e.key.keysym.sym == SDLK_ESCAPE) {
                shutdown();
            }
        }
    }

    glm::vec3 cam_velocity{0};
    const uint8_t *keystates = SDL_GetKeyboardState(0);
    if (keystates[SDL_SCANCODE_A])
        cam_velocity.x += -1;
    else if (keystates[SDL_SCANCODE_D])
        cam_velocity.x += 1;

    if (keystates[SDL_SCANCODE_W])
        cam_velocity.y += 1;
    else if (keystates[SDL_SCANCODE_S])
        cam_velocity.y += -1;

    m_camera.pos += cam_velocity;

    // Rendering here
    int width;
    int height;
    SDL_GetWindowSize(m_window, &width, &height);
    auto aspect_ratio = (float)width / (float)height;

    int mouse_x;
    int mouse_y;
    SDL_GetRelativeMouseState(&mouse_x, &mouse_y);

    m_camera.dir = glm::rotateX(m_camera.dir, mouse_y * 0.001f);
    m_camera.dir = glm::rotateZ(m_camera.dir, mouse_x * -0.001f);

    std::cout << glm::to_string(m_camera.pos) << std::endl;
    std::cout << glm::to_string(m_camera.dir) << std::endl;

    glm::mat4 projection_matrix = glm::perspective(
        m_camera.fov, aspect_ratio, m_camera.near_plane_dist, m_camera.far_plane_dist);
    glm::mat4 view_matrix = glm::lookAt(m_camera.pos, m_camera.pos + m_camera.dir, m_camera.up);

    // Sort by distance to camera
    std::sort(m_scene.begin(), m_scene.end(), [this](const auto &tri1, const auto &tri2) {
        return glm::distance(m_camera.pos, tri1->m_centroid) <
               glm::distance(m_camera.pos, tri2->m_centroid);
    });
    for (auto sample_cnt = 0; sample_cnt < 2; sample_cnt++) {
        for (auto x = 0; x < width; x++) {
            for (auto y = 0; y < height; y++) {
                glm::vec3 win_coords{x, y, 0};
                glm::mat4 model{1.0f};
                glm::vec4 viewport{0, 0, width, height};
                glm::vec3 object_coords =
                    glm::unProject(win_coords, model * view_matrix, projection_matrix, viewport);
                glm::vec3 color = intersect_scene(object_coords, m_camera.dir, 0);
                // std::cout << "r: " << color.r << " g: " << color.g << " b: " << color.b <<
                // std::endl;
                m_pixels[y * width + x] = 0xff << 24 | int(color.r * 255) << 16 |
                                          int(color.g * 255) << 8 | int(color.b * 255);
            }
        }
    }

    SDL_SetRenderDrawColor(m_render, glm::linearRand(0, 255), glm::linearRand(0, 255),
                           glm::linearRand(0, 255), 255);
    SDL_RenderClear(m_render);
    SDL_UpdateTexture(m_render_tex, 0, m_pixels.data(), width * sizeof(uint32_t));
    SDL_RenderCopy(m_render, m_render_tex, 0, 0);

    SDL_RenderPresent(m_render);

    int current_time = SDL_GetTicks();
    double dt = (current_time - m_last_frame_time) / 1000.0;
    (void)dt;
    m_last_frame_time = current_time;

    std::cout << "FPS: " << 1. / dt << std::endl;
}

SDL_Renderer *Viewer::renderer() {
    return m_render;
}

SDL_Window *Viewer::window() {
    return m_window;
}

bool Viewer::is_running() {
    return m_running;
}

void Viewer::shutdown() {
    m_running = false;
}
<commit_msg>Slower movement<commit_after>#include "viewer.hpp"

#include <SDL_ttf.h>
#include <SDL_image.h>

#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtx/intersect.hpp>
#include <glm/gtc/random.hpp>
#include <glm/gtx/string_cast.hpp>
#include <glm/gtx/rotate_vector.hpp>

#include <algorithm>
#include <iostream>

Viewer::~Viewer() {
    TTF_Quit();
    SDL_DestroyTexture(m_render_tex);
    SDL_DestroyRenderer(m_render);
    SDL_DestroyWindow(m_window);
    IMG_Quit();
    SDL_Quit();
}

int Viewer::init() {
    std::cout << "Start init" << std::endl;

    if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) != 0) {
        std::cerr << "SDL_Init error: " << SDL_GetError() << std::endl;
        return 1;
    }

    int width = 600;
    int height = 400;

    m_window = SDL_CreateWindow("trac0r", 100, 100, width, height, SDL_WINDOW_SHOWN);
    if (m_window == nullptr) {
        std::cerr << "SDL_CreateWindow error: " << SDL_GetError() << std::endl;
        SDL_Quit();
        return 1;
    }

    // m_render = SDL_CreateRenderer(m_window, -1, SDL_RENDERER_ACCELERATED |
    // SDL_RENDERER_PRESENTVSYNC);
    m_render = SDL_CreateRenderer(m_window, -1, SDL_RENDERER_ACCELERATED);
    m_render_tex = SDL_CreateTexture(m_render, SDL_PIXELFORMAT_ARGB8888,
                                     SDL_TEXTUREACCESS_STREAMING, width, height);
    m_pixels.resize(width * height, 0);

    if (m_render == nullptr) {
        SDL_DestroyWindow(m_window);
        std::cerr << "SDL_CreateRenderer error: " << SDL_GetError() << std::endl;
        SDL_Quit();
        return 1;
    }

    if (TTF_Init() != 0) {
        std::cerr << "SDL_ttf could not initialize! SDL_ttf error: " << SDL_GetError() << std::endl;
        return 1;
    }

    // Setup scene
    SDL_SetRelativeMouseMode(SDL_TRUE);
    setup_scene();

    std::cout << "Finish init" << std::endl;

    return 0;
}

void Viewer::setup_scene() {
    auto triangle = std::make_unique<Triangle>(glm::vec3{0.f, 5.f, 0.f}, glm::vec3{0.5f, 5.f, 0.f},
                                               glm::vec3{0.5f, 5.f, 0.5f}, glm::vec3{0.3, 0.3, 0.3},
                                               glm::vec3{0.2, 0.2, 0.2});
    m_scene.push_back(std::move(triangle));
    // for (auto i = 0; i < 2; i++) {
    //     auto triangle = std::make_unique<Triangle>(glm::ballRand(5.f), glm::ballRand(5.f),
    //     glm::ballRand(5.f), glm::vec3{0.8, 0.3, 0.3}, glm::vec3{0.5, 0.5, 0.5});
    //     m_scene.push_back(std::move(triangle));
    // }

    m_camera.pos = {0, 0, 0};
    m_camera.dir = {0, 1, 0};
    m_camera.up = {0, 0, 1};
    m_camera.fov = 90.f;
    m_camera.near_plane_dist = 0.1f;
    m_camera.far_plane_dist = 100.f;
}

glm::vec3 Viewer::intersect_scene(glm::vec3 &ray_pos, glm::vec3 &ray_dir, int depth) {
    const auto MAX_DEPTH = 5;

    if (depth == MAX_DEPTH)
        return {0, 0, 0};

    // check all triangles for collision
    bool collided = false;
    glm::vec3 ret_color;
    for (const auto &tri : m_scene) {
        glm::vec3 bary_pos;
        collided =
            glm::intersectRayTriangle(ray_pos, ray_dir, tri->m_v1, tri->m_v2, tri->m_v3, bary_pos);

        if (collided) {
            glm::vec3 new_ray_pos = ray_pos + ray_dir * bary_pos.z;
            auto new_ray_dir = tri->m_normal;
            new_ray_dir = glm::rotateX(tri->m_normal, glm::linearRand(-90.f, 90.f));
            new_ray_dir = glm::rotateY(tri->m_normal, glm::linearRand(-90.f, 90.f));

            float cos_theta = glm::dot(new_ray_dir, tri->m_normal);
            glm::vec3 brdf = 2.f * tri->m_reflectance * cos_theta;
            glm::vec3 reflected = intersect_scene(new_ray_pos, new_ray_dir, depth + 1);

            ret_color = tri->m_emittance + (brdf * reflected);
            break;
        }
    }

    if (collided) {
        return ret_color;
    } else {
        return {0, 0, 0};
    }
}

void Viewer::mainloop() {
    // Input
    SDL_Event e;
    while (SDL_PollEvent(&e)) {
        if (e.type == SDL_QUIT) {
            shutdown();
        }
        if (e.type == SDL_KEYDOWN) {
            if (e.key.keysym.sym == SDLK_ESCAPE) {
                shutdown();
            }
        }
    }

    glm::vec3 cam_velocity{0};
    const uint8_t *keystates = SDL_GetKeyboardState(0);
    if (keystates[SDL_SCANCODE_A])
        cam_velocity.x += -0.2f;
    else if (keystates[SDL_SCANCODE_D])
        cam_velocity.x += 0.2f;

    if (keystates[SDL_SCANCODE_W])
        cam_velocity.y += 0.2f;
    else if (keystates[SDL_SCANCODE_S])
        cam_velocity.y += -0.2f;

    m_camera.pos += cam_velocity;

    // Rendering here
    int width;
    int height;
    SDL_GetWindowSize(m_window, &width, &height);
    auto aspect_ratio = (float)width / (float)height;

    int mouse_x;
    int mouse_y;
    SDL_GetRelativeMouseState(&mouse_x, &mouse_y);

    m_camera.dir = glm::rotateX(m_camera.dir, mouse_y * 0.001f);
    m_camera.dir = glm::rotateZ(m_camera.dir, mouse_x * -0.001f);

    std::cout << glm::to_string(m_camera.pos) << std::endl;
    std::cout << glm::to_string(m_camera.dir) << std::endl;

    glm::mat4 projection_matrix = glm::perspective(
        m_camera.fov, aspect_ratio, m_camera.near_plane_dist, m_camera.far_plane_dist);
    glm::mat4 view_matrix = glm::lookAt(m_camera.pos, m_camera.pos + m_camera.dir, m_camera.up);

    // Sort by distance to camera
    std::sort(m_scene.begin(), m_scene.end(), [this](const auto &tri1, const auto &tri2) {
        return glm::distance(m_camera.pos, tri1->m_centroid) <
               glm::distance(m_camera.pos, tri2->m_centroid);
    });
    for (auto sample_cnt = 0; sample_cnt < 2; sample_cnt++) {
        for (auto x = 0; x < width; x++) {
            for (auto y = 0; y < height; y++) {
                glm::vec3 win_coords{x, y, 0};
                glm::mat4 model{1.0f};
                glm::vec4 viewport{0, 0, width, height};
                glm::vec3 object_coords =
                    glm::unProject(win_coords, model * view_matrix, projection_matrix, viewport);
                glm::vec3 color = intersect_scene(object_coords, m_camera.dir, 0);
                // std::cout << "r: " << color.r << " g: " << color.g << " b: " << color.b <<
                // std::endl;
                m_pixels[y * width + x] = 0xff << 24 | int(color.r * 255) << 16 |
                                          int(color.g * 255) << 8 | int(color.b * 255);
            }
        }
    }

    SDL_SetRenderDrawColor(m_render, glm::linearRand(0, 255), glm::linearRand(0, 255),
                           glm::linearRand(0, 255), 255);
    SDL_RenderClear(m_render);
    SDL_UpdateTexture(m_render_tex, 0, m_pixels.data(), width * sizeof(uint32_t));
    SDL_RenderCopy(m_render, m_render_tex, 0, 0);

    SDL_RenderPresent(m_render);

    int current_time = SDL_GetTicks();
    double dt = (current_time - m_last_frame_time) / 1000.0;
    (void)dt;
    m_last_frame_time = current_time;

    std::cout << "FPS: " << 1. / dt << std::endl;
}

SDL_Renderer *Viewer::renderer() {
    return m_render;
}

SDL_Window *Viewer::window() {
    return m_window;
}

bool Viewer::is_running() {
    return m_running;
}

void Viewer::shutdown() {
    m_running = false;
}
<|endoftext|>


<commit_before><commit_msg>sw: update hintids.hxx comments to match reality<commit_after><|endoftext|>


<commit_before>#include "biobj_simplex.hpp"

using namespace std;

Biobj_simplex::Biobj_simplex() {
  model = new OsiClpSolverInterface;
}

Biobj_simplex::~Biobj_simplex() {
  delete model;
  delete[] cost1;
  delete[] cost2;
  delete[] work_col;
  delete[] basics;
}

double Biobj_simplex::getInfinity() {
  return model->getInfinity();
}

void Biobj_simplex::loadProblem(const CoinPackedMatrix &matrix,
    const double *col_lb,
    const double *col_ub,
    const double *objective1,
    const double *objective2,
    const double *row_lb,
    const double *row_ub) {
  num_cols = matrix.getNumCols();
  num_rows = matrix.getNumRows();

  // load the problem as a single objective one
  model->loadProblem(matrix, col_lb, col_ub, objective1, row_lb, row_ub);
  // artificially add the second objective function as a dummy ubounded constraint
  CoinPackedVector obj2(num_cols, objective2);
  model->addRow(obj2, -1.0 * model->getInfinity(), model->getInfinity());

  // allocate memory for working arrays
  cost1 = new double[num_cols + num_rows];
  cost2 = new double[num_cols + num_rows];
  work_col = new double[num_cols];
  basics = new int[num_rows];

  // tell Osi and Clp to be quiet
  model->messageHandler()->setLogLevel(0);
}

void Biobj_simplex::updateCosts() {
  // the first array of reduced costs
  //TODO copy all array at once
  for (int i = 0; i < num_cols; i++) {
    cost1[i] = model->getReducedCost()[i];
  }
  for (int i = 0; i < num_rows; i++) {
    cost1[num_cols + i] = -model->getRowPrice()[i];
  }

  // get the second array of reduced costs from the dummy constraint
  model->getBInvARow(num_rows, cost2, (double*)(cost2 + num_cols));
}

void Biobj_simplex::solve() {
  // phases 1 and 2: check whether the problem is feasible and compute
  // the first efficient solution
  model->initialSolve();

  // tell model to allow us to do extra things
  model->enableSimplexInterface(true);

  // gather data to update reduced costs
  const double* upper = model->getRowUpper();
  const double* solution = model->getColSolution();
  const double* activity = model->getRowActivity();
  updateCosts();

  model->getBasics(basics);

  // manually compute b values of the simplex tableau
  vector<double> b;
  for ( int i = 0; i < num_rows; i++ ) {
    // the value depends on whether i is in the basis the index of a
    // regular variable ( < num_cols ) or a slack variable ( >= )
    if(basics[i] < num_cols)
      b.push_back(solution[basics[i]]);
    else
      b.push_back(upper[i] - activity[i]);
  }
  // gather in s the values in decision space of the current solution
  vector<double> s (solution, solution + num_cols);

  // create the corresponding solution with its objective values
  BVect sol(/*-1.0 **/ model->getObjValue(), /*-1.0 **/ activity[num_rows], s);
  solutions.push_back(sol);

  // compute candidate variables to enter the basis
  while (computeVarIn()){
    // while at least one such variables does exist,
    // compute the corresponding leaving variable
    computeVarOut();

    // perform pivot
    int outstatus = 1;
    model->pivot(var_in, basics[var_out], outstatus);

    // update data used to compute reduced costs
    upper = model->getRowUpper();
    solution = model->getColSolution();
    activity = model->getRowActivity();
    model->getBasics(basics);
    for ( int i = 0; i < num_rows; i++ ) {
      if(basics[i] < num_cols)
        b.push_back(solution[basics[i]]);
      else
        b.push_back(upper[i] - activity[i]);
    }
    // create the newly obtained solution
    vector<double> s (solution, solution + num_cols);

    BVect sol2(/*-1.0 **/ model->getObjValue(), /*-1.0 **/ activity[num_rows], s);
    solutions.push_back(sol2);
    updateCosts();
  }
}

vector<BVect> Biobj_simplex::getSols() {
  return solutions;
}

bool Biobj_simplex::computeVarIn() {
  lambda = 0;
  bool var_in_found = false;
  for( int i = 0; i < num_cols; i++ ) {
    if ( (cost1[i] > 0) && (cost2[i] < 0) ) {
      // the current variable is eligible to enter the basis
      double candidateLambda = (-cost2[i]/(cost1[i]-cost2[i]));
      var_in_found = true;
      if (candidateLambda > lambda) {
        // the entering variable to select has the greatest lambda value
        lambda = candidateLambda;
        var_in = i;
      }
    }
  }
  return var_in_found;
}

void Biobj_simplex::computeVarOut() {
  // update work_col to represent the column of var_in
  model->getBInvACol(var_in, work_col);

  double current_ratio;
  double min_ratio;
  bool one_out_found = false;

  // update data (a little redundant, isn't it?)
  const double* upper = model->getRowUpper();
  const double* solution = model->getColSolution();
  const double* activity = model->getRowActivity();
  vector<double> b;
  model->getBasics(basics);
  for ( int i = 0; i < num_rows; i++ ) {
    if(basics[i] < num_cols)
      b.push_back(solution[basics[i]]);
    else
      b.push_back(upper[i] - activity[i]);
  }

  for( int i = 0; i < num_rows; i++ ){
    if( work_col[i] > 0){
      // the current variable is eligible to leave the basis
      current_ratio = b[basics[i]]/work_col[i];
      if( !one_out_found ){
        one_out_found = true;
        var_out = i;
        min_ratio = current_ratio;
      } else if( current_ratio < min_ratio ) {
        // the leaving variable to select has the lowest ratio
        var_out = i;
        min_ratio = current_ratio;
      }
    }
  }
}
<commit_msg>Also search for pivot among slack vars<commit_after>#include "biobj_simplex.hpp"

using namespace std;

Biobj_simplex::Biobj_simplex() {
  model = new OsiClpSolverInterface;
}

Biobj_simplex::~Biobj_simplex() {
  delete model;
  delete[] cost1;
  delete[] cost2;
  delete[] work_col;
  delete[] basics;
}

double Biobj_simplex::getInfinity() {
  return model->getInfinity();
}

void Biobj_simplex::loadProblem(const CoinPackedMatrix &matrix,
    const double *col_lb,
    const double *col_ub,
    const double *objective1,
    const double *objective2,
    const double *row_lb,
    const double *row_ub) {
  num_cols = matrix.getNumCols();
  num_rows = matrix.getNumRows();

  // load the problem as a single objective one
  model->loadProblem(matrix, col_lb, col_ub, objective1, row_lb, row_ub);
  // artificially add the second objective function as a dummy ubounded constraint
  CoinPackedVector obj2(num_cols, objective2);
  model->addRow(obj2, -1.0 * model->getInfinity(), model->getInfinity());

  // allocate memory for working arrays
  cost1 = new double[num_cols + num_rows];
  cost2 = new double[num_cols + num_rows];
  work_col = new double[num_cols];
  basics = new int[num_rows];

  // tell Osi and Clp to be quiet
  model->messageHandler()->setLogLevel(0);
}

void Biobj_simplex::updateCosts() {
  // the first array of reduced costs
  //TODO copy all array at once
  for (int i = 0; i < num_cols; i++) {
    cost1[i] = model->getReducedCost()[i];
  }
  for (int i = 0; i < num_rows; i++) {
    cost1[num_cols + i] = -model->getRowPrice()[i];
  }

  // get the second array of reduced costs from the dummy constraint
  model->getBInvARow(num_rows, cost2, (double*)(cost2 + num_cols));
}

void Biobj_simplex::solve() {
  // phases 1 and 2: check whether the problem is feasible and compute
  // the first efficient solution
  model->initialSolve();

  // tell model to allow us to do extra things
  model->enableSimplexInterface(true);

  // gather data to update reduced costs
  const double* upper = model->getRowUpper();
  const double* solution = model->getColSolution();
  const double* activity = model->getRowActivity();
  updateCosts();

  model->getBasics(basics);

  // manually compute b values of the simplex tableau
  vector<double> b;
  for ( int i = 0; i < num_rows; i++ ) {
    // the value depends on whether i is in the basis the index of a
    // regular variable ( < num_cols ) or a slack variable ( >= )
    if(basics[i] < num_cols)
      b.push_back(solution[basics[i]]);
    else
      b.push_back(upper[i] - activity[i]);
  }
  // gather in s the values in decision space of the current solution
  vector<double> s (solution, solution + num_cols);

  // create the corresponding solution with its objective values
  BVect sol(/*-1.0 **/ model->getObjValue(), /*-1.0 **/ activity[num_rows], s);
  solutions.push_back(sol);

  // compute candidate variables to enter the basis
  while (computeVarIn()){
    // while at least one such variables does exist,
    // compute the corresponding leaving variable
    computeVarOut();

    // perform pivot
    int outstatus = 1;
    model->pivot(var_in, basics[var_out], outstatus);

    // update data used to compute reduced costs
    upper = model->getRowUpper();
    solution = model->getColSolution();
    activity = model->getRowActivity();
    model->getBasics(basics);
    for ( int i = 0; i < num_rows; i++ ) {
      if(basics[i] < num_cols)
        b.push_back(solution[basics[i]]);
      else
        b.push_back(upper[i] - activity[i]);
    }
    // create the newly obtained solution
    vector<double> s (solution, solution + num_cols);

    BVect sol2(/*-1.0 **/ model->getObjValue(), /*-1.0 **/ activity[num_rows], s);
    solutions.push_back(sol2);
    updateCosts();
  }
}

vector<BVect> Biobj_simplex::getSols() {
  return solutions;
}

bool Biobj_simplex::computeVarIn() {
  lambda = 0;
  bool var_in_found = false;
  for( int i = 0; i < num_cols + num_rows; i++ ) {
    if ( (cost1[i] >= 0) && (cost2[i] < 0) ) {
      // the current variable is eligible to enter the basis
      double candidateLambda = (-cost2[i]/(cost1[i]-cost2[i]));
      var_in_found = true;
      if (candidateLambda > lambda) {
        // the entering variable to select has the greatest lambda value
        lambda = candidateLambda;
        var_in = i;
      }
    }
  }
  return var_in_found;
}

void Biobj_simplex::computeVarOut() {
  // update work_col to represent the column of var_in
  model->getBInvACol(var_in, work_col);

  double current_ratio;
  double min_ratio;
  bool one_out_found = false;

  // update data (a little redundant, isn't it?)
  const double* upper = model->getRowUpper();
  const double* solution = model->getColSolution();
  const double* activity = model->getRowActivity();
  vector<double> b;
  model->getBasics(basics);
  for ( int i = 0; i < num_rows; i++ ) {
    if(basics[i] < num_cols)
      b.push_back(solution[basics[i]]);
    else
      b.push_back(upper[i] - activity[i]);
  }

  for( int i = 0; i < num_rows; i++ ){
    if( work_col[i] > 0){
      // the current variable is eligible to leave the basis
      current_ratio = b[basics[i]]/work_col[i];
      if( !one_out_found ){
        one_out_found = true;
        var_out = i;
        min_ratio = current_ratio;
      } else if( current_ratio < min_ratio ) {
        // the leaving variable to select has the lowest ratio
        var_out = i;
        min_ratio = current_ratio;
      }
    }
  }
}
<|endoftext|>