<commit_before>/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

/* $Id$ */

//-----------------------------------------------------------------
//           Implementation of the RunTag class
//   This is the class to deal with the tags in the run level
//   Origin: Panos Christakoglou, UOA-CERN, Panos.Christakoglou@cern.ch
//-----------------------------------------------------------------

#include "AliRunTag.h"
#include "AliDetectorTag.h"
#include "AliEventTag.h"

ClassImp(AliRunTag)

//___________________________________________________________________________
  AliRunTag::AliRunTag() :
    TObject(),
    fAliceRunId(-1),
    fAliceMagneticField(0.0),
    fAliceRunStartTime(0),
    fAliceRunStopTime(0),
    fAlirootVersion(0),
    fRootVersion(0),
    fGeant3Version(0),
    fAliceRunQuality(0),
    fAliceBeamEnergy(0.0),
    fAliceBeamType(0),
    fAliceCalibrationVersion(0),
    fAliceDataType(0),
    fNumEvents(0),
    fNumDetectors(0),
    fEventTag("AliEventTag", 1000),
    fDetectorTag(),
    fLHCTag(),
    fQA()
{
  //Default constructor
}

//___________________________________________________________________________
AliRunTag::~AliRunTag() {
  //Destructor
  fEventTag.Delete();
}

//___________________________________________________________________________
void AliRunTag::CopyStandardContent(AliRunTag *oldtag) {
  //function that copies the run, lhc and detector levels
  SetRunId(oldtag->GetRunId());
  SetMagneticField(oldtag->GetMagneticField());
  SetRunStartTime(oldtag->GetRunStartTime());
  SetRunStopTime(oldtag->GetRunStopTime());
  SetAlirootVersion(oldtag->GetAlirootVersion());
  SetRootVersion(oldtag->GetRootVersion());
  SetGeant3Version(oldtag->GetGeant3Version());
  SetRunQuality(oldtag->GetRunQuality());
  SetBeamEnergy(oldtag->GetBeamEnergy());
  SetBeamType(oldtag->GetBeamType());
  SetCalibVersion(oldtag->GetCalibVersion());
  SetDataType(oldtag->GetDataType());
  SetLHCTag(oldtag->GetLHCTag()->GetLuminosity(),oldtag->GetLHCTag()->GetLHCState());
  SetDetectorTag(oldtag->GetDetectorTags()->GetIntDetectorMask());
  SetQA(*(oldtag->GetQA())) ;
}

//___________________________________________________________________________
void AliRunTag::SetLHCTag(Float_t lumin, TString type) {
  //Setter for the LHC tags
  fLHCTag.SetLHCTag(lumin,type);
}

//___________________________________________________________________________
void AliRunTag::SetDetectorTag(UInt_t mask) {
  //Setter for the detector tags
  fDetectorTag.SetDetectorMask(mask);
}

//___________________________________________________________________________
void AliRunTag::AddEventTag(const AliEventTag & EvTag) {
  //Adds an entry to the event tag TClonesArray
  new(fEventTag[fNumEvents++]) AliEventTag(EvTag);
}

//___________________________________________________________________________
void AliRunTag::Clear(const char *) {
  //Resets the number of events and detectors
  fEventTag.Clear();
  fNumEvents = 0;
  fDetectorTag.Clear();
  fNumDetectors = 0;
}
<commit_msg>Use Delete instead of Clear to avoid memory leak.<commit_after>/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

/* $Id$ */

//-----------------------------------------------------------------
//           Implementation of the RunTag class
//   This is the class to deal with the tags in the run level
//   Origin: Panos Christakoglou, UOA-CERN, Panos.Christakoglou@cern.ch
//-----------------------------------------------------------------

#include "AliRunTag.h"
#include "AliDetectorTag.h"
#include "AliEventTag.h"

ClassImp(AliRunTag)

//___________________________________________________________________________
  AliRunTag::AliRunTag() :
    TObject(),
    fAliceRunId(-1),
    fAliceMagneticField(0.0),
    fAliceRunStartTime(0),
    fAliceRunStopTime(0),
    fAlirootVersion(0),
    fRootVersion(0),
    fGeant3Version(0),
    fAliceRunQuality(0),
    fAliceBeamEnergy(0.0),
    fAliceBeamType(0),
    fAliceCalibrationVersion(0),
    fAliceDataType(0),
    fNumEvents(0),
    fNumDetectors(0),
    fEventTag("AliEventTag", 1000),
    fDetectorTag(),
    fLHCTag(),
    fQA()
{
  //Default constructor
}

//___________________________________________________________________________
AliRunTag::~AliRunTag() {
  //Destructor
  fEventTag.Delete();
}

//___________________________________________________________________________
void AliRunTag::CopyStandardContent(AliRunTag *oldtag) {
  //function that copies the run, lhc and detector levels
  SetRunId(oldtag->GetRunId());
  SetMagneticField(oldtag->GetMagneticField());
  SetRunStartTime(oldtag->GetRunStartTime());
  SetRunStopTime(oldtag->GetRunStopTime());
  SetAlirootVersion(oldtag->GetAlirootVersion());
  SetRootVersion(oldtag->GetRootVersion());
  SetGeant3Version(oldtag->GetGeant3Version());
  SetRunQuality(oldtag->GetRunQuality());
  SetBeamEnergy(oldtag->GetBeamEnergy());
  SetBeamType(oldtag->GetBeamType());
  SetCalibVersion(oldtag->GetCalibVersion());
  SetDataType(oldtag->GetDataType());
  SetLHCTag(oldtag->GetLHCTag()->GetLuminosity(),oldtag->GetLHCTag()->GetLHCState());
  SetDetectorTag(oldtag->GetDetectorTags()->GetIntDetectorMask());
  SetQA(*(oldtag->GetQA())) ;
}

//___________________________________________________________________________
void AliRunTag::SetLHCTag(Float_t lumin, TString type) {
  //Setter for the LHC tags
  fLHCTag.SetLHCTag(lumin,type);
}

//___________________________________________________________________________
void AliRunTag::SetDetectorTag(UInt_t mask) {
  //Setter for the detector tags
  fDetectorTag.SetDetectorMask(mask);
}

//___________________________________________________________________________
void AliRunTag::AddEventTag(const AliEventTag & EvTag) {
  //Adds an entry to the event tag TClonesArray
  new(fEventTag[fNumEvents++]) AliEventTag(EvTag);
}

//___________________________________________________________________________
void AliRunTag::Clear(const char *) {
  //Resets the number of events and detectors
  fEventTag.Delete();
  fNumEvents = 0;
  fDetectorTag.Delete();
  fNumDetectors = 0;
}
<|endoftext|>


<commit_before><commit_msg>html uses ' not '<commit_after><|endoftext|>


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

#include "wallItem.h"

#include <QtWidgets/QAction>
#include <QtWidgets/QGraphicsSceneMouseEvent>

#include <math.h>
#include <qrkernel/settingsManager.h>

using namespace twoDModel::items;
using namespace qReal;
using namespace graphicsUtils;

const int wallWidth = 10;

WallItem::WallItem(const QPointF &begin, const QPointF &end)
	: LineItem(begin, end)
	, mDragged(false)
	, mImage(":/icons/2d_wall.png")
	, mOldX1(0)
	, mOldY1(0)
{
	setPrivateData();
	setAcceptDrops(true);
}

AbstractItem *WallItem::clone() const
{
	const auto cloned = new WallItem({x1(), y1()}, {x2(), y2()});
	AbstractItem::copyTo(cloned);
	connect(this, &AbstractItem::positionChanged, cloned, &WallItem::recalculateBorders);
	connect(this, &AbstractItem::x1Changed, cloned, &WallItem::recalculateBorders);
	connect(this, &AbstractItem::y1Changed, cloned, &WallItem::recalculateBorders);
	connect(this, &AbstractItem::x2Changed, cloned, &WallItem::recalculateBorders);
	connect(this, &AbstractItem::y2Changed, cloned, &WallItem::recalculateBorders);
	cloned->mOldX1 = mOldX1;
	cloned->mOldY1 = mOldY1;
	cloned->mDragged = mDragged;
	cloned->mOverlappedWithRobot = mOverlappedWithRobot;
	cloned->mPath = mPath;
	return cloned;
}

QAction *WallItem::wallTool()
{
	QAction * const result = new QAction(QIcon(":/icons/2d_wall.png"), tr("Wall (W)"), nullptr);
	result->setShortcut(QKeySequence(Qt::Key_W));
	return result;
}

void WallItem::setPrivateData()
{
	setZValue(1);
	QPen pen(this->pen());
	pen.setWidth(wallWidth);
	pen.setStyle(Qt::NoPen);
	setPen(pen);
	QBrush brush(this->brush());
	brush.setStyle(Qt::SolidPattern);
	brush.setTextureImage(mImage);
	setBrush(brush);
	mSerializeName = "wall";
}

QPointF WallItem::begin()
{
	return QPointF(x1(), y1()) + scenePos();
}

QPointF WallItem::end()
{
	return QPointF(x2(), y2()) + scenePos();
}

void WallItem::drawItem(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
	Q_UNUSED(option);
	Q_UNUSED(widget);
	painter->drawPath(shape());
	recalculateBorders();
}

void WallItem::drawExtractionForItem(QPainter *painter)
{
	if (!isSelected()) {
		return;
	}

	painter->setPen(QPen(Qt::green));
	mLineImpl.drawExtractionForItem(painter, x1(), y1(), x2(), y2(), drift);
	mLineImpl.drawFieldForResizeItem(painter, resizeDrift, x1(), y1(), x2(), y2());
}

void WallItem::mousePressEvent(QGraphicsSceneMouseEvent * event)
{
	AbstractItem::mousePressEvent(event);

	if (!editable()) {
		return;
	}

	mDragged = (flags() & ItemIsMovable) || mOverlappedWithRobot;
	mOldX1 = event->scenePos().x() - x1();
	mOldY1 = event->scenePos().y() - y1();
}

void WallItem::mouseMoveEvent(QGraphicsSceneMouseEvent * event)
{
	if (!editable()) {
		return;
	}

	// When selecting a robot item on the scene than display widget may appear.
	// After that scene would be shrinked and mouse move event would be generated (but actually
	// mouse cursor is not moved). Because of that selected robot item moves which should not be because you
	// only select robot item and not move it. It also happens when you unselect robot item by selecting another
	// item (not only robot item). In this case new selected item moves.
	if (event->lastScreenPos() == event->screenPos()) {
		return;
	}

	const QRectF oldPos = QRectF(QPointF(x1(), y1()), QPointF(x2(), y2()));

	if (mDragged && ((flags() & ItemIsMovable) || mOverlappedWithRobot)) {
		const QPointF pos = event->scenePos();
		const qreal deltaX = (x1() - x2());
		const qreal deltaY = (y1() - y2());
		setX1(pos.x() - mOldX1);
		setY1(pos.y() - mOldY1);

		if (SettingsManager::value("2dShowGrid").toBool()) {
			const int indexGrid = SettingsManager::value("2dGridCellSize").toInt();
			reshapeBeginWithGrid(indexGrid);
			mCellNumbX1 = x1() / indexGrid;
			mCellNumbY1 = y1() / indexGrid;
			mCellNumbX2 = x2() / indexGrid;
			mCellNumbY2 = y2() / indexGrid;
		}

		setDraggedEnd(deltaX, deltaY);
	}  else if (mDragged) {
		QGraphicsItem::mouseMoveEvent(event);
	}

	// Items under cursor cannot be dragged when adding new item,
	// but it mustn`t confuse the case when item is unmovable
	// because overapped with robot
	if (mDragged && ((flags() & ItemIsMovable) || mOverlappedWithRobot)) {
		emit wallDragged(this, realShape(), oldPos);
	}
	event->accept();
}

bool WallItem::isDragged() const
{
	return mDragged;
}

qreal WallItem::width() const
{
	return pen().width();
}

void WallItem::mouseReleaseEvent(QGraphicsSceneMouseEvent * event)
{
	QGraphicsItem::mouseReleaseEvent(event);
	mDragged = false;
}

void WallItem::deserialize(const QDomElement &element)
{
	LineItem::deserialize(element);
	recalculateBorders();
}

QDomElement WallItem::serialize(QDomDocument &document, const QPoint &topLeftPicture)
{
	QDomElement wallNode = document.createElement(mSerializeName);
	AbstractItem::serialize(wallNode);
	wallNode.setAttribute("begin", QString::number(x1() + scenePos().x() - topLeftPicture.x())
			+ ":" + QString::number(y1() + scenePos().y() - topLeftPicture.y()));
	wallNode.setAttribute("end", QString::number(x2() + scenePos().x() - topLeftPicture.x())
			+ ":" + QString::number(y2() + scenePos().y() - topLeftPicture.y()));
	return wallNode;
}

void WallItem::deserializePenBrush(const QDomElement &element)
{
	Q_UNUSED(element)
	setPrivateData();
}

void WallItem::onOverlappedWithRobot(bool overlapped)
{
	mOverlappedWithRobot = overlapped;
}

QPainterPath WallItem::path() const
{
	return mPath;
}

void WallItem::recalculateBorders()
{
	QPainterPath wallPath;
	wallPath.moveTo(begin());
	wallPath.lineTo(end());

	QPainterPathStroker stroker;
	stroker.setWidth(wallWidth * 3 / 2);
	mPath = stroker.createStroke(wallPath);
}
<commit_msg>Fixed robot comming through walls of zero-lenght<commit_after>/* Copyright 2007-2015 QReal Research Group
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License. */

#include "wallItem.h"

#include <QtWidgets/QAction>
#include <QtWidgets/QGraphicsSceneMouseEvent>

#include <qrkernel/settingsManager.h>
#include <qrutils/mathUtils/geometry.h>

using namespace twoDModel::items;
using namespace qReal;
using namespace graphicsUtils;

const int wallWidth = 10;

WallItem::WallItem(const QPointF &begin, const QPointF &end)
	: LineItem(begin, end)
	, mDragged(false)
	, mImage(":/icons/2d_wall.png")
	, mOldX1(0)
	, mOldY1(0)
{
	setPrivateData();
	setAcceptDrops(true);
}

AbstractItem *WallItem::clone() const
{
	const auto cloned = new WallItem({x1(), y1()}, {x2(), y2()});
	AbstractItem::copyTo(cloned);
	connect(this, &AbstractItem::positionChanged, cloned, &WallItem::recalculateBorders);
	connect(this, &AbstractItem::x1Changed, cloned, &WallItem::recalculateBorders);
	connect(this, &AbstractItem::y1Changed, cloned, &WallItem::recalculateBorders);
	connect(this, &AbstractItem::x2Changed, cloned, &WallItem::recalculateBorders);
	connect(this, &AbstractItem::y2Changed, cloned, &WallItem::recalculateBorders);
	cloned->mOldX1 = mOldX1;
	cloned->mOldY1 = mOldY1;
	cloned->mDragged = mDragged;
	cloned->mOverlappedWithRobot = mOverlappedWithRobot;
	cloned->mPath = mPath;
	return cloned;
}

QAction *WallItem::wallTool()
{
	QAction * const result = new QAction(QIcon(":/icons/2d_wall.png"), tr("Wall (W)"), nullptr);
	result->setShortcut(QKeySequence(Qt::Key_W));
	return result;
}

void WallItem::setPrivateData()
{
	setZValue(1);
	QPen pen(this->pen());
	pen.setWidth(wallWidth);
	pen.setStyle(Qt::NoPen);
	setPen(pen);
	QBrush brush(this->brush());
	brush.setStyle(Qt::SolidPattern);
	brush.setTextureImage(mImage);
	setBrush(brush);
	mSerializeName = "wall";
}

QPointF WallItem::begin()
{
	return QPointF(x1(), y1()) + scenePos();
}

QPointF WallItem::end()
{
	return QPointF(x2(), y2()) + scenePos();
}

void WallItem::drawItem(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
	Q_UNUSED(option);
	Q_UNUSED(widget);
	painter->drawPath(shape());
	recalculateBorders();
}

void WallItem::drawExtractionForItem(QPainter *painter)
{
	if (!isSelected()) {
		return;
	}

	painter->setPen(QPen(Qt::green));
	mLineImpl.drawExtractionForItem(painter, x1(), y1(), x2(), y2(), drift);
	mLineImpl.drawFieldForResizeItem(painter, resizeDrift, x1(), y1(), x2(), y2());
}

void WallItem::mousePressEvent(QGraphicsSceneMouseEvent * event)
{
	AbstractItem::mousePressEvent(event);

	if (!editable()) {
		return;
	}

	mDragged = (flags() & ItemIsMovable) || mOverlappedWithRobot;
	mOldX1 = event->scenePos().x() - x1();
	mOldY1 = event->scenePos().y() - y1();
}

void WallItem::mouseMoveEvent(QGraphicsSceneMouseEvent * event)
{
	if (!editable()) {
		return;
	}

	// When selecting a robot item on the scene than display widget may appear.
	// After that scene would be shrinked and mouse move event would be generated (but actually
	// mouse cursor is not moved). Because of that selected robot item moves which should not be because you
	// only select robot item and not move it. It also happens when you unselect robot item by selecting another
	// item (not only robot item). In this case new selected item moves.
	if (event->lastScreenPos() == event->screenPos()) {
		return;
	}

	const QRectF oldPos = QRectF(QPointF(x1(), y1()), QPointF(x2(), y2()));

	if (mDragged && ((flags() & ItemIsMovable) || mOverlappedWithRobot)) {
		const QPointF pos = event->scenePos();
		const qreal deltaX = (x1() - x2());
		const qreal deltaY = (y1() - y2());
		setX1(pos.x() - mOldX1);
		setY1(pos.y() - mOldY1);

		if (SettingsManager::value("2dShowGrid").toBool()) {
			const int indexGrid = SettingsManager::value("2dGridCellSize").toInt();
			reshapeBeginWithGrid(indexGrid);
			mCellNumbX1 = x1() / indexGrid;
			mCellNumbY1 = y1() / indexGrid;
			mCellNumbX2 = x2() / indexGrid;
			mCellNumbY2 = y2() / indexGrid;
		}

		setDraggedEnd(deltaX, deltaY);
	}  else if (mDragged) {
		QGraphicsItem::mouseMoveEvent(event);
	}

	// Items under cursor cannot be dragged when adding new item,
	// but it mustn`t confuse the case when item is unmovable
	// because overapped with robot
	if (mDragged && ((flags() & ItemIsMovable) || mOverlappedWithRobot)) {
		emit wallDragged(this, realShape(), oldPos);
	}
	event->accept();
}

bool WallItem::isDragged() const
{
	return mDragged;
}

qreal WallItem::width() const
{
	return pen().width();
}

void WallItem::mouseReleaseEvent(QGraphicsSceneMouseEvent * event)
{
	QGraphicsItem::mouseReleaseEvent(event);
	mDragged = false;
}

void WallItem::deserialize(const QDomElement &element)
{
	LineItem::deserialize(element);
	recalculateBorders();
}

QDomElement WallItem::serialize(QDomDocument &document, const QPoint &topLeftPicture)
{
	QDomElement wallNode = document.createElement(mSerializeName);
	AbstractItem::serialize(wallNode);
	wallNode.setAttribute("begin", QString::number(x1() + scenePos().x() - topLeftPicture.x())
			+ ":" + QString::number(y1() + scenePos().y() - topLeftPicture.y()));
	wallNode.setAttribute("end", QString::number(x2() + scenePos().x() - topLeftPicture.x())
			+ ":" + QString::number(y2() + scenePos().y() - topLeftPicture.y()));
	return wallNode;
}

void WallItem::deserializePenBrush(const QDomElement &element)
{
	Q_UNUSED(element)
	setPrivateData();
}

void WallItem::onOverlappedWithRobot(bool overlapped)
{
	mOverlappedWithRobot = overlapped;
}

QPainterPath WallItem::path() const
{
	return mPath;
}

void WallItem::recalculateBorders()
{
	QPainterPath wallPath;
	wallPath.moveTo(begin());

	if (mathUtils::Geometry::eq(begin(), end())) {
		wallPath.lineTo(end().x() + 0.1, end().y());
	} else {
		wallPath.lineTo(end());
	}

	QPainterPathStroker stroker;
	stroker.setWidth(wallWidth * 3 / 2);
	mPath = stroker.createStroke(wallPath);
}
<|endoftext|>


<commit_before><commit_msg>HIR Expand Closures - Don't emit `Self` in parameters<commit_after><|endoftext|>


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

// Code in this file is taked from
// third_party/skia/src/opts/opts_check_SSE2.cpp.

// Note that this file cannot be compiled with -msse2 in gcc.

#include "build/build_config.h"
#include "media/base/cpu_features.h"

namespace media {

#ifdef _MSC_VER
static inline void getcpuid(int info_type, int info[4]) {
  __asm {
    mov    eax, [info_type]
        cpuid
        mov    edi, [info]
        mov    [edi], eax
        mov    [edi+4], ebx
        mov    [edi+8], ecx
        mov    [edi+12], edx
        }
}
#else
static inline void getcpuid(int info_type, int info[4]) {
  // We save and restore ebx, so this code can be compatible with -fPIC
#if defined(__i386__)
  asm volatile (
        "pushl %%ebx      \n\t"
        "cpuid            \n\t"
        "movl %%ebx, %1   \n\t"
        "popl %%ebx       \n\t"
        : "=a"(info[0]), "=r"(info[1]), "=c"(info[2]), "=d"(info[3])
        : "a"(info_type)
                );
#else
  // We can use cpuid instruction without pushing ebx on gcc x86-64 because it
  // does not use ebx (or rbx) as a GOT register.
  asm volatile (
      "cpuid            \n\t"
      : "=a"(info[0]), "=r"(info[1]), "=c"(info[2]), "=d"(info[3])
      : "a"(info_type)
      : "%rbx"
  );
#endif
}
#endif

bool hasMMX() {
  // TODO(hclam): Acutually checks it.
  return true;
}

bool hasSSE() {
  // TODO(hclam): Actually checks it.
  return true;
}

bool hasSSE2() {
#if defined(ARCH_CPU_X86_64)
  /* All x86_64 machines have SSE2, so don't even bother checking. */
  return true;
#else
  int cpu_info[4] = { 0 };
  getcpuid(1, cpu_info);
  return (cpu_info[3] & (1<<26)) != 0;
#endif
}

bool hasSSSE3() {
  int cpu_info[4] = { 0 };
  getcpuid(1, cpu_info);
  return (cpu_info[3] & 0x04000000) != 0 && (cpu_info[2] & 0x00000001) != 0 &&
      (cpu_info[2] & 0x00000200) != 0;
}

}  // namespace media
<commit_msg>Proper detection of MMX and SSE support<commit_after>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Code in this file is taked from
// third_party/skia/src/opts/opts_check_SSE2.cpp.

// Note that this file cannot be compiled with -msse2 in gcc.

#include "build/build_config.h"
#include "media/base/cpu_features.h"

namespace media {

#ifdef _MSC_VER
static inline void getcpuid(int info_type, int info[4]) {
  __asm {
    mov    eax, [info_type]
        cpuid
        mov    edi, [info]
        mov    [edi], eax
        mov    [edi+4], ebx
        mov    [edi+8], ecx
        mov    [edi+12], edx
        }
}
#else
static inline void getcpuid(int info_type, int info[4]) {
  // We save and restore ebx, so this code can be compatible with -fPIC
#if defined(__i386__)
  asm volatile (
        "pushl %%ebx      \n\t"
        "cpuid            \n\t"
        "movl %%ebx, %1   \n\t"
        "popl %%ebx       \n\t"
        : "=a"(info[0]), "=r"(info[1]), "=c"(info[2]), "=d"(info[3])
        : "a"(info_type)
                );
#else
  // We can use cpuid instruction without pushing ebx on gcc x86-64 because it
  // does not use ebx (or rbx) as a GOT register.
  asm volatile (
      "cpuid            \n\t"
      : "=a"(info[0]), "=r"(info[1]), "=c"(info[2]), "=d"(info[3])
      : "a"(info_type)
      : "%rbx"
  );
#endif
}
#endif

bool hasMMX() {
#if defined(ARCH_CPU_X86_64)
  // Every X86_64 processor has MMX.
  return true;
#else
  int cpu_info[4] = { 0 };
  getcpuid(1, cpu_info);
  return (cpu_info[3] & (1<<23)) != 0;
#endif
}

bool hasSSE() {
#if defined(ARCH_CPU_X86_64)
  // Every X86_64 processor has SSE.
  return true;
#else
  int cpu_info[4] = { 0 };
  getcpuid(1, cpu_info);
  return (cpu_info[3] & (1<<25)) != 0;
#endif
}

bool hasSSE2() {
#if defined(ARCH_CPU_X86_64)
  // All X86_64 machines have SSE2, so don't even bother checking.
  return true;
#else
  int cpu_info[4] = { 0 };
  getcpuid(1, cpu_info);
  return (cpu_info[3] & (1<<26)) != 0;
#endif
}

bool hasSSSE3() {
  int cpu_info[4] = { 0 };
  getcpuid(1, cpu_info);
  return (cpu_info[3] & 0x04000000) != 0 && (cpu_info[2] & 0x00000001) != 0 &&
      (cpu_info[2] & 0x00000200) != 0;
}

}  // namespace media
<|endoftext|>


<commit_before>// This program demonstrates the use ports by setting up a simple
// pipeline. All processes create an identical pipeline:
// vtkImageReader -> vtkContourFilter -> vtkElevationFilter
// In addition, the first (root) process creates n input ports
// (where n=nProcs-1), each attached to an output port on the other
// processes. It then appends the polygonal output from all input
// ports and it's own pipeline and renders the result ISO_NUM times,
// each time setting a different scalar value to be contoured.

#include "vtkImageReader.h"
#include "vtkContourFilter.h"
#include "vtkAppendPolyData.h"
#include "vtkOutputPort.h"
#include "vtkInputPort.h"
#include "vtkRenderer.h"
#include "vtkRenderWindow.h"
#include "vtkConeSource.h"
#include "vtkPolyDataMapper.h"
#include "vtkActor.h"
#include "vtkElevationFilter.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkTimerLog.h"
#include "vtkMath.h"
#include "vtkWindowToImageFilter.h"
#include "vtkTIFFWriter.h"
#include "vtkMultiProcessController.h"
#include "vtkRegressionTestImage.h"

static const float ISO_START=4250.0;
static const float ISO_STEP=-1250.0;
static const int ISO_NUM=3;
// Just pick a tag which is available
static const int ISO_VALUE_RMI_TAG=300;
static const int PORT_TAG=999;

struct ParallelIsoArgs_tmp
{
  int* retVal;
  int argc;
  char** argv;
};

// call back to set the iso surface value.
void SetIsoValueRMI(void *localArg, void *remoteArg,
		  int remoteArgLen, int id)
{
  float val;

  vtkContourFilter *iso;
  iso = (vtkContourFilter *)localArg;
  val = iso->GetValue(0);
  iso->SetValue(0, val + ISO_STEP);
}

// This will be called by all processes
void MyMain( vtkMultiProcessController *controller, void *arg )
{
  vtkImageReader *reader;
  vtkContourFilter *iso;
  vtkElevationFilter *elev;
  int myid, numProcs;
  float val;
  int numTris;
  ParallelIsoArgs_tmp* args = reinterpret_cast<ParallelIsoArgs_tmp*>(arg);

  // Obtain the id of the running process and the total
  // number of processes
  myid = controller->GetLocalProcessId();
  numProcs = controller->GetNumberOfProcesses();

  // Create the reader, the data file name might have
  // to be changed depending on where the data files are.
  reader = vtkImageReader::New();
  reader->SetDataByteOrderToLittleEndian();
  reader->SetDataExtent(0, 63, 0, 63, 1, 93);
  reader->SetFilePrefix("../../../../vtkdata/headsq/quarter");
  reader->SetDataSpacing(3.2, 3.2, 1.5);

  // Iso-surface.
  iso = vtkContourFilter::New();
  iso->SetInput(reader->GetOutput());
  iso->SetValue(0, ISO_START);
  iso->ComputeScalarsOff();
  iso->ComputeGradientsOff();

  // Compute a different color for each process.
  elev = vtkElevationFilter::New();
  elev->SetInput(iso->GetOutput());
  vtkMath::RandomSeed(myid * 100);
  val = vtkMath::Random();
  elev->SetScalarRange(val, val+0.001);

  if (myid != 0)
    {
    // If I am not the root process

    // Satellite process! Send data through port.
    vtkOutputPort *upPort = vtkOutputPort::New();

    // Last, set up a RMI call back to change the iso surface value.
    // This is done so that the root process can let this process
    // know that it wants the contour value to change.
    controller->AddRMI(SetIsoValueRMI, (void *)iso, ISO_VALUE_RMI_TAG);

    // connect the port to the output of the pipeline
    upPort->SetInput(elev->GetPolyDataOutput());

    // Multiple ports can go through the same connection.
    // This is used to differentiate ports
    upPort->SetTag(PORT_TAG);

    // Loop which processes RMI requests.
    // Use vtkMultiProcessController::BREAK_RMI_TAG to break it.
    // The root process with send a ISO_VALUE_RMI_TAG to make this
    // process change it's contour value.
    upPort->WaitForUpdate();

    // We are done. Clean up.
    upPort->Delete();
    }
  else
    {
    // If I am the root process

    int i, j;
    vtkAppendPolyData *app = vtkAppendPolyData::New();
    vtkInputPort *downPort;
    vtkRenderer *ren = vtkRenderer::New();
    vtkRenderWindow *renWindow = vtkRenderWindow::New();
    vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New();
    vtkPolyDataMapper *mapper = vtkPolyDataMapper::New();
    vtkActor *actor = vtkActor::New();
    vtkTimerLog *timer = vtkTimerLog::New();
    vtkCamera *cam = vtkCamera::New();

    // Add my pipeline's output to the append filter
    app->AddInput(elev->GetPolyDataOutput());

    // ###################### important ####################
    // # This tells the append filter to request pieces from
    // # each of its inputs.  Since each of its inputs comes from
    // # a different process,  each process generates a separate
    // # piece of the data (data parallelism).
    // # If this is not used, all processes will iso-surface
    // # all the data.
    app->ParallelStreamingOn();

    // This is the main thread: Collect the data and render it.
    for (i = 1; i < numProcs; ++i)
      {
      downPort = vtkInputPort::New();
      downPort->SetRemoteProcessId(i);

      // Multiple ports can go through the same connection.
      // This is used to differentiate ports
      downPort->SetTag(PORT_TAG);

      app->AddInput(downPort->GetPolyDataOutput());

      // Reference already incremented by AddInput(). Delete()
      // will only decrement the count, not destroy the object.
      // The ports will be destroyed when the append filter
      // goes away.
      downPort->Delete();
      downPort = NULL;
      }

    // Create the rendering part of the pipeline
    renWindow->AddRenderer(ren);
    iren->SetRenderWindow(renWindow);
    ren->SetBackground(0.9, 0.9, 0.9);
    renWindow->SetSize( 400, 400);

    mapper->SetInput(app->GetOutput());
    actor->SetMapper(mapper);

    ren->AddActor(actor);

    cam->SetFocalPoint(100, 100, 65);
    cam->SetPosition(100, 450, 65);
    cam->SetViewUp(0, 0, -1);
    cam->SetViewAngle(30);

    cam->SetClippingRange(177.0, 536.0);
    ren->SetActiveCamera(cam);

    // loop through some iso surface values.
    for (j = 0; j < ISO_NUM; ++j)
      {
      // set the local value
      SetIsoValueRMI((void*)iso, NULL, 0, 0);
      for (i = 1; i < numProcs; ++i)
	{
	// trigger the RMI to change the iso surface value.
	controller->TriggerRMI(i, ISO_VALUE_RMI_TAG);
	}

      // Time the rendering. Note that the execution on all processes
      // start only after Update()
      timer->StartTimer();
      app->Update();
      timer->StopTimer();
      numTris = iso->GetOutput()->GetNumberOfCells();
      val = iso->GetValue(0);
      cerr << "Update " << val << " took " << timer->GetElapsedTime()
	   << " seconds to produce " << numTris << " triangles\n";

      // now render the results
      renWindow->Render();
      }

    *(args->retVal) =
      vtkRegressionTestImage2(args->argc, args->argv, renWindow);

    // Tell the other processors to stop processing RMIs.
    for (i = 1; i < numProcs; ++i)
      {
      controller->TriggerRMI(i, vtkMultiProcessController::BREAK_RMI_TAG);
      }

    // Clean up
    app->Delete();
    ren->Delete();
    renWindow->Delete();
    iren->Delete();
    mapper->Delete();
    actor->Delete();
    cam->Delete();
    timer->Delete();
    }

  // clean up objects in all processes.
  reader->Delete();
  iso->Delete();
  elev->Delete();
}

int main( int argc, char* argv[] )
{
  vtkMultiProcessController *controller;

  // Note that this will create a vtkMPIController if MPI
  // is configured, vtkThreadedController otherwise.
  controller = vtkMultiProcessController::New();

  controller->Initialize(&argc, &argv);

  // Added for regression test.
  // ----------------------------------------------
  int retVal;
  ParallelIsoArgs_tmp args;
  args.retVal = &retVal;
  args.argc = argc;
  args.argv = argv;
  // ----------------------------------------------

  controller->SetSingleMethod(MyMain, &args);

  // When using MPI, the number of processes is determined
  // by the external program which launches this application.
  // However, when using threads, we need to set it ourselves.
  if (controller->IsA("vtkThreadedController"))
    {
    // Set the number of processes to 2 for this example.
    controller->SetNumberOfProcesses(2);
    }
  controller->SingleMethodExecute();

  int myid = controller->GetLocalProcessId();

  controller->Finalize();
  controller->Delete();

  return !retVal;
}

<commit_msg>Uses new function to get the data files root.<commit_after>// This program demonstrates the use ports by setting up a simple
// pipeline. All processes create an identical pipeline:
// vtkImageReader -> vtkContourFilter -> vtkElevationFilter
// In addition, the first (root) process creates n input ports
// (where n=nProcs-1), each attached to an output port on the other
// processes. It then appends the polygonal output from all input
// ports and it's own pipeline and renders the result ISO_NUM times,
// each time setting a different scalar value to be contoured.

#include "vtkImageReader.h"
#include "vtkContourFilter.h"
#include "vtkAppendPolyData.h"
#include "vtkOutputPort.h"
#include "vtkInputPort.h"
#include "vtkRenderer.h"
#include "vtkRenderWindow.h"
#include "vtkConeSource.h"
#include "vtkPolyDataMapper.h"
#include "vtkActor.h"
#include "vtkElevationFilter.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkTimerLog.h"
#include "vtkMath.h"
#include "vtkWindowToImageFilter.h"
#include "vtkTIFFWriter.h"
#include "vtkMultiProcessController.h"
#include "vtkRegressionTestImage.h"

static const float ISO_START=4250.0;
static const float ISO_STEP=-1250.0;
static const int ISO_NUM=3;
// Just pick a tag which is available
static const int ISO_VALUE_RMI_TAG=300;
static const int PORT_TAG=999;

struct ParallelIsoArgs_tmp
{
  int* retVal;
  int argc;
  char** argv;
};

// call back to set the iso surface value.
void SetIsoValueRMI(void *localArg, void *remoteArg,
		  int remoteArgLen, int id)
{
  float val;

  vtkContourFilter *iso;
  iso = (vtkContourFilter *)localArg;
  val = iso->GetValue(0);
  iso->SetValue(0, val + ISO_STEP);
}

// This will be called by all processes
void MyMain( vtkMultiProcessController *controller, void *arg )
{
  vtkImageReader *reader;
  vtkContourFilter *iso;
  vtkElevationFilter *elev;
  int myid, numProcs;
  float val;
  int numTris;
  ParallelIsoArgs_tmp* args = reinterpret_cast<ParallelIsoArgs_tmp*>(arg);

  // Obtain the id of the running process and the total
  // number of processes
  myid = controller->GetLocalProcessId();
  numProcs = controller->GetNumberOfProcesses();

  // Create the reader, the data file name might have
  // to be changed depending on where the data files are.
  char* fname = vtkExpandDataFileName(args->argc, args->argv,
				      "Data/headsq/quarter");
  reader = vtkImageReader::New();
  reader->SetDataByteOrderToLittleEndian();
  reader->SetDataExtent(0, 63, 0, 63, 1, 93);
  reader->SetFilePrefix(fname);
  reader->SetDataSpacing(3.2, 3.2, 1.5);
  delete[] fname;

  // Iso-surface.
  iso = vtkContourFilter::New();
  iso->SetInput(reader->GetOutput());
  iso->SetValue(0, ISO_START);
  iso->ComputeScalarsOff();
  iso->ComputeGradientsOff();

  // Compute a different color for each process.
  elev = vtkElevationFilter::New();
  elev->SetInput(iso->GetOutput());
  vtkMath::RandomSeed(myid * 100);
  val = vtkMath::Random();
  elev->SetScalarRange(val, val+0.001);

  if (myid != 0)
    {
    // If I am not the root process

    // Satellite process! Send data through port.
    vtkOutputPort *upPort = vtkOutputPort::New();

    // Last, set up a RMI call back to change the iso surface value.
    // This is done so that the root process can let this process
    // know that it wants the contour value to change.
    controller->AddRMI(SetIsoValueRMI, (void *)iso, ISO_VALUE_RMI_TAG);

    // connect the port to the output of the pipeline
    upPort->SetInput(elev->GetPolyDataOutput());

    // Multiple ports can go through the same connection.
    // This is used to differentiate ports
    upPort->SetTag(PORT_TAG);

    // Loop which processes RMI requests.
    // Use vtkMultiProcessController::BREAK_RMI_TAG to break it.
    // The root process with send a ISO_VALUE_RMI_TAG to make this
    // process change it's contour value.
    upPort->WaitForUpdate();

    // We are done. Clean up.
    upPort->Delete();
    }
  else
    {
    // If I am the root process

    int i, j;
    vtkAppendPolyData *app = vtkAppendPolyData::New();
    vtkInputPort *downPort;
    vtkRenderer *ren = vtkRenderer::New();
    vtkRenderWindow *renWindow = vtkRenderWindow::New();
    vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New();
    vtkPolyDataMapper *mapper = vtkPolyDataMapper::New();
    vtkActor *actor = vtkActor::New();
    vtkTimerLog *timer = vtkTimerLog::New();
    vtkCamera *cam = vtkCamera::New();

    // Add my pipeline's output to the append filter
    app->AddInput(elev->GetPolyDataOutput());

    // ###################### important ####################
    // # This tells the append filter to request pieces from
    // # each of its inputs.  Since each of its inputs comes from
    // # a different process,  each process generates a separate
    // # piece of the data (data parallelism).
    // # If this is not used, all processes will iso-surface
    // # all the data.
    app->ParallelStreamingOn();

    // This is the main thread: Collect the data and render it.
    for (i = 1; i < numProcs; ++i)
      {
      downPort = vtkInputPort::New();
      downPort->SetRemoteProcessId(i);

      // Multiple ports can go through the same connection.
      // This is used to differentiate ports
      downPort->SetTag(PORT_TAG);

      app->AddInput(downPort->GetPolyDataOutput());

      // Reference already incremented by AddInput(). Delete()
      // will only decrement the count, not destroy the object.
      // The ports will be destroyed when the append filter
      // goes away.
      downPort->Delete();
      downPort = NULL;
      }

    // Create the rendering part of the pipeline
    renWindow->AddRenderer(ren);
    iren->SetRenderWindow(renWindow);
    ren->SetBackground(0.9, 0.9, 0.9);
    renWindow->SetSize( 400, 400);

    mapper->SetInput(app->GetOutput());
    actor->SetMapper(mapper);

    ren->AddActor(actor);

    cam->SetFocalPoint(100, 100, 65);
    cam->SetPosition(100, 450, 65);
    cam->SetViewUp(0, 0, -1);
    cam->SetViewAngle(30);

    cam->SetClippingRange(177.0, 536.0);
    ren->SetActiveCamera(cam);

    // loop through some iso surface values.
    for (j = 0; j < ISO_NUM; ++j)
      {
      // set the local value
      SetIsoValueRMI((void*)iso, NULL, 0, 0);
      for (i = 1; i < numProcs; ++i)
	{
	// trigger the RMI to change the iso surface value.
	controller->TriggerRMI(i, ISO_VALUE_RMI_TAG);
	}

      // Time the rendering. Note that the execution on all processes
      // start only after Update()
      timer->StartTimer();
      app->Update();
      timer->StopTimer();
      numTris = iso->GetOutput()->GetNumberOfCells();
      val = iso->GetValue(0);
      cerr << "Update " << val << " took " << timer->GetElapsedTime()
	   << " seconds to produce " << numTris << " triangles\n";

      // now render the results
      renWindow->Render();
      }

    *(args->retVal) =
      vtkRegressionTestImage2(args->argc, args->argv, renWindow);

    // Tell the other processors to stop processing RMIs.
    for (i = 1; i < numProcs; ++i)
      {
      controller->TriggerRMI(i, vtkMultiProcessController::BREAK_RMI_TAG);
      }

    // Clean up
    app->Delete();
    ren->Delete();
    renWindow->Delete();
    iren->Delete();
    mapper->Delete();
    actor->Delete();
    cam->Delete();
    timer->Delete();
    }

  // clean up objects in all processes.
  reader->Delete();
  iso->Delete();
  elev->Delete();
}

int main( int argc, char* argv[] )
{
  vtkMultiProcessController *controller;

  // Note that this will create a vtkMPIController if MPI
  // is configured, vtkThreadedController otherwise.
  controller = vtkMultiProcessController::New();

  controller->Initialize(&argc, &argv);

  // Added for regression test.
  // ----------------------------------------------
  int retVal;
  ParallelIsoArgs_tmp args;
  args.retVal = &retVal;
  args.argc = argc;
  args.argv = argv;
  // ----------------------------------------------

  controller->SetSingleMethod(MyMain, &args);

  // When using MPI, the number of processes is determined
  // by the external program which launches this application.
  // However, when using threads, we need to set it ourselves.
  if (controller->IsA("vtkThreadedController"))
    {
    // Set the number of processes to 2 for this example.
    controller->SetNumberOfProcesses(2);
    }
  controller->SingleMethodExecute();

  controller->Finalize();
  controller->Delete();

  return !retVal;
}

<|endoftext|>


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

#include "base/at_exit.h"
#include "base/bind.h"
#include "base/message_loop/message_loop.h"
#include "base/strings/string_number_conversions.h"
#include "base/time/time.h"
#include "media/base/media.h"
#include "media/base/media_log.h"
#include "media/base/test_data_util.h"
#include "media/filters/ffmpeg_demuxer.h"
#include "media/filters/file_data_source.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/perf/perf_test.h"

namespace media {

static const int kBenchmarkIterations = 500;

class DemuxerHostImpl : public media::DemuxerHost {
 public:
  DemuxerHostImpl() {}
  virtual ~DemuxerHostImpl() {}

  // DemuxerHost implementation.
  virtual void AddBufferedTimeRange(base::TimeDelta start,
                                    base::TimeDelta end) OVERRIDE {}
  virtual void SetDuration(base::TimeDelta duration) OVERRIDE {}
  virtual void OnDemuxerError(media::PipelineStatus error) OVERRIDE {}
  virtual void AddTextStream(media::DemuxerStream* text_stream,
                             const media::TextTrackConfig& config) OVERRIDE {}
  virtual void RemoveTextStream(media::DemuxerStream* text_stream) OVERRIDE {}

 private:
  DISALLOW_COPY_AND_ASSIGN(DemuxerHostImpl);
};

static void QuitLoopWithStatus(base::MessageLoop* message_loop,
                        media::PipelineStatus status) {
  CHECK_EQ(status, media::PIPELINE_OK);
  message_loop->PostTask(FROM_HERE, base::MessageLoop::QuitWhenIdleClosure());
}

static void NeedKey(const std::string& type,
                    const std::vector<uint8>& init_data) {
  VLOG(0) << "File is encrypted.";
}

typedef std::vector<media::DemuxerStream* > Streams;

// Simulates playback reading requirements by reading from each stream
// present in |demuxer| in as-close-to-monotonically-increasing timestamp order.
class StreamReader {
 public:
  StreamReader(media::Demuxer* demuxer, bool enable_bitstream_converter);
  ~StreamReader();

  // Performs a single step read.
  void Read();

  // Returns true when all streams have reached end of stream.
  bool IsDone();

  int number_of_streams() { return static_cast<int>(streams_.size()); }
  const Streams& streams() { return streams_; }
  const std::vector<int>& counts() { return counts_; }

 private:
  void OnReadDone(base::MessageLoop* message_loop,
                  bool* end_of_stream,
                  base::TimeDelta* timestamp,
                  media::DemuxerStream::Status status,
                  const scoped_refptr<media::DecoderBuffer>& buffer);
  int GetNextStreamIndexToRead();

  Streams streams_;
  std::vector<bool> end_of_stream_;
  std::vector<base::TimeDelta> last_read_timestamp_;
  std::vector<int> counts_;

  DISALLOW_COPY_AND_ASSIGN(StreamReader);
};

StreamReader::StreamReader(media::Demuxer* demuxer,
                           bool enable_bitstream_converter) {
  media::DemuxerStream* stream =
      demuxer->GetStream(media::DemuxerStream::AUDIO);
  if (stream) {
    streams_.push_back(stream);
    end_of_stream_.push_back(false);
    last_read_timestamp_.push_back(media::kNoTimestamp());
    counts_.push_back(0);
  }

  stream = demuxer->GetStream(media::DemuxerStream::VIDEO);
  if (stream) {
    streams_.push_back(stream);
    end_of_stream_.push_back(false);
    last_read_timestamp_.push_back(media::kNoTimestamp());
    counts_.push_back(0);

    if (enable_bitstream_converter)
      stream->EnableBitstreamConverter();
  }
}

StreamReader::~StreamReader() {}

void StreamReader::Read() {
  int index = GetNextStreamIndexToRead();
  bool end_of_stream = false;
  base::TimeDelta timestamp;

  streams_[index]->Read(base::Bind(
      &StreamReader::OnReadDone, base::Unretained(this),
      base::MessageLoop::current(), &end_of_stream, &timestamp));
  base::MessageLoop::current()->Run();

  CHECK(end_of_stream || timestamp != media::kNoTimestamp());
  end_of_stream_[index] = end_of_stream;
  last_read_timestamp_[index] = timestamp;
  counts_[index]++;
}

bool StreamReader::IsDone() {
  for (size_t i = 0; i < end_of_stream_.size(); ++i) {
    if (!end_of_stream_[i])
      return false;
  }
  return true;
}

void StreamReader::OnReadDone(
    base::MessageLoop* message_loop,
    bool* end_of_stream,
    base::TimeDelta* timestamp,
    media::DemuxerStream::Status status,
    const scoped_refptr<media::DecoderBuffer>& buffer) {
  CHECK_EQ(status, media::DemuxerStream::kOk);
  CHECK(buffer.get());
  *end_of_stream = buffer->end_of_stream();
  *timestamp = *end_of_stream ? media::kNoTimestamp() : buffer->timestamp();
  message_loop->PostTask(FROM_HERE, base::MessageLoop::QuitWhenIdleClosure());
}

int StreamReader::GetNextStreamIndexToRead() {
  int index = -1;
  for (int i = 0; i < number_of_streams(); ++i) {
    // Ignore streams at EOS.
    if (end_of_stream_[i])
      continue;

    // Use a stream if it hasn't been read from yet.
    if (last_read_timestamp_[i] == media::kNoTimestamp())
      return i;

    if (index < 0 ||
        last_read_timestamp_[i] < last_read_timestamp_[index]) {
      index = i;
    }
  }
  CHECK_GE(index, 0) << "Couldn't find a stream to read";
  return index;
}

static void RunDemuxerBenchmark(const std::string& filename) {
  base::FilePath file_path(GetTestDataFilePath(filename));
  double total_time = 0.0;
  for (int i = 0; i < kBenchmarkIterations; ++i) {
    // Setup.
    base::MessageLoop message_loop;
    DemuxerHostImpl demuxer_host;
    FileDataSource data_source;
    ASSERT_TRUE(data_source.Initialize(file_path));

    Demuxer::NeedKeyCB need_key_cb = base::Bind(&NeedKey);
    FFmpegDemuxer demuxer(message_loop.message_loop_proxy(),
                          &data_source,
                          need_key_cb,
                          new MediaLog());

    demuxer.Initialize(&demuxer_host,
                       base::Bind(&QuitLoopWithStatus, &message_loop),
                       false);
    message_loop.Run();
    StreamReader stream_reader(&demuxer, false);

    // Benchmark.
    base::TimeTicks start = base::TimeTicks::HighResNow();
    while (!stream_reader.IsDone()) {
      stream_reader.Read();
    }
    base::TimeTicks end = base::TimeTicks::HighResNow();
    total_time += (end - start).InSecondsF();
    demuxer.Stop(base::Bind(
        &QuitLoopWithStatus, &message_loop, PIPELINE_OK));
    message_loop.Run();
  }

  perf_test::PrintResult("demuxer_bench",
                         "",
                         filename,
                         kBenchmarkIterations / total_time,
                         "runs/s",
                         true);
}

TEST(DemuxerPerfTest, Demuxer) {
  RunDemuxerBenchmark("bear.ogv");
  RunDemuxerBenchmark("bear-640x360.webm");
  RunDemuxerBenchmark("sfx_s16le.wav");
#if defined(USE_PROPRIETARY_CODECS)
  RunDemuxerBenchmark("bear-1280x720.mp4");
  RunDemuxerBenchmark("sfx.mp3");
#endif
#if defined(OS_CHROMEOS)
  RunDemuxerBenchmark("bear.flac");
#endif
#if defined(USE_PROPRIETARY_CODECS) && defined(OS_CHROMEOS)
  RunDemuxerBenchmark("bear.avi");
#endif
}

}  // namespace media
<commit_msg>Disable DemuxerPerfTest.Demuxer on Windows since it takes longer than the test launcher timeout to run.<commit_after>// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/at_exit.h"
#include "base/bind.h"
#include "base/message_loop/message_loop.h"
#include "base/strings/string_number_conversions.h"
#include "base/time/time.h"
#include "media/base/media.h"
#include "media/base/media_log.h"
#include "media/base/test_data_util.h"
#include "media/filters/ffmpeg_demuxer.h"
#include "media/filters/file_data_source.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/perf/perf_test.h"

namespace media {

static const int kBenchmarkIterations = 500;

class DemuxerHostImpl : public media::DemuxerHost {
 public:
  DemuxerHostImpl() {}
  virtual ~DemuxerHostImpl() {}

  // DemuxerHost implementation.
  virtual void AddBufferedTimeRange(base::TimeDelta start,
                                    base::TimeDelta end) OVERRIDE {}
  virtual void SetDuration(base::TimeDelta duration) OVERRIDE {}
  virtual void OnDemuxerError(media::PipelineStatus error) OVERRIDE {}
  virtual void AddTextStream(media::DemuxerStream* text_stream,
                             const media::TextTrackConfig& config) OVERRIDE {}
  virtual void RemoveTextStream(media::DemuxerStream* text_stream) OVERRIDE {}

 private:
  DISALLOW_COPY_AND_ASSIGN(DemuxerHostImpl);
};

static void QuitLoopWithStatus(base::MessageLoop* message_loop,
                        media::PipelineStatus status) {
  CHECK_EQ(status, media::PIPELINE_OK);
  message_loop->PostTask(FROM_HERE, base::MessageLoop::QuitWhenIdleClosure());
}

static void NeedKey(const std::string& type,
                    const std::vector<uint8>& init_data) {
  VLOG(0) << "File is encrypted.";
}

typedef std::vector<media::DemuxerStream* > Streams;

// Simulates playback reading requirements by reading from each stream
// present in |demuxer| in as-close-to-monotonically-increasing timestamp order.
class StreamReader {
 public:
  StreamReader(media::Demuxer* demuxer, bool enable_bitstream_converter);
  ~StreamReader();

  // Performs a single step read.
  void Read();

  // Returns true when all streams have reached end of stream.
  bool IsDone();

  int number_of_streams() { return static_cast<int>(streams_.size()); }
  const Streams& streams() { return streams_; }
  const std::vector<int>& counts() { return counts_; }

 private:
  void OnReadDone(base::MessageLoop* message_loop,
                  bool* end_of_stream,
                  base::TimeDelta* timestamp,
                  media::DemuxerStream::Status status,
                  const scoped_refptr<media::DecoderBuffer>& buffer);
  int GetNextStreamIndexToRead();

  Streams streams_;
  std::vector<bool> end_of_stream_;
  std::vector<base::TimeDelta> last_read_timestamp_;
  std::vector<int> counts_;

  DISALLOW_COPY_AND_ASSIGN(StreamReader);
};

StreamReader::StreamReader(media::Demuxer* demuxer,
                           bool enable_bitstream_converter) {
  media::DemuxerStream* stream =
      demuxer->GetStream(media::DemuxerStream::AUDIO);
  if (stream) {
    streams_.push_back(stream);
    end_of_stream_.push_back(false);
    last_read_timestamp_.push_back(media::kNoTimestamp());
    counts_.push_back(0);
  }

  stream = demuxer->GetStream(media::DemuxerStream::VIDEO);
  if (stream) {
    streams_.push_back(stream);
    end_of_stream_.push_back(false);
    last_read_timestamp_.push_back(media::kNoTimestamp());
    counts_.push_back(0);

    if (enable_bitstream_converter)
      stream->EnableBitstreamConverter();
  }
}

StreamReader::~StreamReader() {}

void StreamReader::Read() {
  int index = GetNextStreamIndexToRead();
  bool end_of_stream = false;
  base::TimeDelta timestamp;

  streams_[index]->Read(base::Bind(
      &StreamReader::OnReadDone, base::Unretained(this),
      base::MessageLoop::current(), &end_of_stream, &timestamp));
  base::MessageLoop::current()->Run();

  CHECK(end_of_stream || timestamp != media::kNoTimestamp());
  end_of_stream_[index] = end_of_stream;
  last_read_timestamp_[index] = timestamp;
  counts_[index]++;
}

bool StreamReader::IsDone() {
  for (size_t i = 0; i < end_of_stream_.size(); ++i) {
    if (!end_of_stream_[i])
      return false;
  }
  return true;
}

void StreamReader::OnReadDone(
    base::MessageLoop* message_loop,
    bool* end_of_stream,
    base::TimeDelta* timestamp,
    media::DemuxerStream::Status status,
    const scoped_refptr<media::DecoderBuffer>& buffer) {
  CHECK_EQ(status, media::DemuxerStream::kOk);
  CHECK(buffer.get());
  *end_of_stream = buffer->end_of_stream();
  *timestamp = *end_of_stream ? media::kNoTimestamp() : buffer->timestamp();
  message_loop->PostTask(FROM_HERE, base::MessageLoop::QuitWhenIdleClosure());
}

int StreamReader::GetNextStreamIndexToRead() {
  int index = -1;
  for (int i = 0; i < number_of_streams(); ++i) {
    // Ignore streams at EOS.
    if (end_of_stream_[i])
      continue;

    // Use a stream if it hasn't been read from yet.
    if (last_read_timestamp_[i] == media::kNoTimestamp())
      return i;

    if (index < 0 ||
        last_read_timestamp_[i] < last_read_timestamp_[index]) {
      index = i;
    }
  }
  CHECK_GE(index, 0) << "Couldn't find a stream to read";
  return index;
}

static void RunDemuxerBenchmark(const std::string& filename) {
  base::FilePath file_path(GetTestDataFilePath(filename));
  double total_time = 0.0;
  for (int i = 0; i < kBenchmarkIterations; ++i) {
    // Setup.
    base::MessageLoop message_loop;
    DemuxerHostImpl demuxer_host;
    FileDataSource data_source;
    ASSERT_TRUE(data_source.Initialize(file_path));

    Demuxer::NeedKeyCB need_key_cb = base::Bind(&NeedKey);
    FFmpegDemuxer demuxer(message_loop.message_loop_proxy(),
                          &data_source,
                          need_key_cb,
                          new MediaLog());

    demuxer.Initialize(&demuxer_host,
                       base::Bind(&QuitLoopWithStatus, &message_loop),
                       false);
    message_loop.Run();
    StreamReader stream_reader(&demuxer, false);

    // Benchmark.
    base::TimeTicks start = base::TimeTicks::HighResNow();
    while (!stream_reader.IsDone()) {
      stream_reader.Read();
    }
    base::TimeTicks end = base::TimeTicks::HighResNow();
    total_time += (end - start).InSecondsF();
    demuxer.Stop(base::Bind(
        &QuitLoopWithStatus, &message_loop, PIPELINE_OK));
    message_loop.Run();
  }

  perf_test::PrintResult("demuxer_bench",
                         "",
                         filename,
                         kBenchmarkIterations / total_time,
                         "runs/s",
                         true);
}

#if defined(OS_WIN)
// http://crbug.com/399002
#define MAYBE_Demuxer DISABLED_Demuxer
#else
#define MAYBE_Demuxer Demuxer
#endif
TEST(DemuxerPerfTest, MAYBE_Demuxer) {
  RunDemuxerBenchmark("bear.ogv");
  RunDemuxerBenchmark("bear-640x360.webm");
  RunDemuxerBenchmark("sfx_s16le.wav");
#if defined(USE_PROPRIETARY_CODECS)
  RunDemuxerBenchmark("bear-1280x720.mp4");
  RunDemuxerBenchmark("sfx.mp3");
#endif
#if defined(OS_CHROMEOS)
  RunDemuxerBenchmark("bear.flac");
#endif
#if defined(USE_PROPRIETARY_CODECS) && defined(OS_CHROMEOS)
  RunDemuxerBenchmark("bear.avi");
#endif
}

}  // namespace media
<|endoftext|>


<commit_before>
#include <glslengine.h>
#include <glslparser.h>
#include <glsllexer.h>
#include <iostream>
#include <fstream>
#include <cstring>
#include <cassert>

using namespace GLSL;

#ifndef EXIT_FAILURE
#define EXIT_FAILURE 1
#endif
#ifndef EXIT_SUCCESS
#define EXIT_SUCCESS 0
#endif

int main(int argc, char *argv[])
{
    int variant = 0;

    while (argc > 1 && argv[1][0] == '-' && argv[1][1] == '-') {
        if (!strcmp(argv[1], "--version=1.20")) {
            variant |= Lexer::Variant_GLSL_120;
        } else if (!strcmp(argv[1], "--version=1.50")) {
            variant |= Lexer::Variant_GLSL_150;
        } else if (!strcmp(argv[1], "--version=4.00")) {
            variant |= Lexer::Variant_GLSL_400;
        } else if (!strcmp(argv[1], "--version=es")) {
            variant |= Lexer::Variant_GLSL_ES_100;
        } else if (!strcmp(argv[1], "--version=qt")) {
            variant |= Lexer::Variant_GLSL_ES_100 |
                       Lexer::Variant_GLSL_Qt;
        } else if (!strcmp(argv[1], "--shader=vertex")) {
            variant |= Lexer::Variant_VertexShader;
        } else if (!strcmp(argv[1], "--shader=fragment")) {
            variant |= Lexer::Variant_FragmentShader;
        } else {
            std::cerr << "glsl: unknown option: " << argv[1] << std::endl;
            return EXIT_FAILURE;
        }
        ++argv;
        --argc;
    }

    if (argc != 2) {
        std::cerr << "glsl: no input file" << std::endl;
        return EXIT_FAILURE;
    }

    std::ifstream fin(argv[1]);
    if (! fin) {
        std::cerr << "glsl: No such file or directory" << std::endl;
        return EXIT_FAILURE;
    }
    fin.seekg(0, std::ios::end);
    size_t size = fin.tellg();
    fin.seekg(0, std::ios::beg);
    char *source = new char[size];
    fin.read(source, size);
    fin.close();
    if (!variant)
        variant = Lexer::Variant_Mask & ~Lexer::Variant_Reserved;
    else if ((variant & (Lexer::Variant_VertexShader | Lexer::Variant_FragmentShader)) == 0)
        variant |= Lexer::Variant_VertexShader | Lexer::Variant_FragmentShader;
    Engine engine;
    Parser parser(&engine, source, size, variant);
    TranslationUnit *ast = parser.parse();
    std::cout << argv[1] << (ast ? " OK " : " KO ") << std::endl;

    if (ast) {
        assert(ast->asTranslationUnit() != 0);
        int n = 0;
        for (List<Declaration *> *it = ast->declarations; it; it = it->next, ++n) {
            Declaration *decl = it->value;
            // ### do something with decl
            (void) decl;
        }
        std::cout << "found " << n << " level declarations" << std::endl;
    }

    delete source;
    delete ast;

    return EXIT_SUCCESS;
}
<commit_msg>Dump the AST.<commit_after>
#include <glslengine.h>
#include <glslparser.h>
#include <glsllexer.h>
#include <glslastdump.h>

#include <QtCore/QTextStream>

#include <iostream>
#include <fstream>
#include <cstring>
#include <cassert>
#include <cstdio>

using namespace GLSL;

#ifndef EXIT_FAILURE
#define EXIT_FAILURE 1
#endif
#ifndef EXIT_SUCCESS
#define EXIT_SUCCESS 0
#endif

namespace {
QTextStream qout(stdout, QIODevice::WriteOnly);
}

int main(int argc, char *argv[])
{
    int variant = 0;

    while (argc > 1 && argv[1][0] == '-' && argv[1][1] == '-') {
        if (!strcmp(argv[1], "--version=1.20")) {
            variant |= Lexer::Variant_GLSL_120;
        } else if (!strcmp(argv[1], "--version=1.50")) {
            variant |= Lexer::Variant_GLSL_150;
        } else if (!strcmp(argv[1], "--version=4.00")) {
            variant |= Lexer::Variant_GLSL_400;
        } else if (!strcmp(argv[1], "--version=es")) {
            variant |= Lexer::Variant_GLSL_ES_100;
        } else if (!strcmp(argv[1], "--version=qt")) {
            variant |= Lexer::Variant_GLSL_ES_100 |
                       Lexer::Variant_GLSL_Qt;
        } else if (!strcmp(argv[1], "--shader=vertex")) {
            variant |= Lexer::Variant_VertexShader;
        } else if (!strcmp(argv[1], "--shader=fragment")) {
            variant |= Lexer::Variant_FragmentShader;
        } else {
            std::cerr << "glsl: unknown option: " << argv[1] << std::endl;
            return EXIT_FAILURE;
        }
        ++argv;
        --argc;
    }

    if (argc != 2) {
        std::cerr << "glsl: no input file" << std::endl;
        return EXIT_FAILURE;
    }

    std::ifstream fin(argv[1]);
    if (! fin) {
        std::cerr << "glsl: No such file or directory" << std::endl;
        return EXIT_FAILURE;
    }
    fin.seekg(0, std::ios::end);
    size_t size = fin.tellg();
    fin.seekg(0, std::ios::beg);
    char *source = new char[size];
    fin.read(source, size);
    fin.close();
    if (!variant)
        variant = Lexer::Variant_Mask & ~Lexer::Variant_Reserved;
    else if ((variant & (Lexer::Variant_VertexShader | Lexer::Variant_FragmentShader)) == 0)
        variant |= Lexer::Variant_VertexShader | Lexer::Variant_FragmentShader;
    Engine engine;
    Parser parser(&engine, source, size, variant);
    TranslationUnit *ast = parser.parse();
    std::cout << argv[1] << (ast ? " OK " : " KO ") << std::endl;

    ASTDump dump(qout);
    dump(ast);

    delete source;
    delete ast;

    return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before><commit_msg>Cache infinite_simplex<commit_after><|endoftext|>


<commit_before><commit_msg>tests: Avoid hitting some known minor tinyformat issues when fuzzing strprintf(...)<commit_after><|endoftext|>


<commit_before>#include <tuple>
#include <cppkafka/metadata.h>
#include "topic_offset_reader.h"
#include "detail/logging.h"
#include "utils/utils.h"

using std::string;
using std::move;
using std::unordered_set;
using std::set;
using std::lock_guard;
using std::mutex;
using std::tie;
using std::ignore;

using std::this_thread::sleep_for;

using std::chrono::seconds;

using cppkafka::Consumer;
using cppkafka::Message;
using cppkafka::Configuration;
using cppkafka::Metadata;
using cppkafka::TopicMetadata;
using cppkafka::TopicPartition;
using cppkafka::TopicPartitionList;

namespace pirulo {

PIRULO_CREATE_LOGGER("p.topics");

static Configuration prepare_config(Configuration config) {
    config.set("group.id", utils::generate_group_id());
    LOG4CXX_INFO(logger, "Using consumer " << config.get("group.id") << " for "
                 << " topic offset consumption");
    return config;
}

TopicOffsetReader::TopicOffsetReader(StorePtr store, size_t thread_count,
                                     ConsumerOffsetReaderPtr consumer_reader,
                                     Configuration config)
: consumer_pool_(thread_count, prepare_config(move(config))),store_(move(store)),
  thread_pool_(thread_count), consumer_offset_reader_(move(consumer_reader)) {

}

void TopicOffsetReader::run() {
    LOG4CXX_INFO(logger, "Performing topic offsets cold start");
    process_metadata([&](TopicPartitionCount topics) {
        async_process_topics(topics);
        monitor_topics(topics);
    });
    thread_pool_.wait_for_tasks();
    LOG4CXX_INFO(logger, "Finished topic offsets cold start");

    monitor_new_topics();
    while (running_) {
        sleep_for(seconds(10));
    }
}

void TopicOffsetReader::stop() {
    running_ = false;
    thread_pool_.stop();
}

TopicOffsetReader::StorePtr TopicOffsetReader::get_store() const {
    return store_;
}

void TopicOffsetReader::async_process_topics(const TopicPartitionCount& topics) {
    LOG4CXX_INFO(logger, "Fetching offsets for " << topics.size() << " topics");
    for (const auto& topic_pair : topics) {
        const string& topic = topic_pair.first;
        const size_t partition_count = topic_pair.second;
        for (size_t i = 0; i < partition_count; ++i) {
            thread_pool_.add_task([&, topic, i] {
                process_topic_partition({ topic, static_cast<int>(i) });
            });
        }
    }
}

void TopicOffsetReader::monitor_topics(const TopicPartitionCount& topics) {
    // They're all new, just convert them to a TopicPartitionList
    monitor_topics(get_new_topic_partitions(topics));
}

void TopicOffsetReader::monitor_topics(const TopicPartitionList& topics) {
    for (const TopicPartition& topic_partition : topics) {
        auto task = [&, topic_partition] {
            process_topic_partition(topic_partition);
        };
        // Schedule a task to process it periodically
        auto task_id = task_scheduler_.add_task(move(task), maximum_topic_reload_time_);

        // Mark it as monitored
        monitored_topic_task_id_.emplace(topic_partition, task_id);

        // Watch for commits on this topic
        auto commit_callback = [&](const string& topic, int partition) {
            on_commit(topic, partition);
        };
        consumer_offset_reader_->watch_commits(topic_partition.get_topic(),
                                               topic_partition.get_partition(),
                                               move(commit_callback));
    }
}

void TopicOffsetReader::monitor_new_topics() {
    auto task = [&] {
        process_metadata([&](const TopicPartitionCount& counts) {
            const TopicPartitionList new_topics = get_new_topic_partitions(counts);
            if (!new_topics.empty()) {
                LOG4CXX_INFO(logger, "Found " << new_topics.size() << " new topic/partitions "
                             "to process");
                monitor_topics(new_topics);
            }
        });
    };
    task_scheduler_.add_task(move(task), maximum_metadata_reload_time_);
}

TopicPartitionList TopicOffsetReader::get_new_topic_partitions(const TopicPartitionCount& counts) {
    TopicPartitionList output;
    for (const auto& topic_count_pair : counts) {
        const string& topic = topic_count_pair.first;
        for (size_t i = 0; i < topic_count_pair.second; ++i) {
            TopicPartition topic_partition(topic, i);
            if (!monitored_topic_task_id_.count(topic_partition)) {
                output.emplace_back(move(topic_partition));
            }
        }
    }
    return output;
}

TopicOffsetReader::TopicPartitionCount TopicOffsetReader::load_metadata() {
    // Load all existing topic names
    TopicPartitionCount topics;
    consumer_pool_.acquire_consumer([&](Consumer& consumer) {
        Metadata md = consumer.get_metadata();
        for (const TopicMetadata& topic_metadata : md.get_topics()) {
            topics.emplace(topic_metadata.get_name(),
                           topic_metadata.get_partitions().size());
        }
    });
    return topics;
}

void TopicOffsetReader::process_metadata(const MetadataCallback& callback) {
    LOG4CXX_INFO(logger, "Loading topics metadata");

    try {
        TopicPartitionCount topics = load_metadata();
        LOG4CXX_INFO(logger, "Finished loading metadata, found " << topics.size() << " topics");
        callback(move(topics));
    }
    catch (const cppkafka::Exception& ex) {
        LOG4CXX_ERROR(logger, "Failed to fetch topic metadata: " << ex.what());
    }
}

void TopicOffsetReader::process_topic_partition(const TopicPartition& topic_partition) {
    LOG4CXX_TRACE(logger, "Fetching offset for " << topic_partition);
    uint64_t offset;
    try {
        consumer_pool_.acquire_consumer([&](Consumer& consumer) {
            tie(ignore, offset) = consumer.query_offsets(topic_partition);
            store_->store_topic_offset(topic_partition.get_topic(),
                                       topic_partition.get_partition(), offset);
        });
    }
    catch (const cppkafka::Exception& ex) {
        LOG4CXX_ERROR(logger, "Failed to fetch offsets for " << topic_partition
                      << ": " << ex.what());
    }
}

void TopicOffsetReader::on_commit(const string& topic, int partition) {
    TopicPartition topic_partition(topic, partition);
    LOG4CXX_TRACE(logger, "Bumping up priority of offset loading for " << topic_partition);
    // Increase the priority for this task
    auto task_id = monitored_topic_task_id_.at(topic_partition);
    task_scheduler_.set_priority(task_id, 0.0);
}

} // pirulo
<commit_msg>Don't sleep while looping on topic offset reader<commit_after>#include <tuple>
#include <cppkafka/metadata.h>
#include "topic_offset_reader.h"
#include "detail/logging.h"
#include "utils/utils.h"

using std::string;
using std::move;
using std::unordered_set;
using std::set;
using std::lock_guard;
using std::mutex;
using std::tie;
using std::ignore;

using std::this_thread::sleep_for;

using std::chrono::seconds;

using cppkafka::Consumer;
using cppkafka::Message;
using cppkafka::Configuration;
using cppkafka::Metadata;
using cppkafka::TopicMetadata;
using cppkafka::TopicPartition;
using cppkafka::TopicPartitionList;

namespace pirulo {

PIRULO_CREATE_LOGGER("p.topics");

static Configuration prepare_config(Configuration config) {
    config.set("group.id", utils::generate_group_id());
    LOG4CXX_INFO(logger, "Using consumer " << config.get("group.id") << " for "
                 << " topic offset consumption");
    return config;
}

TopicOffsetReader::TopicOffsetReader(StorePtr store, size_t thread_count,
                                     ConsumerOffsetReaderPtr consumer_reader,
                                     Configuration config)
: consumer_pool_(thread_count, prepare_config(move(config))),store_(move(store)),
  thread_pool_(thread_count), consumer_offset_reader_(move(consumer_reader)) {

}

void TopicOffsetReader::run() {
    LOG4CXX_INFO(logger, "Performing topic offsets cold start");
    process_metadata([&](TopicPartitionCount topics) {
        async_process_topics(topics);
        monitor_topics(topics);
    });
    thread_pool_.wait_for_tasks();
    LOG4CXX_INFO(logger, "Finished topic offsets cold start");

    monitor_new_topics();
}

void TopicOffsetReader::stop() {
    running_ = false;
    thread_pool_.stop();
}

TopicOffsetReader::StorePtr TopicOffsetReader::get_store() const {
    return store_;
}

void TopicOffsetReader::async_process_topics(const TopicPartitionCount& topics) {
    LOG4CXX_INFO(logger, "Fetching offsets for " << topics.size() << " topics");
    for (const auto& topic_pair : topics) {
        const string& topic = topic_pair.first;
        const size_t partition_count = topic_pair.second;
        for (size_t i = 0; i < partition_count; ++i) {
            thread_pool_.add_task([&, topic, i] {
                process_topic_partition({ topic, static_cast<int>(i) });
            });
        }
    }
}

void TopicOffsetReader::monitor_topics(const TopicPartitionCount& topics) {
    // They're all new, just convert them to a TopicPartitionList
    monitor_topics(get_new_topic_partitions(topics));
}

void TopicOffsetReader::monitor_topics(const TopicPartitionList& topics) {
    for (const TopicPartition& topic_partition : topics) {
        auto task = [&, topic_partition] {
            process_topic_partition(topic_partition);
        };
        // Schedule a task to process it periodically
        auto task_id = task_scheduler_.add_task(move(task), maximum_topic_reload_time_);

        // Mark it as monitored
        monitored_topic_task_id_.emplace(topic_partition, task_id);

        // Watch for commits on this topic
        auto commit_callback = [&](const string& topic, int partition) {
            on_commit(topic, partition);
        };
        consumer_offset_reader_->watch_commits(topic_partition.get_topic(),
                                               topic_partition.get_partition(),
                                               move(commit_callback));
    }
}

void TopicOffsetReader::monitor_new_topics() {
    auto task = [&] {
        process_metadata([&](const TopicPartitionCount& counts) {
            const TopicPartitionList new_topics = get_new_topic_partitions(counts);
            if (!new_topics.empty()) {
                LOG4CXX_INFO(logger, "Found " << new_topics.size() << " new topic/partitions "
                             "to process");
                monitor_topics(new_topics);
            }
        });
    };
    task_scheduler_.add_task(move(task), maximum_metadata_reload_time_);
}

TopicPartitionList TopicOffsetReader::get_new_topic_partitions(const TopicPartitionCount& counts) {
    TopicPartitionList output;
    for (const auto& topic_count_pair : counts) {
        const string& topic = topic_count_pair.first;
        for (size_t i = 0; i < topic_count_pair.second; ++i) {
            TopicPartition topic_partition(topic, i);
            if (!monitored_topic_task_id_.count(topic_partition)) {
                output.emplace_back(move(topic_partition));
            }
        }
    }
    return output;
}

TopicOffsetReader::TopicPartitionCount TopicOffsetReader::load_metadata() {
    // Load all existing topic names
    TopicPartitionCount topics;
    consumer_pool_.acquire_consumer([&](Consumer& consumer) {
        Metadata md = consumer.get_metadata();
        for (const TopicMetadata& topic_metadata : md.get_topics()) {
            topics.emplace(topic_metadata.get_name(),
                           topic_metadata.get_partitions().size());
        }
    });
    return topics;
}

void TopicOffsetReader::process_metadata(const MetadataCallback& callback) {
    LOG4CXX_INFO(logger, "Loading topics metadata");

    try {
        TopicPartitionCount topics = load_metadata();
        LOG4CXX_INFO(logger, "Finished loading metadata, found " << topics.size() << " topics");
        callback(move(topics));
    }
    catch (const cppkafka::Exception& ex) {
        LOG4CXX_ERROR(logger, "Failed to fetch topic metadata: " << ex.what());
    }
}

void TopicOffsetReader::process_topic_partition(const TopicPartition& topic_partition) {
    LOG4CXX_TRACE(logger, "Fetching offset for " << topic_partition);
    uint64_t offset;
    try {
        consumer_pool_.acquire_consumer([&](Consumer& consumer) {
            tie(ignore, offset) = consumer.query_offsets(topic_partition);
            store_->store_topic_offset(topic_partition.get_topic(),
                                       topic_partition.get_partition(), offset);
        });
    }
    catch (const cppkafka::Exception& ex) {
        LOG4CXX_ERROR(logger, "Failed to fetch offsets for " << topic_partition
                      << ": " << ex.what());
    }
}

void TopicOffsetReader::on_commit(const string& topic, int partition) {
    TopicPartition topic_partition(topic, partition);
    LOG4CXX_TRACE(logger, "Bumping up priority of offset loading for " << topic_partition);
    // Increase the priority for this task
    auto task_id = monitored_topic_task_id_.at(topic_partition);
    task_scheduler_.set_priority(task_id, 0.0);
}

} // pirulo
<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- vim:set ts=4 sw=4 sts=4 noet: */
#include "method.h"

#include <cassert>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <iterator>
#include <sstream>
#include <string>
#include <unordered_map>
#include <vector>

#include <boost/uuid/uuid.hpp>
#include <boost/variant/static_visitor.hpp>

#include "db/ast-inserter.h"
#include "db/query.h"
#include "method/equation-grammar.h"
#include "method/equation-lexer.h"
#include "method/helper.h"
#include "method/parser.h"
#include "method/printer.h"

namespace flint {
namespace method {

namespace {

class VariantPrinter : public boost::static_visitor<> {
public:
	explicit VariantPrinter(std::ostream *os)
		: os_(os)
	{}

	void operator()(const Compound &c) const {
		os_->put('(');
		*os_ << c.keyword;
		for (const auto &child : c.children) {
			os_->put(' ');
			boost::apply_visitor(*this, child);
		}
		os_->put(')');
	}

	void operator()(const std::string &s) const {
		if (s[0] != '%') {
			*os_ << s;
			return;
		}
		if (s == "%time") {
			*os_ << "(plus %time @dt)";
			return;
		}
		*os_ << s << "#0";
	}

	void operator()(int i) const {
		*os_ << i;
	}

	void operator()(const flint::lexer::Rational &r) const {
		*os_ << r.lexeme;
	}

	void operator()(const flint::lexer::Real &r) const {
		*os_ << r.lexeme;
	}

private:
	std::ostream *os_;
};

bool IsDifferential(const Expr &e, std::string &id)
{
	if (e.which() != kExprIsCompound)
		return false;
	const auto &c = boost::get<Compound>(e);
	if (c.keyword != "$differential")
		return false;
	if (c.children.size() != 1)
		return false;
	const auto &x = c.children.at(0);
	if (x.which() != kExprIsString)
		return false;
	id = boost::get<std::string>(x);
	return true;
}

bool IsMinus1(const Expr &e, Expr &arg)
{
	if (e.which() != kExprIsCompound)
		return false;
	const auto &c = boost::get<Compound>(e);
	if (c.keyword != "minus")
		return false;
	if (c.children.size() == 1) {
		arg = c.children[0];
		return true;
	}
	return false;
}

Expr ChangeSign(const Expr &e, double sign)
{
	if (sign > 0)
		return e;
	Expr r;
	if (IsMinus1(e, r))
		return r;
	Compound m;
	m.keyword = "minus";
	m.children.push_back(e);
	return m;
}

bool DecomposeSdeRhsTerm(const Expr &term, std::string &id, Expr &factor, double sign)
{
	if (IsDifferential(term, id)) {
		factor = sign * 1.0;
		return true;
	}
	if (term.which() != kExprIsCompound)
		return false;
	const auto &c = boost::get<Compound>(term);
	if (c.keyword != "times")
		return false;
	if (IsDifferential(c.children.back(), id)) {
		if (c.children.size() == 2) {
			factor = ChangeSign(c.children.front(), sign);
			return true;
		}
		Compound p;
		p.keyword = "times";
		// copy children except the last one
		for (size_t i=0;i<c.children.size()-1;i++)
			p.children.push_back(c.children[i]);
		factor = ChangeSign(p, sign);
		return true;
	}
	if (IsDifferential(c.children.front(), id)) {
		if (c.children.size() == 2) {
			factor = ChangeSign(c.children.back(), sign);
			return true;
		}
		Compound p;
		p.keyword = "times";
		// copy children except the first one
		for (size_t i=1;i<c.children.size();i++)
			p.children.push_back(c.children[i]);
		factor = ChangeSign(p, sign);
		return true;
	}
	return false;
}

bool IsVoidDrift(Expr &drift)
{
	return drift.which() == kExprIsInteger && boost::get<int>(drift) == 0;
}

/*
 * precondition: drift = 0
 */
bool DecomposeSdeRhs(const Expr &rhs, Expr &drift, std::unordered_map<std::string, Expr> &diffusion,
					 double sign = 1.0)
{
	assert(rhs.which() == kExprIsCompound);
	std::string id;
	Expr factor;
	if (DecomposeSdeRhsTerm(rhs, id, factor, sign)) {
		if (id == "%time") {
			if (IsVoidDrift(drift)) {
				drift = factor;
				return true;
			} else {
				std::cerr << "more than one drift terms" << std::endl;
				return false;
			}
		} else if (diffusion.emplace(id, factor).second) {
			return true;
		} else {
			std::cerr << "more than one diffusion terms are unsupported: " << id << std::endl;
			return false;
		}
	}
	const auto &c = boost::get<Compound>(rhs);
	if (c.keyword == "plus") {
		for (const auto &e : c.children) {
			Expr d = 0;
			if (!DecomposeSdeRhs(e, d, diffusion, sign))
				return false;
			// check if there are more than one drift terms
			if (!IsVoidDrift(d)) {
				if (IsVoidDrift(drift)) {
					drift = d;
				} else {
					std::cerr << "more than one drift terms" << std::endl;
					return false;
				}
			}
		}
		return true;
	}
	if (c.keyword == "minus") {
		if (c.children.size() == 1) {
			Expr d = 0;
			if (!DecomposeSdeRhs(c.children[0], d, diffusion, -sign))
				return false;
			// check if there are more than one drift terms
			if (!IsVoidDrift(d)) {
				if (IsVoidDrift(drift)) {
					drift = d;
				} else {
					std::cerr << "more than one drift terms" << std::endl;
					return false;
				}
			}
		} else {
			assert(c.children.size() == 2);
			Expr d0 = 0;
			if (!DecomposeSdeRhs(c.children[0], d0, diffusion, sign))
				return false;
			// check if there are more than one drift terms
			if (!IsVoidDrift(d0)) {
				if (IsVoidDrift(drift)) {
					drift = d0;
				} else {
					std::cerr << "more than one drift terms" << std::endl;
					return false;
				}
			}
			Expr d1 = 0;
			if (!DecomposeSdeRhs(c.children[1], d1, diffusion, -sign))
				return false;
			// check if there are more than one drift terms
			if (!IsVoidDrift(d1)) {
				if (IsVoidDrift(drift)) {
					drift = d1;
				} else {
					std::cerr << "more than one drift terms" << std::endl;
					return false;
				}
			}
		}
		return true;
	}
	std::cerr << "either plus or minus expected, but got: " << c.keyword << std::endl;
	return false;
}

class Inserter : db::AstInserter {
public:
	explicit Inserter(sqlite3 *db)
		: db::AstInserter(db)
	{
	}

	bool PrintAndInsert(const boost::uuids::uuid &uuid,
						const Expr &lhs,
						const Expr &rhs)
	{
		std::ostringstream oss;
		if (lhs.which() == kExprIsString) { // LHS: x = ...
			const std::string &id(boost::get<std::string>(lhs));
			oss << id << "#0";
			std::string name = oss.str();
			oss.str("");
			boost::apply_visitor(VariantPrinter(&oss), rhs);
			std::string math = oss.str();
			return Insert(uuid, name.c_str(), math.c_str());
		}
		std::string id;
		if (IsDifferential(lhs, id)) { // LHS: dx = ...
			Expr drift = 0;
			std::unordered_map<std::string, Expr> diffusion;
			if (!DecomposeSdeRhs(rhs, drift, diffusion))
				return false;
			oss << id << "#0";
			std::string name = oss.str();
			oss.str("");
			for (const auto &d : diffusion) {
				(void)d;
				oss << "(plus ";
			}
			if (IsVoidDrift(drift)) {
				oss << id;
			} else {
				oss << "(plus " << id << " (times ";
				boost::apply_visitor(Printer(&oss), drift);
				oss << " @dt))";
			}
			for (const auto &d : diffusion) {
				oss << " (times ";
				boost::apply_visitor(Printer(&oss), d.second);
				oss << " " << d.first << "#1))";
			}
			std::string math = oss.str();
			return Insert(uuid, name.c_str(), math.c_str());
		}
		// LHS: dx/dt = ...
		assert(lhs.which() == kExprIsCompound);
		const Compound &c(boost::get<Compound>(lhs));
		assert(c.children.size() == 2);
		const Expr &e(c.children.at(1));
		assert(e.which() == kExprIsString);
		id = boost::get<std::string>(e);
		oss << id << "#0";
		std::string name = oss.str();
		oss.str("");
		oss << "(plus " << id << " (times @dt ";
		boost::apply_visitor(Printer(&oss), rhs);
		oss << "))";
		std::string math = oss.str();
		return Insert(uuid, name.c_str(), math.c_str());
	}

	bool PrintAndInsertWiener(const boost::uuids::uuid &uuid,
							  const Expr &e)
	{
		std::ostringstream oss;
		assert(e.which() == kExprIsString);
		const std::string &id(boost::get<std::string>(e));
		oss << id << "#1";
		std::string name = oss.str();
		if (!Insert(uuid, name.c_str(), "($gauss_variate 0 (root @dt))"))
			return false;
		oss.str("");
		oss << id << "#0";
		name = oss.str();
		oss.str("");
		oss << "(plus " << id << " " << id << "#1)";
		std::string math = oss.str();
		return Insert(uuid, name.c_str(), math.c_str());
	}
};

}

bool EulerMaruyama(sqlite3 *db, const char *input, sqlite3 *output)
{
	return Parse<2, EquationLexer, EquationGrammar, Inserter>(db, input, output);
}

}
}
<commit_msg>Generate simpler code for cefficients of substraction form<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- vim:set ts=4 sw=4 sts=4 noet: */
#include "method.h"

#include <cassert>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <iterator>
#include <sstream>
#include <string>
#include <unordered_map>
#include <vector>

#include <boost/uuid/uuid.hpp>
#include <boost/variant/static_visitor.hpp>

#include "db/ast-inserter.h"
#include "db/query.h"
#include "method/equation-grammar.h"
#include "method/equation-lexer.h"
#include "method/helper.h"
#include "method/parser.h"
#include "method/printer.h"

namespace flint {
namespace method {

namespace {

class VariantPrinter : public boost::static_visitor<> {
public:
	explicit VariantPrinter(std::ostream *os)
		: os_(os)
	{}

	void operator()(const Compound &c) const {
		os_->put('(');
		*os_ << c.keyword;
		for (const auto &child : c.children) {
			os_->put(' ');
			boost::apply_visitor(*this, child);
		}
		os_->put(')');
	}

	void operator()(const std::string &s) const {
		if (s[0] != '%') {
			*os_ << s;
			return;
		}
		if (s == "%time") {
			*os_ << "(plus %time @dt)";
			return;
		}
		*os_ << s << "#0";
	}

	void operator()(int i) const {
		*os_ << i;
	}

	void operator()(const flint::lexer::Rational &r) const {
		*os_ << r.lexeme;
	}

	void operator()(const flint::lexer::Real &r) const {
		*os_ << r.lexeme;
	}

private:
	std::ostream *os_;
};

bool IsDifferential(const Expr &e, std::string &id)
{
	if (e.which() != kExprIsCompound)
		return false;
	const auto &c = boost::get<Compound>(e);
	if (c.keyword != "$differential")
		return false;
	if (c.children.size() != 1)
		return false;
	const auto &x = c.children.at(0);
	if (x.which() != kExprIsString)
		return false;
	id = boost::get<std::string>(x);
	return true;
}

bool IsMinus1(const Expr &e, Expr &arg)
{
	if (e.which() != kExprIsCompound)
		return false;
	const auto &c = boost::get<Compound>(e);
	if (c.keyword != "minus")
		return false;
	if (c.children.size() == 1) {
		arg = c.children[0];
		return true;
	}
	return false;
}

bool IsMinus2(const Expr &e, Expr &arg0, Expr &arg1)
{
	if (e.which() != kExprIsCompound)
		return false;
	const auto &c = boost::get<Compound>(e);
	if (c.keyword != "minus")
		return false;
	if (c.children.size() == 2) {
		arg0 = c.children[0];
		arg1 = c.children[1];
		return true;
	}
	return false;
}

Expr ChangeSign(const Expr &e, double sign)
{
	if (sign > 0)
		return e;
	Expr r0, r1;
	if (IsMinus1(e, r0))
		return r0;
	Compound m;
	m.keyword = "minus";
	if (IsMinus2(e, r0, r1)) { // swap the 1st argument with the 2nd
		m.children.push_back(r1);
		m.children.push_back(r0);
		return m;
	}
	m.children.push_back(e);
	return m;
}

bool DecomposeSdeRhsTerm(const Expr &term, std::string &id, Expr &factor, double sign)
{
	if (IsDifferential(term, id)) {
		factor = sign * 1.0;
		return true;
	}
	if (term.which() != kExprIsCompound)
		return false;
	const auto &c = boost::get<Compound>(term);
	if (c.keyword != "times")
		return false;
	if (IsDifferential(c.children.back(), id)) {
		if (c.children.size() == 2) {
			factor = ChangeSign(c.children.front(), sign);
			return true;
		}
		Compound p;
		p.keyword = "times";
		// copy children except the last one
		for (size_t i=0;i<c.children.size()-1;i++)
			p.children.push_back(c.children[i]);
		factor = ChangeSign(p, sign);
		return true;
	}
	if (IsDifferential(c.children.front(), id)) {
		if (c.children.size() == 2) {
			factor = ChangeSign(c.children.back(), sign);
			return true;
		}
		Compound p;
		p.keyword = "times";
		// copy children except the first one
		for (size_t i=1;i<c.children.size();i++)
			p.children.push_back(c.children[i]);
		factor = ChangeSign(p, sign);
		return true;
	}
	return false;
}

bool IsVoidDrift(Expr &drift)
{
	return drift.which() == kExprIsInteger && boost::get<int>(drift) == 0;
}

/*
 * precondition: drift = 0
 */
bool DecomposeSdeRhs(const Expr &rhs, Expr &drift, std::unordered_map<std::string, Expr> &diffusion,
					 double sign = 1.0)
{
	assert(rhs.which() == kExprIsCompound);
	std::string id;
	Expr factor;
	if (DecomposeSdeRhsTerm(rhs, id, factor, sign)) {
		if (id == "%time") {
			if (IsVoidDrift(drift)) {
				drift = factor;
				return true;
			} else {
				std::cerr << "more than one drift terms" << std::endl;
				return false;
			}
		} else if (diffusion.emplace(id, factor).second) {
			return true;
		} else {
			std::cerr << "more than one diffusion terms are unsupported: " << id << std::endl;
			return false;
		}
	}
	const auto &c = boost::get<Compound>(rhs);
	if (c.keyword == "plus") {
		for (const auto &e : c.children) {
			Expr d = 0;
			if (!DecomposeSdeRhs(e, d, diffusion, sign))
				return false;
			// check if there are more than one drift terms
			if (!IsVoidDrift(d)) {
				if (IsVoidDrift(drift)) {
					drift = d;
				} else {
					std::cerr << "more than one drift terms" << std::endl;
					return false;
				}
			}
		}
		return true;
	}
	if (c.keyword == "minus") {
		if (c.children.size() == 1) {
			Expr d = 0;
			if (!DecomposeSdeRhs(c.children[0], d, diffusion, -sign))
				return false;
			// check if there are more than one drift terms
			if (!IsVoidDrift(d)) {
				if (IsVoidDrift(drift)) {
					drift = d;
				} else {
					std::cerr << "more than one drift terms" << std::endl;
					return false;
				}
			}
		} else {
			assert(c.children.size() == 2);
			Expr d0 = 0;
			if (!DecomposeSdeRhs(c.children[0], d0, diffusion, sign))
				return false;
			// check if there are more than one drift terms
			if (!IsVoidDrift(d0)) {
				if (IsVoidDrift(drift)) {
					drift = d0;
				} else {
					std::cerr << "more than one drift terms" << std::endl;
					return false;
				}
			}
			Expr d1 = 0;
			if (!DecomposeSdeRhs(c.children[1], d1, diffusion, -sign))
				return false;
			// check if there are more than one drift terms
			if (!IsVoidDrift(d1)) {
				if (IsVoidDrift(drift)) {
					drift = d1;
				} else {
					std::cerr << "more than one drift terms" << std::endl;
					return false;
				}
			}
		}
		return true;
	}
	std::cerr << "either plus or minus expected, but got: " << c.keyword << std::endl;
	return false;
}

class Inserter : db::AstInserter {
public:
	explicit Inserter(sqlite3 *db)
		: db::AstInserter(db)
	{
	}

	bool PrintAndInsert(const boost::uuids::uuid &uuid,
						const Expr &lhs,
						const Expr &rhs)
	{
		std::ostringstream oss;
		if (lhs.which() == kExprIsString) { // LHS: x = ...
			const std::string &id(boost::get<std::string>(lhs));
			oss << id << "#0";
			std::string name = oss.str();
			oss.str("");
			boost::apply_visitor(VariantPrinter(&oss), rhs);
			std::string math = oss.str();
			return Insert(uuid, name.c_str(), math.c_str());
		}
		std::string id;
		if (IsDifferential(lhs, id)) { // LHS: dx = ...
			Expr drift = 0;
			std::unordered_map<std::string, Expr> diffusion;
			if (!DecomposeSdeRhs(rhs, drift, diffusion))
				return false;
			oss << id << "#0";
			std::string name = oss.str();
			oss.str("");
			for (const auto &d : diffusion) {
				(void)d;
				oss << "(plus ";
			}
			if (IsVoidDrift(drift)) {
				oss << id;
			} else {
				oss << "(plus " << id << " (times ";
				boost::apply_visitor(Printer(&oss), drift);
				oss << " @dt))";
			}
			for (const auto &d : diffusion) {
				oss << " (times ";
				boost::apply_visitor(Printer(&oss), d.second);
				oss << " " << d.first << "#1))";
			}
			std::string math = oss.str();
			return Insert(uuid, name.c_str(), math.c_str());
		}
		// LHS: dx/dt = ...
		assert(lhs.which() == kExprIsCompound);
		const Compound &c(boost::get<Compound>(lhs));
		assert(c.children.size() == 2);
		const Expr &e(c.children.at(1));
		assert(e.which() == kExprIsString);
		id = boost::get<std::string>(e);
		oss << id << "#0";
		std::string name = oss.str();
		oss.str("");
		oss << "(plus " << id << " (times @dt ";
		boost::apply_visitor(Printer(&oss), rhs);
		oss << "))";
		std::string math = oss.str();
		return Insert(uuid, name.c_str(), math.c_str());
	}

	bool PrintAndInsertWiener(const boost::uuids::uuid &uuid,
							  const Expr &e)
	{
		std::ostringstream oss;
		assert(e.which() == kExprIsString);
		const std::string &id(boost::get<std::string>(e));
		oss << id << "#1";
		std::string name = oss.str();
		if (!Insert(uuid, name.c_str(), "($gauss_variate 0 (root @dt))"))
			return false;
		oss.str("");
		oss << id << "#0";
		name = oss.str();
		oss.str("");
		oss << "(plus " << id << " " << id << "#1)";
		std::string math = oss.str();
		return Insert(uuid, name.c_str(), math.c_str());
	}
};

}

bool EulerMaruyama(sqlite3 *db, const char *input, sqlite3 *output)
{
	return Parse<2, EquationLexer, EquationGrammar, Inserter>(db, input, output);
}

}
}
<|endoftext|>