<commit_before>/***************************************************************************
 *   Copyright (C) 2006 by FThauer FHammer   *
 *   f.thauer@web.de   *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/

#include <boost/asio.hpp>
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <qapplication.h>
#include <QtGui>
#include <QtCore>

#ifdef __APPLE__
	#include <QMacStyle>
#endif

#include <curl/curl.h>

#include "session.h"
#include "startwindowimpl.h"
#include "configfile.h"
#include "startsplash.h"
#include "game_defs.h"
#include <net/socket_startup.h>
#include <third_party/qtsingleapplication/qtsingleapplication.h>

#ifdef _MSC_VER
	#ifdef _DEBUG
		#define _CRTDBG_MAP_ALLOC
		#include <crtdbg.h>

		#define ENABLE_LEAK_CHECK() \
			{ \
				int tmpFlag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG); \
				tmpFlag |= _CRTDBG_LEAK_CHECK_DF; \
				_CrtSetDbgFlag(tmpFlag); \
			}
	#endif
#endif

#ifndef ENABLE_LEAK_CHECK
	#define ENABLE_LEAK_CHECK()
#endif

//Uncomment this for RELEASE on Linux/Unix/BSD (static Qt only)
//#include <QtPlugin>
//Q_IMPORT_PLUGIN(qjpeg)
//Q_IMPORT_PLUGIN(qgif)

#ifdef _WIN32 // Always use static Qt on Windows.
#include <QtPlugin>
Q_IMPORT_PLUGIN(qjpeg)
Q_IMPORT_PLUGIN(qgif)
#endif

using namespace std;

class startWindowImpl;
class Game;

int main( int argc, char **argv )
{

	//ENABLE_LEAK_CHECK();

	//_CrtSetBreakAlloc(49937);
	socket_startup();
	curl_global_init(CURL_GLOBAL_NOTHING);

	/////// can be removed for non-qt-guis ////////////
	QApplication a( argc, argv );

	/*if (a.sendMessage("Wake up!")) {
		return 0;
	}*/

#ifdef __APPLE__
	// The following needs to be done directly after the application is created.
	QDir dir(QApplication::applicationDirPath());
	dir.cdUp();
	dir.cd("plugins");
	QApplication::setLibraryPaths(QStringList(dir.absolutePath()));
#endif

	//create defaultconfig
	ConfigFile *myConfig = new ConfigFile(argv[0], false);

	// set PlastiqueStyle even for mac-version to prevent artefacts on styled widgets
        a.setStyle(new QPlastiqueStyle);

	QString	myAppDataPath = QString::fromUtf8(myConfig->readConfigString("AppDataDir").c_str());
	//set QApplication default font

	QFontDatabase::addApplicationFont (myAppDataPath +"fonts/n019003l.pfb");
	QFontDatabase::addApplicationFont (myAppDataPath +"fonts/VeraBd.ttf");
	QFontDatabase::addApplicationFont (myAppDataPath +"fonts/c059013l.pfb");

#ifdef _WIN32
        QString font1String("QApplication, QWidget, QDialog { font-size: 12px; }");
#else
        #ifdef __APPLE__
//            QString font1String("font-family: \"Lucida Grande\";");
            QString font1String("QApplication, QWidget, QDialog { font-size: 11px; }");
        #else
            QString font1String("QApplication, QWidget, QDialog { font-family: \"Nimbus Sans L\"; font-size: 12px; }");
        #endif
#endif
        a.setStyleSheet(font1String + " QDialogButtonBox, QMessageBox { dialogbuttonbox-buttons-have-icons: 1; dialog-ok-icon: url(:/gfx/dialog_ok_apply.png); dialog-cancel-icon: url(:/gfx/dialog_close.png); dialog-close-icon: url(:/gfx/dialog_close.png); dialog-yes-icon: url(:/gfx/dialog_ok_apply.png); dialog-no-icon: url(:/gfx/dialog_close.png) }");

	QPixmap *pixmap = new QPixmap(myAppDataPath + "gfx/gui/misc/welcomepokerth.png");
	StartSplash splash(*pixmap);
	if(!myConfig->readConfigInt("DisableSplashScreenOnStartup")) {
		splash.show();
		splash.showMessage(QString("Version %1").arg(POKERTH_BETA_RELEASE_STRING), 0x0042, QColor(153,213,0));
	}

	//Set translations
	QTranslator qtTranslator;
        qtTranslator.load(QString(myAppDataPath +"translations/qt_") + QString::fromStdString(myConfig->readConfigString("Language")));
        a.installTranslator(&qtTranslator);

	QTranslator translator;
	translator.load(QString(myAppDataPath +"translations/pokerth_") + QString::fromStdString(myConfig->readConfigString("Language")));
	a.installTranslator(&translator);

	qRegisterMetaType<unsigned>("unsigned");
	qRegisterMetaType<boost::shared_ptr<Game> >("boost::shared_ptr<Game>");
	qRegisterMetaType<ServerStats>("ServerStats");
        qRegisterMetaType<DenyGameInvitationReason>("DenyGameInvitationReason");
	///////////////////////////////////////////////////

        startWindowImpl mainWin(myConfig);
        //a.setActivationWindow(&mainWin, true);

	int retVal = a.exec();

	curl_global_cleanup();
	socket_cleanup();

	return retVal;

}
<commit_msg>Fix qtsingleapplication.<commit_after>/***************************************************************************
 *   Copyright (C) 2006 by FThauer FHammer   *
 *   f.thauer@web.de   *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/

#include <boost/asio.hpp>
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <qapplication.h>
#include <QtGui>
#include <QtCore>

#ifdef __APPLE__
	#include <QMacStyle>
#endif

#include <curl/curl.h>

#include "session.h"
#include "startwindowimpl.h"
#include "configfile.h"
#include "startsplash.h"
#include "game_defs.h"
#include <net/socket_startup.h>
#include <third_party/qtsingleapplication/qtsingleapplication.h>

#ifdef _MSC_VER
	#ifdef _DEBUG
		#define _CRTDBG_MAP_ALLOC
		#include <crtdbg.h>

		#define ENABLE_LEAK_CHECK() \
			{ \
				int tmpFlag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG); \
				tmpFlag |= _CRTDBG_LEAK_CHECK_DF; \
				_CrtSetDbgFlag(tmpFlag); \
			}
	#endif
#endif

#ifndef ENABLE_LEAK_CHECK
	#define ENABLE_LEAK_CHECK()
#endif

//Uncomment this for RELEASE on Linux/Unix/BSD (static Qt only)
//#include <QtPlugin>
//Q_IMPORT_PLUGIN(qjpeg)
//Q_IMPORT_PLUGIN(qgif)

#ifdef _WIN32 // Always use static Qt on Windows.
#include <QtPlugin>
Q_IMPORT_PLUGIN(qjpeg)
Q_IMPORT_PLUGIN(qgif)
#endif

using namespace std;

class startWindowImpl;
class Game;

int main( int argc, char **argv )
{

	//ENABLE_LEAK_CHECK();

	//_CrtSetBreakAlloc(49937);
	socket_startup();
	curl_global_init(CURL_GLOBAL_NOTHING);

	/////// can be removed for non-qt-guis ////////////
	QtSingleApplication a( argc, argv );

	if (a.sendMessage("Wake up!")) {
		return 0;
	}

#ifdef __APPLE__
	// The following needs to be done directly after the application is created.
	QDir dir(QApplication::applicationDirPath());
	dir.cdUp();
	dir.cd("plugins");
	QApplication::setLibraryPaths(QStringList(dir.absolutePath()));
#endif

	//create defaultconfig
	ConfigFile *myConfig = new ConfigFile(argv[0], false);

	// set PlastiqueStyle even for mac-version to prevent artefacts on styled widgets
        a.setStyle(new QPlastiqueStyle);

	QString	myAppDataPath = QString::fromUtf8(myConfig->readConfigString("AppDataDir").c_str());
	//set QApplication default font

	QFontDatabase::addApplicationFont (myAppDataPath +"fonts/n019003l.pfb");
	QFontDatabase::addApplicationFont (myAppDataPath +"fonts/VeraBd.ttf");
	QFontDatabase::addApplicationFont (myAppDataPath +"fonts/c059013l.pfb");

#ifdef _WIN32
        QString font1String("QApplication, QWidget, QDialog { font-size: 12px; }");
#else
        #ifdef __APPLE__
//            QString font1String("font-family: \"Lucida Grande\";");
            QString font1String("QApplication, QWidget, QDialog { font-size: 11px; }");
        #else
            QString font1String("QApplication, QWidget, QDialog { font-family: \"Nimbus Sans L\"; font-size: 12px; }");
        #endif
#endif
        a.setStyleSheet(font1String + " QDialogButtonBox, QMessageBox { dialogbuttonbox-buttons-have-icons: 1; dialog-ok-icon: url(:/gfx/dialog_ok_apply.png); dialog-cancel-icon: url(:/gfx/dialog_close.png); dialog-close-icon: url(:/gfx/dialog_close.png); dialog-yes-icon: url(:/gfx/dialog_ok_apply.png); dialog-no-icon: url(:/gfx/dialog_close.png) }");

	QPixmap *pixmap = new QPixmap(myAppDataPath + "gfx/gui/misc/welcomepokerth.png");
	StartSplash splash(*pixmap);
	if(!myConfig->readConfigInt("DisableSplashScreenOnStartup")) {
		splash.show();
		splash.showMessage(QString("Version %1").arg(POKERTH_BETA_RELEASE_STRING), 0x0042, QColor(153,213,0));
	}

	//Set translations
	QTranslator qtTranslator;
        qtTranslator.load(QString(myAppDataPath +"translations/qt_") + QString::fromStdString(myConfig->readConfigString("Language")));
        a.installTranslator(&qtTranslator);

	QTranslator translator;
	translator.load(QString(myAppDataPath +"translations/pokerth_") + QString::fromStdString(myConfig->readConfigString("Language")));
	a.installTranslator(&translator);

	qRegisterMetaType<unsigned>("unsigned");
	qRegisterMetaType<boost::shared_ptr<Game> >("boost::shared_ptr<Game>");
	qRegisterMetaType<ServerStats>("ServerStats");
        qRegisterMetaType<DenyGameInvitationReason>("DenyGameInvitationReason");
	///////////////////////////////////////////////////

        startWindowImpl mainWin(myConfig);
		a.setActivationWindow(&mainWin, true);

	int retVal = a.exec();

	curl_global_cleanup();
	socket_cleanup();

	return retVal;

}
<|endoftext|>


<commit_before>#include "musicnetworktestwidget.h"
#include "ui_musicnetworktestwidget.h"
#include "musicbgthememanager.h"
#include "musicuiobject.h"
#include "musicnetworktestthread.h"
#include "musicutils.h"
#include "musicdatadownloadthread.h"
#include "musicmessagebox.h"

MusicNetworkTestWidget::MusicNetworkTestWidget(QWidget *parent)
    : MusicAbstractMoveDialog(parent),
      ui(new Ui::MusicNetworkTestWidget), m_thead(nullptr), m_testDownload(nullptr)
{
    ui->setupUi(this);

    ui->topTitleCloseButton->setIcon(QIcon(":/share/searchclosed"));
    ui->topTitleCloseButton->setStyleSheet(MusicUIObject::MToolButtonStyle03);
    ui->topTitleCloseButton->setCursor(QCursor(Qt::PointingHandCursor));
    ui->topTitleCloseButton->setToolTip(tr("Close"));
    connect(ui->topTitleCloseButton, SIGNAL(clicked()), SLOT(close()));

    m_totalUp = 0;
    m_totalDown = 0;
    m_testAverage = 0;
    ui->speedWidget->setAnimating(false);
    ui->speedWidget->setRatio(50);

    ui->suspensionButton->setStyleSheet(MusicUIObject::MPushButtonStyle06);
    ui->suspensionButton->setCursor(QCursor((Qt::PointingHandCursor)));
    ui->testButton->setStyleSheet(MusicUIObject::MPushButtonStyle06);
    ui->testButton->setCursor(QCursor((Qt::PointingHandCursor)));
    connect(ui->suspensionButton, SIGNAL(clicked()), SLOT(suspensionOpen()));
    connect(ui->testButton, SIGNAL(clicked()), SLOT(networkTestStart()));

    m_thead = new MusicNetworkTestThread(this);
    connect(m_thead, SIGNAL(networkData(ulong,ulong)), SLOT(networkData(ulong,ulong)));
    m_thead->start();

    m_testTimer.setInterval(5*1000);
    connect(&m_testTimer, SIGNAL(timeout()), SLOT(networkTestStop()));
}

MusicNetworkTestWidget::~MusicNetworkTestWidget()
{
    m_testTimer.stop();
    m_thead->stopAndQuitThread();
    delete m_thead;
    delete m_testDownload;
    delete ui;
}

void MusicNetworkTestWidget::networkData(ulong upload, ulong download)
{
    m_totalUp += upload/5;
    m_totalDown += download/5;

    ui->uploadSpeedValue->setText(MusicUtils::speed2Label(upload));
    ui->downloadSpeedValue->setText(MusicUtils::speed2Label(download));
    ui->uploadAllSpeedValue->setText(MusicUtils::speed2Label(m_totalUp));
    ui->downloadAllSpeedValue->setText(MusicUtils::speed2Label(m_totalDown));

    if(m_testTimer.isActive())
    {
        int value = MusicUtils::sizeByte2KByte(download/5);
        if(value > 100*ui->speedWidget->ratio())
        {
            value = 100*ui->speedWidget->ratio();
        }
        m_testAverage += value;
        ui->speedWidget->setValue(value);
    }
}

void MusicNetworkTestWidget::suspensionOpen()
{

}

void MusicNetworkTestWidget::networkTestStart()
{
    ui->testButton->setEnabled(false);
    m_testTimer.stop();
    delete m_testDownload;
    m_testDownload = new MusicDataDownloadThread(testUrl, testName,
                             MusicDownLoadThreadAbstract::Download_BigBG, this);
    m_testDownload->startToDownload();
    m_testTimer.start();
}

void MusicNetworkTestWidget::networkTestStop()
{
    delete m_testDownload;
    m_testDownload = NULL;
    m_testTimer.stop();
    ///remove temp file
    QFile::remove(testName);
    ui->testButton->setEnabled(true);

    MusicMessageBox message(this);
    message.setText(tr("Average is %1 kb/s").arg(m_testAverage/5));
    message.exec();
}

int MusicNetworkTestWidget::exec()
{
    QPixmap pix(M_BG_MANAGER->getMBackground());
    ui->background->setPixmap(pix.scaled( size() ));
    return MusicAbstractMoveDialog::exec();
}
<commit_msg>reset average flag to zero[564982]<commit_after>#include "musicnetworktestwidget.h"
#include "ui_musicnetworktestwidget.h"
#include "musicbgthememanager.h"
#include "musicuiobject.h"
#include "musicnetworktestthread.h"
#include "musicutils.h"
#include "musicdatadownloadthread.h"
#include "musicmessagebox.h"

MusicNetworkTestWidget::MusicNetworkTestWidget(QWidget *parent)
    : MusicAbstractMoveDialog(parent),
      ui(new Ui::MusicNetworkTestWidget), m_thead(nullptr), m_testDownload(nullptr)
{
    ui->setupUi(this);

    ui->topTitleCloseButton->setIcon(QIcon(":/share/searchclosed"));
    ui->topTitleCloseButton->setStyleSheet(MusicUIObject::MToolButtonStyle03);
    ui->topTitleCloseButton->setCursor(QCursor(Qt::PointingHandCursor));
    ui->topTitleCloseButton->setToolTip(tr("Close"));
    connect(ui->topTitleCloseButton, SIGNAL(clicked()), SLOT(close()));

    m_totalUp = 0;
    m_totalDown = 0;
    m_testAverage = 0;
    ui->speedWidget->setAnimating(false);
    ui->speedWidget->setRatio(50);

    ui->suspensionButton->setStyleSheet(MusicUIObject::MPushButtonStyle06);
    ui->suspensionButton->setCursor(QCursor((Qt::PointingHandCursor)));
    ui->testButton->setStyleSheet(MusicUIObject::MPushButtonStyle06);
    ui->testButton->setCursor(QCursor((Qt::PointingHandCursor)));
    connect(ui->suspensionButton, SIGNAL(clicked()), SLOT(suspensionOpen()));
    connect(ui->testButton, SIGNAL(clicked()), SLOT(networkTestStart()));

    m_thead = new MusicNetworkTestThread(this);
    connect(m_thead, SIGNAL(networkData(ulong,ulong)), SLOT(networkData(ulong,ulong)));
    m_thead->start();

    m_testTimer.setInterval(5*1000);
    connect(&m_testTimer, SIGNAL(timeout()), SLOT(networkTestStop()));
}

MusicNetworkTestWidget::~MusicNetworkTestWidget()
{
    m_testTimer.stop();
    m_thead->stopAndQuitThread();
    delete m_thead;
    delete m_testDownload;
    delete ui;
}

void MusicNetworkTestWidget::networkData(ulong upload, ulong download)
{
    m_totalUp += upload/5;
    m_totalDown += download/5;

    ui->uploadSpeedValue->setText(MusicUtils::speed2Label(upload));
    ui->downloadSpeedValue->setText(MusicUtils::speed2Label(download));
    ui->uploadAllSpeedValue->setText(MusicUtils::speed2Label(m_totalUp));
    ui->downloadAllSpeedValue->setText(MusicUtils::speed2Label(m_totalDown));

    if(m_testTimer.isActive())
    {
        int value = MusicUtils::sizeByte2KByte(download/5);
        if(value > 100*ui->speedWidget->ratio())
        {
            value = 100*ui->speedWidget->ratio();
        }
        m_testAverage += value;
        ui->speedWidget->setValue(value);
    }
}

void MusicNetworkTestWidget::suspensionOpen()
{

}

void MusicNetworkTestWidget::networkTestStart()
{
    ui->testButton->setEnabled(false);
    m_testTimer.stop();
    delete m_testDownload;
    m_testDownload = new MusicDataDownloadThread(testUrl, testName,
                             MusicDownLoadThreadAbstract::Download_BigBG, this);
    m_testDownload->startToDownload();
    m_testTimer.start();
}

void MusicNetworkTestWidget::networkTestStop()
{
    m_testAverage = 0;
    delete m_testDownload;
    m_testDownload = NULL;
    m_testTimer.stop();
    ///remove temp file
    QFile::remove(testName);
    ui->testButton->setEnabled(true);

    MusicMessageBox message(this);
    message.setText(tr("Average is %1 kb/s").arg(m_testAverage/5));
    message.exec();
}

int MusicNetworkTestWidget::exec()
{
    QPixmap pix(M_BG_MANAGER->getMBackground());
    ui->background->setPixmap(pix.scaled( size() ));
    return MusicAbstractMoveDialog::exec();
}
<|endoftext|>


<commit_before>/*
* Copyright (C) 2019 German Aerospace Center (DLR/SC)
*
* Created: 2019-05-14 Martin Siggel <Martin.Siggel@dlr.de> with Marko Alder <Marko.Alder@dlr.de>
*
* 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 "CCPACSFuselageWallSegment.h"
#include "generated/CPACSWallSegments.h"
#include "generated/CPACSWalls.h"
#include "CCPACSFuselageStructure.h"
#include "CCPACSFuselage.h"
#include "CCPACSFuselageSegment.h"
#include "CNamedShape.h"
#include "CCPACSWallPosition.h"
#include "CTiglUIDManager.h"
#include "tiglcommonfunctions.h"
#include "to_string.h"

#include <Bnd_Box.hxx>
#include <BRepBndLib.hxx>
#include <BRep_Tool.hxx>
#include <BRepBuilderAPI_MakeEdge.hxx>
#include <BRepBuilderAPI_MakeWire.hxx>
#include <BRepBuilderAPI_MakeFace.hxx>
#include <TopExp_Explorer.hxx>
#include <TopoDS.hxx>
#include <GeomLib_IsPlanarSurface.hxx>
#include <IntCurvesFace_ShapeIntersector.hxx>
#include <TopTools_IndexedMapOfShape.hxx>
#include <TopExp.hxx>
#include <gp_Ax3.hxx>
#include <gp_Pln.hxx>

#include <algorithm>

namespace {

// create a face out of four points
TopoDS_Face MakeFace(gp_Pnt const& p1, gp_Pnt const& p2, gp_Pnt const& p3, gp_Pnt const& p4) {
    TopoDS_Edge e1 = BRepBuilderAPI_MakeEdge(p1, p2).Edge();
    TopoDS_Edge e2 = BRepBuilderAPI_MakeEdge(p2, p3).Edge();
    TopoDS_Edge e3 = BRepBuilderAPI_MakeEdge(p3, p4).Edge();
    TopoDS_Edge e4 = BRepBuilderAPI_MakeEdge(p4, p1).Edge();
    TopoDS_Wire w = BRepBuilderAPI_MakeWire(e1, e2, e3, e4).Wire();
    return BRepBuilderAPI_MakeFace(w, false).Face();
}

// Given a CCPACSWallposition with a defined shape, project the point pnt along the direction dir onto the
// plane, in which the shape lies. The shape must be convertable to a planar TopoDS_Face.
void FlushPointAlongVec(tigl::CCPACSWallPosition const& p, gp_Vec const dir, double extents, gp_Pnt& pnt)
{
    if (!p.GetShape()) {
        throw tigl::CTiglError("Cannot flush point for wall position without shape definition.");
    }
    gp_Pln pln;
    TopoDS_Shape shape = *p.GetShape();
    Handle(Geom_Surface) surf = BRep_Tool::Surface(TopoDS::Face(*p.GetShape()));
    GeomLib_IsPlanarSurface surf_check(surf);
    if (surf_check.IsPlanar()) {
        pln = surf_check.Plan();
    }
    else {
        throw tigl::CTiglError("Cannot flush point at non-planar surface");
    }

    pln.SetLocation(p.GetBasePoint());
    TopoDS_Face face = BRepBuilderAPI_MakeFace(pln);
    TopoDS_Edge edge = BRepBuilderAPI_MakeEdge(pnt.Translated( dir*extents),
                                               pnt.Translated(-dir*extents)).Edge();
    GetIntersectionPoint(face, edge, pnt);
}

}

namespace tigl
{

CCPACSFuselageWallSegment::CCPACSFuselageWallSegment(CCPACSWallSegments* parent, tigl::CTiglUIDManager *uidMgr)
    : generated::CPACSWallSegment(parent, uidMgr)
{
}

TopoDS_Compound CCPACSFuselageWallSegment::GetCutPlanes() const
{
    // Makes sure, that the cut planes are already computed
    if (m_cutPlanes.IsNull()) {
        BuildLoft();
    }
    return m_cutPlanes;
}

const CCPACSWalls& CCPACSFuselageWallSegment::GetWalls() const
{
    const CCPACSWallSegments* wallSegments = GetParent();
    if (!wallSegments) {
        throw CTiglError("Error in CCPACSFuselageWallSegment::GetWalls. Null pointer returned.", TIGL_NULL_POINTER);
    }

    const CCPACSWalls* walls = wallSegments->GetParent();
    if (!walls) {
        throw CTiglError("Error in CCPACSFuselageWallSegment::GetWalls. Null pointer returned.", TIGL_NULL_POINTER);
    }

    return *walls;
}

const CCPACSFuselage &CCPACSFuselageWallSegment::GetFuselage() const
{
    const CCPACSWalls& walls = GetWalls();

    const CCPACSFuselageStructure* fuselageStructure = walls.GetParent();
    if (!fuselageStructure) {
        throw CTiglError("Cannot get fuselage in CCPACSFuselageWallSegment::GetFuselage. Null pointer parent.", TIGL_NULL_POINTER);
    }

    const CCPACSFuselage* fuselage = fuselageStructure->GetParent();
    if (!fuselageStructure) {
        throw CTiglError("Cannot get fuselage in CCPACSFuselageWallSegment::GetFuselage. Null pointer parent.", TIGL_NULL_POINTER);
    }

    return *fuselage;
}

PNamedShape CCPACSFuselageWallSegment::BuildLoft() const
{
    // A bounding box is created to use its diagonal as reference for the
    // extrusion length (edge length). This ensures that these always go
    //  beyond the model, but do not reach into infinity.
    Bnd_Box boundingBox;
    const CCPACSFuselage& fuselage = GetFuselage();
    TopoDS_Shape fuselageShape = fuselage.GetLoft()->Shape();
    BRepBndLib::Add(fuselageShape, boundingBox);
    double bboxSize = sqrt(boundingBox.SquareExtent());

    size_t nWallPositions = GetWallPositionUIDs().GetWallPositionUIDs().size();

    // list with base points:
    std::vector<gp_Pnt> base_pnts;
    base_pnts.reserve(nWallPositions);

    // extrusion in negative direction is realized by setting u_neg to
    // -bboxSize:
    bool negativeExtrusion = GetNegativeExtrusion().value_or(false);
    double u_pos = bboxSize;
    double u_neg = 0.;
    if (negativeExtrusion) {
        u_neg = -bboxSize;
    }

    gp_Pnt upper, lower;   // upper and lower extrusion points for each base point
    gp_Vec x_vec;          // vector from one base point to the next

    // build for untrimmed wall
    TopoDS_Builder builder_wall, builder_cutter;
    TopoDS_Compound wall;
    builder_wall.MakeCompound(wall);
    builder_cutter.MakeCompound(m_cutPlanes);

    size_t count = 0;
    const auto& walls = GetWalls();
    for (auto wallPositionUID : GetWallPositionUIDs().GetWallPositionUIDs()) {
        const CCPACSWallPosition& p = walls.GetWallPosition(wallPositionUID);

        // get current base point and x_vec pointing from previous base point to current
        gp_Pnt base_point = p.GetBasePoint();
        if ( count > 0 ) {
            x_vec = gp_Vec(base_pnts.back(), base_point);
        }

        // extrusion vector
        double phiRad = Radians(GetPhi());
        gp_Vec ext_vec(0., -sin(phiRad), cos(phiRad));

        if (count==1) {
            // flush first position to shape
            if( p.GetShape() && GetFlushConnectionStart().value_or(false) ) {
                std::string uid_prev = GetWallPositionUIDs().GetWallPositionUIDs().front();
                const CCPACSWallPosition& p_prev = walls.GetWallPosition(uid_prev);
                FlushPointAlongVec(p_prev, x_vec, bboxSize, upper);
                FlushPointAlongVec(p_prev, x_vec, bboxSize, lower);
            }
        }

        gp_Pnt upper_new = base_point.Translated(u_pos*ext_vec);
        gp_Pnt lower_new = base_point.Translated(u_neg*ext_vec);

        if (count==nWallPositions-1) {
            // flush last position to shape
            if( p.GetShape() && GetFlushConnectionEnd().value_or(false) ) {
                FlushPointAlongVec(p, x_vec, bboxSize, upper_new);
                FlushPointAlongVec(p, x_vec, bboxSize, lower_new);
            }
        }

        // create the wall segment from the four corner points lower, upper, lower_new, upper_new
        if (count > 0 ) {
            TopoDS_Face face = MakeFace(lower, lower_new, upper_new, upper);
            builder_wall.Add(wall, face);

            //first and last face are enlarged for the cutting tool
            gp_Pnt lower_cut = lower;
            gp_Pnt upper_cut = upper;
            gp_Pnt lower_new_cut = lower_new;
            gp_Pnt upper_new_cut = upper_new;
            if (count==1) {
                lower_cut = lower.Translated(-bboxSize*x_vec);
                upper_cut = upper.Translated(-bboxSize*x_vec);
            }
            if (count==nWallPositions-1) {
                lower_new_cut = lower_new.Translated(bboxSize*x_vec);
                upper_new_cut = upper_new.Translated(bboxSize*x_vec);
            }
            face = MakeFace(lower_cut, lower_new_cut, upper_new_cut, upper_cut);
            builder_cutter.Add(m_cutPlanes, face);
        }

        // store base_pnts and remember current lower and upper point for next position
        base_pnts.push_back(base_point);
        upper = upper_new;
        lower = lower_new;
        ++count;
    }

    // trim the wall
    // Step 1/2: Trim the wall by the fuselage
    {
        TopoDS_Compound cut_wall;
        builder_wall.MakeCompound(cut_wall);

        TopoDS_Shape result = SplitShape(wall, fuselageShape);
        TopTools_IndexedMapOfShape faceMap;
        TopExp::MapShapes(result, TopAbs_FACE, faceMap);
        for (int i = 0; i < faceMap.Extent(); ++i) {
            TopoDS_Face face = TopoDS::Face(faceMap(i+1));
            gp_Pnt faceCenter = GetCentralFacePoint(face);
            // TODO: This is fast but could be potentially dangerous.
            // Maybe we should check if the point is outside the fuselage
            // shape rather than the bounding box.
            if (!boundingBox.IsOut(faceCenter)) {
                builder_wall.Add(cut_wall, face);
            }
        }
        wall = cut_wall;
    }

    // Step 2/2: Cut the wall with bounding elements:
    if (GetBoundingElementUIDs()) {
        for (std::string bounding_element_uid : GetBoundingElementUIDs()->GetBoundingElementUIDs()) {
            const CCPACSFuselageWallSegment& bounding_element = GetWalls().GetWallSegment(bounding_element_uid);
            // TODO: Check: The order of whoch the walls are evaulated seem to matter here!
            TopoDS_Compound bounding_cutPlane = bounding_element.GetCutPlanes();
            TopoDS_Shape result = SplitShape(wall, bounding_cutPlane);

            TopoDS_Compound cut_wall;
            builder_wall.MakeCompound(cut_wall);
            TopTools_IndexedMapOfShape faceMap;
            TopExp::MapShapes(result, TopAbs_FACE, faceMap);

            // Loop over the split faces and check weather one of the
            // base points belongs to the face.
            for (int i = 0; i <faceMap.Extent(); ++i) {
                TopoDS_Face face = TopoDS::Face(faceMap(i+1));
                for (auto point : base_pnts) {
                    if ( IsPointInsideFace(face, point) ) {
                        builder_wall.Add(cut_wall,face);
                        break;
                    }
                }
            }
            wall = cut_wall;
        } // loop over bounding elements
    } // if has bounding elements

    return PNamedShape(new CNamedShape(wall, GetDefaultedUID()));
}

} // namespace tigl
<commit_msg>classify point using fuselage shape not bounding box<commit_after>/*
* Copyright (C) 2019 German Aerospace Center (DLR/SC)
*
* Created: 2019-05-14 Martin Siggel <Martin.Siggel@dlr.de> with Marko Alder <Marko.Alder@dlr.de>
*
* 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 "CCPACSFuselageWallSegment.h"
#include "generated/CPACSWallSegments.h"
#include "generated/CPACSWalls.h"
#include "CCPACSFuselageStructure.h"
#include "CCPACSFuselage.h"
#include "CCPACSFuselageSegment.h"
#include "CNamedShape.h"
#include "CCPACSWallPosition.h"
#include "CTiglUIDManager.h"
#include "tiglcommonfunctions.h"
#include "to_string.h"

#include <Bnd_Box.hxx>
#include <BRepBndLib.hxx>
#include <BRep_Tool.hxx>
#include <BRepBuilderAPI_MakeEdge.hxx>
#include <BRepBuilderAPI_MakeWire.hxx>
#include <BRepBuilderAPI_MakeFace.hxx>
#include <TopExp_Explorer.hxx>
#include <TopoDS.hxx>
#include <GeomLib_IsPlanarSurface.hxx>
#include <IntCurvesFace_ShapeIntersector.hxx>
#include <TopTools_IndexedMapOfShape.hxx>
#include <TopExp.hxx>
#include <gp_Ax3.hxx>
#include <gp_Pln.hxx>
#include <BRepClass3d_SolidClassifier.hxx>

#include <algorithm>

namespace {

// create a face out of four points
TopoDS_Face MakeFace(gp_Pnt const& p1, gp_Pnt const& p2, gp_Pnt const& p3, gp_Pnt const& p4) {
    TopoDS_Edge e1 = BRepBuilderAPI_MakeEdge(p1, p2).Edge();
    TopoDS_Edge e2 = BRepBuilderAPI_MakeEdge(p2, p3).Edge();
    TopoDS_Edge e3 = BRepBuilderAPI_MakeEdge(p3, p4).Edge();
    TopoDS_Edge e4 = BRepBuilderAPI_MakeEdge(p4, p1).Edge();
    TopoDS_Wire w = BRepBuilderAPI_MakeWire(e1, e2, e3, e4).Wire();
    return BRepBuilderAPI_MakeFace(w, false).Face();
}

// Given a CCPACSWallposition with a defined shape, project the point pnt along the direction dir onto the
// plane, in which the shape lies. The shape must be convertable to a planar TopoDS_Face.
void FlushPointAlongVec(tigl::CCPACSWallPosition const& p, gp_Vec const dir, double extents, gp_Pnt& pnt)
{
    if (!p.GetShape()) {
        throw tigl::CTiglError("Cannot flush point for wall position without shape definition.");
    }
    gp_Pln pln;
    TopoDS_Shape shape = *p.GetShape();
    Handle(Geom_Surface) surf = BRep_Tool::Surface(TopoDS::Face(*p.GetShape()));
    GeomLib_IsPlanarSurface surf_check(surf);
    if (surf_check.IsPlanar()) {
        pln = surf_check.Plan();
    }
    else {
        throw tigl::CTiglError("Cannot flush point at non-planar surface");
    }

    pln.SetLocation(p.GetBasePoint());
    TopoDS_Face face = BRepBuilderAPI_MakeFace(pln);
    TopoDS_Edge edge = BRepBuilderAPI_MakeEdge(pnt.Translated( dir*extents),
                                               pnt.Translated(-dir*extents)).Edge();
    GetIntersectionPoint(face, edge, pnt);
}

}

namespace tigl
{

CCPACSFuselageWallSegment::CCPACSFuselageWallSegment(CCPACSWallSegments* parent, tigl::CTiglUIDManager *uidMgr)
    : generated::CPACSWallSegment(parent, uidMgr)
{
}

TopoDS_Compound CCPACSFuselageWallSegment::GetCutPlanes() const
{
    // Makes sure, that the cut planes are already computed
    if (m_cutPlanes.IsNull()) {
        BuildLoft();
    }
    return m_cutPlanes;
}

const CCPACSWalls& CCPACSFuselageWallSegment::GetWalls() const
{
    const CCPACSWallSegments* wallSegments = GetParent();
    if (!wallSegments) {
        throw CTiglError("Error in CCPACSFuselageWallSegment::GetWalls. Null pointer returned.", TIGL_NULL_POINTER);
    }

    const CCPACSWalls* walls = wallSegments->GetParent();
    if (!walls) {
        throw CTiglError("Error in CCPACSFuselageWallSegment::GetWalls. Null pointer returned.", TIGL_NULL_POINTER);
    }

    return *walls;
}

const CCPACSFuselage &CCPACSFuselageWallSegment::GetFuselage() const
{
    const CCPACSWalls& walls = GetWalls();

    const CCPACSFuselageStructure* fuselageStructure = walls.GetParent();
    if (!fuselageStructure) {
        throw CTiglError("Cannot get fuselage in CCPACSFuselageWallSegment::GetFuselage. Null pointer parent.", TIGL_NULL_POINTER);
    }

    const CCPACSFuselage* fuselage = fuselageStructure->GetParent();
    if (!fuselageStructure) {
        throw CTiglError("Cannot get fuselage in CCPACSFuselageWallSegment::GetFuselage. Null pointer parent.", TIGL_NULL_POINTER);
    }

    return *fuselage;
}

PNamedShape CCPACSFuselageWallSegment::BuildLoft() const
{
    // A bounding box is created to use its diagonal as reference for the
    // extrusion length (edge length). This ensures that these always go
    //  beyond the model, but do not reach into infinity.
    Bnd_Box boundingBox;
    const CCPACSFuselage& fuselage = GetFuselage();
    TopoDS_Shape fuselageShape = fuselage.GetLoft()->Shape();
    BRepBndLib::Add(fuselageShape, boundingBox);
    double bboxSize = sqrt(boundingBox.SquareExtent());

    size_t nWallPositions = GetWallPositionUIDs().GetWallPositionUIDs().size();

    // list with base points:
    std::vector<gp_Pnt> base_pnts;
    base_pnts.reserve(nWallPositions);

    // extrusion in negative direction is realized by setting u_neg to
    // -bboxSize:
    bool negativeExtrusion = GetNegativeExtrusion().value_or(false);
    double u_pos = bboxSize;
    double u_neg = 0.;
    if (negativeExtrusion) {
        u_neg = -bboxSize;
    }

    gp_Pnt upper, lower;   // upper and lower extrusion points for each base point
    gp_Vec x_vec;          // vector from one base point to the next

    // build for untrimmed wall
    TopoDS_Builder builder_wall, builder_cutter;
    TopoDS_Compound wall;
    builder_wall.MakeCompound(wall);
    builder_cutter.MakeCompound(m_cutPlanes);

    size_t count = 0;
    const auto& walls = GetWalls();
    for (auto wallPositionUID : GetWallPositionUIDs().GetWallPositionUIDs()) {
        const CCPACSWallPosition& p = walls.GetWallPosition(wallPositionUID);

        // get current base point and x_vec pointing from previous base point to current
        gp_Pnt base_point = p.GetBasePoint();
        if ( count > 0 ) {
            x_vec = gp_Vec(base_pnts.back(), base_point);
        }

        // extrusion vector
        double phiRad = Radians(GetPhi());
        gp_Vec ext_vec(0., -sin(phiRad), cos(phiRad));

        if (count==1) {
            // flush first position to shape
            if( p.GetShape() && GetFlushConnectionStart().value_or(false) ) {
                std::string uid_prev = GetWallPositionUIDs().GetWallPositionUIDs().front();
                const CCPACSWallPosition& p_prev = walls.GetWallPosition(uid_prev);
                FlushPointAlongVec(p_prev, x_vec, bboxSize, upper);
                FlushPointAlongVec(p_prev, x_vec, bboxSize, lower);
            }
        }

        gp_Pnt upper_new = base_point.Translated(u_pos*ext_vec);
        gp_Pnt lower_new = base_point.Translated(u_neg*ext_vec);

        if (count==nWallPositions-1) {
            // flush last position to shape
            if( p.GetShape() && GetFlushConnectionEnd().value_or(false) ) {
                FlushPointAlongVec(p, x_vec, bboxSize, upper_new);
                FlushPointAlongVec(p, x_vec, bboxSize, lower_new);
            }
        }

        // create the wall segment from the four corner points lower, upper, lower_new, upper_new
        if (count > 0 ) {
            TopoDS_Face face = MakeFace(lower, lower_new, upper_new, upper);
            builder_wall.Add(wall, face);

            //first and last face are enlarged for the cutting tool
            gp_Pnt lower_cut = lower;
            gp_Pnt upper_cut = upper;
            gp_Pnt lower_new_cut = lower_new;
            gp_Pnt upper_new_cut = upper_new;
            if (count==1) {
                lower_cut = lower.Translated(-bboxSize*x_vec);
                upper_cut = upper.Translated(-bboxSize*x_vec);
            }
            if (count==nWallPositions-1) {
                lower_new_cut = lower_new.Translated(bboxSize*x_vec);
                upper_new_cut = upper_new.Translated(bboxSize*x_vec);
            }
            face = MakeFace(lower_cut, lower_new_cut, upper_new_cut, upper_cut);
            builder_cutter.Add(m_cutPlanes, face);
        }

        // store base_pnts and remember current lower and upper point for next position
        base_pnts.push_back(base_point);
        upper = upper_new;
        lower = lower_new;
        ++count;
    }

    // trim the wall
    // Step 1/2: Trim the wall by the fuselage
    {
        TopoDS_Compound cut_wall;
        builder_wall.MakeCompound(cut_wall);

        TopoDS_Shape result = SplitShape(wall, fuselageShape);
        TopTools_IndexedMapOfShape faceMap;
        TopExp::MapShapes(result, TopAbs_FACE, faceMap);
        for (int i = 0; i < faceMap.Extent(); ++i) {
            // check if face center is on the interior of the fuselage
            TopoDS_Face face = TopoDS::Face(faceMap(i+1));
            gp_Pnt faceCenter = GetCentralFacePoint(face);

            BRepClass3d_SolidClassifier clas3d(fuselageShape);
            clas3d.Perform(faceCenter, Precision::Confusion());

            if (clas3d.State() == TopAbs_IN) {
                builder_wall.Add(cut_wall, face);
            }
        }
        wall = cut_wall;
    }

    // Step 2/2: Cut the wall with bounding elements:
    if (GetBoundingElementUIDs()) {
        for (std::string bounding_element_uid : GetBoundingElementUIDs()->GetBoundingElementUIDs()) {
            const CCPACSFuselageWallSegment& bounding_element = GetWalls().GetWallSegment(bounding_element_uid);
            // TODO: Check: The order of whoch the walls are evaulated seem to matter here!
            TopoDS_Compound bounding_cutPlane = bounding_element.GetCutPlanes();
            TopoDS_Shape result = SplitShape(wall, bounding_cutPlane);

            TopoDS_Compound cut_wall;
            builder_wall.MakeCompound(cut_wall);
            TopTools_IndexedMapOfShape faceMap;
            TopExp::MapShapes(result, TopAbs_FACE, faceMap);

            // Loop over the split faces and check weather one of the
            // base points belongs to the face.
            for (int i = 0; i <faceMap.Extent(); ++i) {
                TopoDS_Face face = TopoDS::Face(faceMap(i+1));
                for (auto point : base_pnts) {
                    if ( IsPointInsideFace(face, point) ) {
                        builder_wall.Add(cut_wall,face);
                        break;
                    }
                }
            }
            wall = cut_wall;
        } // loop over bounding elements
    } // if has bounding elements

    return PNamedShape(new CNamedShape(wall, GetDefaultedUID()));
}

} // namespace tigl
<|endoftext|>


<commit_before>#include "Tutorial4ActorModule.h"
#include "NFComm/NFCore/NFTimer.h"
#include <thread>

bool HelloWorld4ActorModule::Init()
{
    //ʼ
    std::cout << "Hello, world4, Init ThreadID: " << std::this_thread::get_id() << std::endl;

    return true;
}

int HelloWorld4ActorModule::OnASyncEvent(const NFIDENTID& self, const int event, std::string& arg)
{
    //¼ص
    std::cout << "Begin OnEvent EventID: " << event << " self: " << self.nData64 << " argList: " << arg << " ThreadID: " << std::this_thread::get_id() << std::endl;

	arg += "  event test ok";

    return 0;
}

int HelloWorld4ActorModule::OnSyncEvent(const NFIDENTID& self, const int event, const std::string& arg)
{
	//¼ص
	std::cout << "End OnEvent EventID: " << event << " self: " << self.nData64 << " argList: " << arg << " ThreadID: " << std::this_thread::get_id() << std::endl;

	return 0;
}

bool HelloWorld4ActorModule::AfterInit()
{

    //ʼ
    std::cout << "Hello, world4, AfterInit, ThreadID: " << GetCurrentThreadId() << std::endl;

    m_pKernelModule = dynamic_cast<NFIKernelModule*>(pPluginManager->FindModule("NFCKernelModule"));
    m_pEventProcessModule = dynamic_cast<NFIEventProcessModule*>(pPluginManager->FindModule("NFCEventProcessModule"));
    m_pElementInfoModule = dynamic_cast<NFIElementInfoModule*>(pPluginManager->FindModule("NFCElementInfoModule"));

	//////////////////////////////////////ͬ/////////////////////////////////////////////////////////////////////
	m_pEventProcessModule->AddAsyncEventCallBack(NFIDENTID(), 2222, this, &HelloWorld4ActorModule::OnASyncEvent, &HelloWorld4ActorModule::OnSyncEvent);

	for (int i = 0; i < 20; ++i)
	{
		m_pEventProcessModule->DoEvent(NFIDENTID(), 2222, NFCDataList() << boost::lexical_cast<std::string>(i), false);

	}

	std::cout << "End Test Actor, ThreadID: " << std::this_thread::get_id() << std::endl;

	///////////////////////////////////////////////////////////////////////////////////////////////////////////

    return true;
}

bool HelloWorld4ActorModule::Execute( const float fLasFrametime, const float fStartedTime )
{
    //ÿִ֡
    //std::cout << "Hello, world3, Execute" << std::endl;

    return true;
}

bool HelloWorld4ActorModule::BeforeShut()
{
    //ʼ֮ǰ
    std::cout << "Hello, world4, BeforeShut" << std::endl;

    m_pKernelModule->DestroyAll();

    return true;
}

bool HelloWorld4ActorModule::Shut()
{
    //ʼ
    std::cout << "Hello, world4, Shut" << std::endl;

    return true;
}
<commit_msg>modify GetCurrentThreadID() as std::this_thread::get_id()<commit_after>#include "Tutorial4ActorModule.h"
#include "NFComm/NFCore/NFTimer.h"
#include <thread>

bool HelloWorld4ActorModule::Init()
{
    //ʼ
    std::cout << "Hello, world4, Init ThreadID: " << std::this_thread::get_id() << std::endl;

    return true;
}

int HelloWorld4ActorModule::OnASyncEvent(const NFIDENTID& self, const int event, std::string& arg)
{
    //¼ص
    std::cout << "Begin OnEvent EventID: " << event << " self: " << self.nData64 << " argList: " << arg << " ThreadID: " << std::this_thread::get_id() << std::endl;

	arg += "  event test ok";

    return 0;
}

int HelloWorld4ActorModule::OnSyncEvent(const NFIDENTID& self, const int event, const std::string& arg)
{
	//¼ص
	std::cout << "End OnEvent EventID: " << event << " self: " << self.nData64 << " argList: " << arg << " ThreadID: " << std::this_thread::get_id() << std::endl;

	return 0;
}

bool HelloWorld4ActorModule::AfterInit()
{

    //ʼ
    std::cout << "Hello, world4, AfterInit, ThreadID: " << std::this_thread::get_id() << std::endl;

    m_pKernelModule = dynamic_cast<NFIKernelModule*>(pPluginManager->FindModule("NFCKernelModule"));
    m_pEventProcessModule = dynamic_cast<NFIEventProcessModule*>(pPluginManager->FindModule("NFCEventProcessModule"));
    m_pElementInfoModule = dynamic_cast<NFIElementInfoModule*>(pPluginManager->FindModule("NFCElementInfoModule"));

	//////////////////////////////////////ͬ/////////////////////////////////////////////////////////////////////
	m_pEventProcessModule->AddAsyncEventCallBack(NFIDENTID(), 2222, this, &HelloWorld4ActorModule::OnASyncEvent, &HelloWorld4ActorModule::OnSyncEvent);

	for (int i = 0; i < 20; ++i)
	{
		m_pEventProcessModule->DoEvent(NFIDENTID(), 2222, NFCDataList() << boost::lexical_cast<std::string>(i), false);

	}

	std::cout << "End Test Actor, ThreadID: " << std::this_thread::get_id() << std::endl;

	///////////////////////////////////////////////////////////////////////////////////////////////////////////

    return true;
}

bool HelloWorld4ActorModule::Execute( const float fLasFrametime, const float fStartedTime )
{
    //ÿִ֡
    //std::cout << "Hello, world3, Execute" << std::endl;

    return true;
}

bool HelloWorld4ActorModule::BeforeShut()
{
    //ʼ֮ǰ
    std::cout << "Hello, world4, BeforeShut" << std::endl;

    m_pKernelModule->DestroyAll();

    return true;
}

bool HelloWorld4ActorModule::Shut()
{
    //ʼ
    std::cout << "Hello, world4, Shut" << std::endl;

    return true;
}
<|endoftext|>


<commit_before>/* Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.

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 "paddle/fluid/operators/reduce_ops/reduce_min_max_op.h"
#include "paddle/fluid/platform/device/npu/npu_op_runner.h"

namespace paddle {
namespace operators {

using Tensor = framework::Tensor;
template <typename DeviceContext, typename T>
class ReduceMaxNPUKernel : public framework::OpKernel<T> {
 public:
  void Compute(const framework::ExecutionContext& ctx) const override {
    auto* x = ctx.Input<Tensor>("X");
    auto* out = ctx.Output<Tensor>("Out");
    auto dims = ctx.Attr<std::vector<int>>("dim");
    bool keep_dim = ctx.Attr<bool>("keep_dim");
    bool reduce_all = ctx.Attr<bool>("reduce_all");
    int out_dtype = ctx.Attr<int>("out_dtype");

    auto place = ctx.GetPlace();

    framework::Tensor cast_out(x->type());
    cast_out.Resize(out->dims());
    cast_out.mutable_data<T>(place);

    auto cast_out_dtype = framework::TransToProtoVarType(x->dtype());
    if (out_dtype != -1) {
      cast_out_dtype = static_cast<framework::proto::VarType::Type>(out_dtype);
    }

    if (framework::TransToProtoVarType(x->dtype()) != cast_out_dtype) {
      if (cast_out_dtype == framework::proto::VarType::FP32) {
        out->mutable_data<float>(place);
      } else if (cast_out_dtype == framework::proto::VarType::FP16) {
        out->mutable_data<paddle::platform::float16>(place);
      } else if (cast_out_dtype == framework::proto::VarType::INT16) {
        out->mutable_data<int16_t>(place);
      } else if (cast_out_dtype == framework::proto::VarType::INT32) {
        out->mutable_data<int32_t>(place);
      } else if (cast_out_dtype == framework::proto::VarType::INT64) {
        out->mutable_data<int64_t>(place);
      } else if (cast_out_dtype == framework::proto::VarType::FP64) {
        out->mutable_data<double>(place);
      } else if (cast_out_dtype == framework::proto::VarType::BOOL) {
        out->mutable_data<bool>(place);
      }
    } else {
      out->ShareDataWith(cast_out);
    }

    framework::NPUAttributeMap attr_input = {{"axes", dims},
                                             {"keep_dims", keep_dim}};

    if (reduce_all) {
      std::vector<int> dim_vec;
      for (int i = 0; i < x->dims().size(); i++) {
        dim_vec.push_back(i);
      }

      attr_input = {{"axes", dim_vec}, {"keep_dims", keep_dim}};
    }

    const auto& dev_ctx =
        ctx.template device_context<paddle::platform::NPUDeviceContext>();
    if (framework::TransToProtoVarType(x->dtype()) ==
        framework::proto::VarType::INT64) {
      auto op_func = [](const std::vector<Tensor>& inputs,
                        const std::vector<Tensor>& outputs,
                        const NPUAttributeMap& attrs,
                        const platform::NPUDeviceContext& dev_ctx) {
        const auto& runner =
            NpuOpRunner("ReduceMaxD", {inputs[0]}, {outputs[0]}, attrs);
        runner.Run(dev_ctx.stream());
      };

      NpuOpRunner::TypeAdapter({*x}, {cast_out}, attr_input, dev_ctx, op_func,
                               {framework::proto::VarType::INT32},
                               {framework::proto::VarType::INT32});
    } else {
      const auto& runner =
          NpuOpRunner("ReduceMaxD", {*x}, {cast_out}, attr_input);
      runner.Run(dev_ctx.stream());
    }

    if (framework::TransToProtoVarType(x->dtype()) != cast_out_dtype) {
      auto dst_dtype = ConvertToNpuDtype(cast_out_dtype);
      const auto& runner_cast =
          NpuOpRunner("Cast", {cast_out}, {*out},
                      {{"dst_type", static_cast<int>(dst_dtype)}});
      runner_cast.Run(dev_ctx.stream());
    }
  }
};

}  // namespace operators
}  // namespace paddle

namespace ops = paddle::operators;
namespace plat = paddle::platform;
REGISTER_OP_NPU_KERNEL(
    reduce_max, ops::ReduceMaxNPUKernel<plat::NPUDeviceContext, float>,
    ops::ReduceMaxNPUKernel<plat::NPUDeviceContext, plat::float16>,
    ops::ReduceMaxNPUKernel<plat::NPUDeviceContext, int64_t>,
    ops::ReduceMaxNPUKernel<plat::NPUDeviceContext, int>);
<commit_msg>[NPU] add reduce_max_grad op (#42672)<commit_after>/* Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.

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 "paddle/fluid/operators/reduce_ops/reduce_min_max_op.h"
#include "paddle/fluid/platform/device/npu/npu_op_runner.h"

namespace paddle {
namespace operators {

using Tensor = framework::Tensor;
template <typename DeviceContext, typename T>
class ReduceMaxNPUKernel : public framework::OpKernel<T> {
 public:
  void Compute(const framework::ExecutionContext& ctx) const override {
    auto* x = ctx.Input<Tensor>("X");
    auto* out = ctx.Output<Tensor>("Out");
    auto dims = ctx.Attr<std::vector<int>>("dim");
    bool keep_dim = ctx.Attr<bool>("keep_dim");
    bool reduce_all = ctx.Attr<bool>("reduce_all");
    int out_dtype = ctx.Attr<int>("out_dtype");

    auto place = ctx.GetPlace();

    framework::Tensor cast_out(x->type());
    cast_out.Resize(out->dims());
    cast_out.mutable_data<T>(place);

    auto cast_out_dtype = framework::TransToProtoVarType(x->dtype());
    if (out_dtype != -1) {
      cast_out_dtype = static_cast<framework::proto::VarType::Type>(out_dtype);
    }

    if (framework::TransToProtoVarType(x->dtype()) != cast_out_dtype) {
      if (cast_out_dtype == framework::proto::VarType::FP32) {
        out->mutable_data<float>(place);
      } else if (cast_out_dtype == framework::proto::VarType::FP16) {
        out->mutable_data<paddle::platform::float16>(place);
      } else if (cast_out_dtype == framework::proto::VarType::INT16) {
        out->mutable_data<int16_t>(place);
      } else if (cast_out_dtype == framework::proto::VarType::INT32) {
        out->mutable_data<int32_t>(place);
      } else if (cast_out_dtype == framework::proto::VarType::INT64) {
        out->mutable_data<int64_t>(place);
      } else if (cast_out_dtype == framework::proto::VarType::FP64) {
        out->mutable_data<double>(place);
      } else if (cast_out_dtype == framework::proto::VarType::BOOL) {
        out->mutable_data<bool>(place);
      }
    } else {
      out->ShareDataWith(cast_out);
    }

    framework::NPUAttributeMap attr_input = {{"axes", dims},
                                             {"keep_dims", keep_dim}};

    if (reduce_all) {
      std::vector<int> dim_vec;
      for (int i = 0; i < x->dims().size(); i++) {
        dim_vec.push_back(i);
      }

      attr_input = {{"axes", dim_vec}, {"keep_dims", keep_dim}};
    }

    const auto& dev_ctx =
        ctx.template device_context<paddle::platform::NPUDeviceContext>();
    if (framework::TransToProtoVarType(x->dtype()) ==
        framework::proto::VarType::INT64) {
      auto op_func = [](const std::vector<Tensor>& inputs,
                        const std::vector<Tensor>& outputs,
                        const NPUAttributeMap& attrs,
                        const platform::NPUDeviceContext& dev_ctx) {
        const auto& runner =
            NpuOpRunner("ReduceMaxD", {inputs[0]}, {outputs[0]}, attrs);
        runner.Run(dev_ctx.stream());
      };

      NpuOpRunner::TypeAdapter({*x}, {cast_out}, attr_input, dev_ctx, op_func,
                               {framework::proto::VarType::INT32},
                               {framework::proto::VarType::INT32});
    } else {
      const auto& runner =
          NpuOpRunner("ReduceMaxD", {*x}, {cast_out}, attr_input);
      runner.Run(dev_ctx.stream());
    }

    if (framework::TransToProtoVarType(x->dtype()) != cast_out_dtype) {
      auto dst_dtype = ConvertToNpuDtype(cast_out_dtype);
      const auto& runner_cast =
          NpuOpRunner("Cast", {cast_out}, {*out},
                      {{"dst_type", static_cast<int>(dst_dtype)}});
      runner_cast.Run(dev_ctx.stream());
    }
  }
};

template <typename DeviceContext, typename T>
class ReduceMaxGradNPUKernel : public framework::OpKernel<T> {
 public:
  void Compute(const framework::ExecutionContext& context) const override {
    auto* x = context.Input<Tensor>("X");
    auto* out = context.Input<Tensor>("Out");
    auto* out_grad = context.Input<Tensor>(framework::GradVarName("Out"));
    int in_dtype = context.Attr<int>("in_dtype");

    PADDLE_ENFORCE_EQ(
        in_dtype == -1, true,
        platform::errors::InvalidArgument(
            "NPU only support in_dtype == -1 in reduce_max_grad op."));

    auto* x_grad = context.Output<Tensor>(framework::GradVarName("X"));
    x_grad->mutable_data<T>(context.GetPlace());

    auto& dev_ctx =
        context.template device_context<paddle::platform::NPUDeviceContext>();
    auto place = context.GetPlace();
    auto stream = dev_ctx.stream();

    // broadcast
    auto x_dims_vec = phi::vectorize(x->dims());
    Tensor transformed_out(x->type());
    transformed_out.Resize(phi::make_ddim(x_dims_vec));
    transformed_out.mutable_data<T>(place);
    NpuOpRunner r_brd_out;
    r_brd_out.SetType("BroadcastTo")
        .AddInput(*out)
        .AddInput(std::move(x_dims_vec))
        .AddOutput(transformed_out)
        .Run(stream);
    Tensor transformed_out_grad(x->type());
    transformed_out_grad.Resize(phi::make_ddim(x_dims_vec));
    transformed_out_grad.mutable_data<T>(place);
    NpuOpRunner r_brd_out_grad;
    r_brd_out_grad.SetType("BroadcastTo")
        .AddInput(*out_grad)
        .AddInput(std::move(x_dims_vec))
        .AddOutput(transformed_out_grad)
        .Run(stream);

    // compare
    Tensor equal_cond;
    equal_cond.mutable_data<bool>(x_grad->dims(), place);
    const auto& r_equal =
        NpuOpRunner("Equal", {*x, transformed_out}, {equal_cond}, {});
    r_equal.Run(stream);

    // select
    Tensor t_zero;
    t_zero.mutable_data<T>(x_grad->dims(), place);
    FillNpuTensorWithConstant(&t_zero, static_cast<T>(0));
    t_zero.Resize(x_grad->dims());

    const auto& r_sel = NpuOpRunner(
        "SelectV2", {equal_cond, transformed_out_grad, t_zero}, {*x_grad}, {});
    r_sel.Run(stream);
  }
};

}  // namespace operators
}  // namespace paddle

namespace ops = paddle::operators;
namespace plat = paddle::platform;
REGISTER_OP_NPU_KERNEL(
    reduce_max, ops::ReduceMaxNPUKernel<plat::NPUDeviceContext, float>,
    ops::ReduceMaxNPUKernel<plat::NPUDeviceContext, plat::float16>,
    ops::ReduceMaxNPUKernel<plat::NPUDeviceContext, int64_t>,
    ops::ReduceMaxNPUKernel<plat::NPUDeviceContext, int>);
REGISTER_OP_NPU_KERNEL(
    reduce_max_grad, ops::ReduceMaxGradNPUKernel<plat::NPUDeviceContext, float>,
    ops::ReduceMaxGradNPUKernel<plat::NPUDeviceContext, plat::float16>,
    ops::ReduceMaxGradNPUKernel<plat::NPUDeviceContext, int64_t>,
    ops::ReduceMaxGradNPUKernel<plat::NPUDeviceContext, int>);
<|endoftext|>


<commit_before>// Time:  O(n)
// Space: O(1)

// DP with rolling window.
class Solution {
public:
    /**
     * @param values: a vector of integers
     * @return: a boolean which equals to true if the first player will win
     */
    bool firstWillWin(vector<int> &values) {
        vector<int> P(5, 0);
        int sum = 0;
        // P[i] = max(values[i] + min(P[i + 2], P[i + 3]),
        //            values[i] + values[i + 1] + min(P[i + 3], P[i + 4]))
        for (int i = values.size() - 1; i >= 0; --i) {
            sum += values[i];
            int a = i + 2 < values.size() ? P[(i + 2) % 5] : 0;
            int b = i + 3 < values.size() ? P[(i + 3) % 5] : 0;
            int c = i + 4 < values.size() ? P[(i + 4) % 5] : 0;
            P[i % 5] = max(values[i] + min(a, b),
                       values[i] + values[i + 1] + min(b, c));
        }

        return P[0] > sum - P[0];
    }
};

// Time:  O(n)
// Space: O(n)
class Solution2 {
public:
    /**
     * @param values: a vector of integers
     * @return: a boolean which equals to true if the first player will win
     */
    bool firstWillWin(vector<int> &values) {
        vector<int> P(values.size(), 0);
        int sum = 0;
        // P[i] = max(values[i] + min(P[i + 2], P[i + 3]),
        //            values[i] + values[i + 1] + min(P[i + 3], P[i + 4]))
        for (int i = values.size() - 1; i >= 0; --i) {
            sum += values[i];
            int a = i + 2 < values.size() ? P[i + 2] : 0;
            int b = i + 3 < values.size() ? P[i + 3] : 0;
            int c = i + 4 < values.size() ? P[i + 4] : 0;
            P[i] = max(values[i] + min(a, b),
                       values[i] + values[i + 1] + min(b, c));
        }

        return P[0] > sum - P[0];
    }
};
<commit_msg>Update coins-in-a-line-ii.cpp<commit_after>// Time:  O(n)
// Space: O(1)

// DP with rolling window.
class Solution {
public:
    /**
     * @param values: a vector of integers
     * @return: a boolean which equals to true if the first player will win
     */
// Time:  O(n)
// Space: O(1)

// DP with rolling window.
class Solution {
public:
    /**
     * @param values: a vector of integers
     * @return: a boolean which equals to true if the first player will win
     */
    bool firstWillWin(vector<int> &values) {
        // For corner case.
        if (values.size() < 2) {
            return values.size() % 2;
        }

        vector<int> P(5, 0);
        int sum = 0;
        // P[i] = max(values[i] + min(P[i + 2], P[i + 3]),
        //            values[i] + values[i + 1] + min(P[i + 3], P[i + 4]))
        for (int i = values.size() - 1; i >= 0; --i) {
            sum += values[i];
            int values_i_plus_1 = i + 1 < values.size() ? values[i + 1]: 0;
            int a = i + 2 < values.size() ? P[(i + 2) % 5] : 0;
            int b = i + 3 < values.size() ? P[(i + 3) % 5] : 0;
            int c = i + 4 < values.size() ? P[(i + 4) % 5] : 0;

            P[i % 5] = max(values[i] + min(a, b),
                           values[i] + values_i_plus_1 + min(b, c));
        }

        return P[0] > sum - P[0];
    }
};

// Time:  O(n)
// Space: O(n)
class Solution2 {
public:
    /**
     * @param values: a vector of integers
     * @return: a boolean which equals to true if the first player will win
     */
    bool firstWillWin(vector<int> &values) {
        vector<int> P(values.size(), 0);
        int sum = 0;
        // P[i] = max(values[i] + min(P[i + 2], P[i + 3]),
        //            values[i] + values[i + 1] + min(P[i + 3], P[i + 4]))
        for (int i = values.size() - 1; i >= 0; --i) {
            sum += values[i];
            int values_i_plus_1 = i + 1 < values.size() ? values[i + 1]: 0;
            int a = i + 2 < values.size() ? P[i + 2] : 0;
            int b = i + 3 < values.size() ? P[i + 3] : 0;
            int c = i + 4 < values.size() ? P[i + 4] : 0;
            P[i] = max(values[i] + min(a, b),
                       values[i] + values_i_plus_1 + min(b, c));
        }

        return P[0] > sum - P[0];
    }
};
<|endoftext|>


<commit_before>/*
    This file is part of Magnum.

    Original authors — credit is appreciated but not required:

        2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 —
            Vladimír Vondruš <mosra@centrum.cz>
        2015 — Jonathan Hale <squareys@googlemail.com>

    This is free and unencumbered software released into the public domain.

    Anyone is free to copy, modify, publish, use, compile, sell, or distribute
    this software, either in source code form or as a compiled binary, for any
    purpose, commercial or non-commercial, and by any means.

    In jurisdictions that recognize copyright laws, the author or authors of
    this software dedicate any and all copyright interest in the software to
    the public domain. We make this dedication for the benefit of the public
    at large and to the detriment of our heirs and successors. We intend this
    dedication to be an overt act of relinquishment in perpetuity of all
    present and future rights to this software under copyright law.

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

#include <Corrade/Containers/Array.h>
#include <Corrade/PluginManager/PluginManager.h>

#include <Magnum/Audio/AbstractImporter.h>
#include <Magnum/Audio/Buffer.h>
#include <Magnum/Audio/Context.h>
#include <Magnum/Audio/Listener.h>
#include <Magnum/Audio/Playable.h>
#include <Magnum/Audio/PlayableGroup.h>
#include <Magnum/Audio/Renderer.h>
#include <Magnum/Audio/Source.h>

#include <Magnum/Shapes/Shape.h>
#include <Magnum/Shapes/ShapeGroup.h>
#include <Magnum/Shapes/Sphere.h>
#include <Magnum/Shapes/Box.h>
#include <Magnum/DebugTools/ResourceManager.h>
#include <Magnum/DebugTools/ShapeRenderer.h>

#include <Magnum/DefaultFramebuffer.h>
#include <Magnum/Platform/Sdl2Application.h>
#include <Magnum/Renderer.h>
#include <Magnum/SceneGraph/Camera.h>
#include <Magnum/SceneGraph/Object.h>
#include <Magnum/SceneGraph/Scene.h>
#include <Magnum/SceneGraph/Drawable.h>
#include <Magnum/SceneGraph/DualQuaternionTransformation.h>

#include "configure.h"

namespace Magnum { namespace Examples {

using namespace Magnum::SceneGraph;
using namespace Magnum::Math::Literals;

typedef Scene<DualQuaternionTransformation> Scene3D;
typedef Object<DualQuaternionTransformation> Object3D;

class AudioExample: public Platform::Application {
    public:
        explicit AudioExample(const Arguments& arguments);

    private:
        void drawEvent() override;

        void keyPressEvent(KeyEvent& event);

        DebugTools::ResourceManager _manager;

        /* Audio related members */
        Audio::Context _context;
        Audio::Buffer _testBuffer;
        Audio::Source _source;
        Corrade::Containers::Array<char> _bufferData;

        /* Scene objects */
        Scene3D _scene;
        Object3D _sourceRig;
        Object3D _sourceObject;
        Object3D _cameraObject;
        SceneGraph::Camera3D _camera;
        SceneGraph::DrawableGroup3D _drawables;

        Audio::PlayableGroup3D _playables;
        Audio::Playable3D _playable;
        Audio::Listener3D _listener;

        Shapes::ShapeGroup3D _shapes;
};

AudioExample::AudioExample(const Arguments& arguments):
    Platform::Application{arguments, NoCreate},
    /* Create the audio context. Without this, sound will not be initialized:
       Needs to be done before Playables and Sources are initialized. */
    _context(Audio::Context::Configuration().setHrtf(Audio::Context::Configuration::Hrtf::Enabled)),
    _sourceRig(&_scene),
    _sourceObject(&_sourceRig),
    _cameraObject(&_scene),
    _camera(_cameraObject),
    _playable(_sourceObject, &_playables),
    _listener(_scene)
{
    /* Try 16x MSAA */
    Configuration conf;
    conf.setTitle("Magnum Audio Example")
        .setSampleCount(16);
    if(!tryCreateContext(conf))
        createContext(conf.setSampleCount(0));

    /* Setup the camera */
    _camera.setAspectRatioPolicy(SceneGraph::AspectRatioPolicy::Extend)
           .setProjectionMatrix(Matrix4::perspectiveProjection(Deg(90.0f), 1.0f, 0.001f, 100.0f))
           .setViewport(defaultFramebuffer.viewport().size());

    /* Load importer plugin */
    PluginManager::Manager<Audio::AbstractImporter> audioManager{MAGNUM_PLUGINS_AUDIOIMPORTER_DIR};
    std::unique_ptr<Audio::AbstractImporter> importer = audioManager.loadAndInstantiate("StbVorbisAudioImporter");
    if(!importer)
        std::exit(1);

    /* Load audio file from compiled resources */
    const Utility::Resource rs{"audio-data"};
    if(!importer->openData(rs.getRaw("chimes.ogg")))
        std::exit(2);

    _bufferData = importer->data(); /* Get the data from importer */
    /* Add the sample data to the buffer */
    _testBuffer.setData(importer->format(), _bufferData, importer->frequency());

    /* Make our sound source play the buffer again and again... */
    _playable.source().setBuffer(&_testBuffer);
    _playable.source().setLooping(true);
    _playable.source().play();

    /* Initial offset of the sound source */
    _sourceObject.translate({0.0f, 0.0f, -5.0f});

    /* Camera placement */
    _cameraObject.rotateX(-45.0_degf).rotateY(45.0_degf);
    _cameraObject.translate({8.0f, 10.0f, 8.0f});

    /* Setup simple shape rendering for listener and source */
    _manager.set("pink", DebugTools::ShapeRendererOptions().setColor({1.0f, 0.0f, 1.0f}));
    Shapes::Shape<Shapes::Sphere3D>* sphere = new Shapes::Shape<Shapes::Sphere3D>(_sourceObject, {{}, 0.5f}, &_shapes);
    new DebugTools::ShapeRenderer3D(*sphere, ResourceKey("pink"), &_drawables);

    _manager.set("white", DebugTools::ShapeRendererOptions().setColor({1.0f, 1.0f, 1.0f}));
    Shapes::Shape<Shapes::Box3D>* box = new Shapes::Shape<Shapes::Box3D>(_scene, {Matrix4{}}, &_shapes);
    new DebugTools::ShapeRenderer3D(*box, ResourceKey("white"), &_drawables);

    /* Enable depth testing for correct overlap of shapes */
    Renderer::enable(Renderer::Feature::DepthTest);

    /* Print hrft status information */
    Debug() << "Hrtf status:" << _context.hrtfStatus();
    Debug() << "Hrtf enabled:" << _context.isHrtfEnabled();
    Debug() << "Hrtf specifier:" << _context.hrtfSpecifier();

    /* Loop at 60 Hz max */
    setSwapInterval(1);
    setMinimalLoopPeriod(16);
}

void AudioExample::drawEvent() {
    defaultFramebuffer.clear(FramebufferClear::Color | FramebufferClear::Depth);

    _shapes.setClean();

    /* Update listener and sound source positions */
    _listener.update({_playables});

    _camera.draw(_drawables);

    swapBuffers();
    redraw();
}

void AudioExample::keyPressEvent(KeyEvent& event) {
    if(event.key() == KeyEvent::Key::Down) {
        _sourceRig.rotateXLocal(Deg(-5.0f));
        _sourceRig.normalizeRotation();
    } else if(event.key() == KeyEvent::Key::Up) {
        _sourceRig.rotateXLocal(Deg(5.0f));
        _sourceRig.normalizeRotation();
    } else if(event.key() == KeyEvent::Key::Left) {
        _sourceRig.rotateY(Deg(5.0f));
        _sourceRig.normalizeRotation();
    } else if(event.key() == KeyEvent::Key::Right) {
        _sourceRig.rotateY(Deg(-5.0f));
        _sourceRig.normalizeRotation();
    } else if(event.key() == KeyEvent::Key::PageUp)
        _sourceObject.translate({0.0f, 0.0f, -.25f});
    else if(event.key() == KeyEvent::Key::PageDown && _sourceObject.transformation().translation().z() < 0.0f)
        _sourceObject.translate({0.0f, 0.0f, .25f});
    else if(event.key() == KeyEvent::Key::Esc)
        this->exit();

    event.setAccepted();
}

}}

MAGNUM_APPLICATION_MAIN(Magnum::Examples::AudioExample)
<commit_msg>audio: don't use deprecated functionality.<commit_after>/*
    This file is part of Magnum.

    Original authors — credit is appreciated but not required:

        2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 —
            Vladimír Vondruš <mosra@centrum.cz>
        2015 — Jonathan Hale <squareys@googlemail.com>

    This is free and unencumbered software released into the public domain.

    Anyone is free to copy, modify, publish, use, compile, sell, or distribute
    this software, either in source code form or as a compiled binary, for any
    purpose, commercial or non-commercial, and by any means.

    In jurisdictions that recognize copyright laws, the author or authors of
    this software dedicate any and all copyright interest in the software to
    the public domain. We make this dedication for the benefit of the public
    at large and to the detriment of our heirs and successors. We intend this
    dedication to be an overt act of relinquishment in perpetuity of all
    present and future rights to this software under copyright law.

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

#include <Corrade/Containers/Array.h>
#include <Corrade/PluginManager/PluginManager.h>

#include <Magnum/Audio/AbstractImporter.h>
#include <Magnum/Audio/Buffer.h>
#include <Magnum/Audio/Context.h>
#include <Magnum/Audio/Listener.h>
#include <Magnum/Audio/Playable.h>
#include <Magnum/Audio/PlayableGroup.h>
#include <Magnum/Audio/Renderer.h>
#include <Magnum/Audio/Source.h>

#include <Magnum/Shapes/Shape.h>
#include <Magnum/Shapes/ShapeGroup.h>
#include <Magnum/Shapes/Sphere.h>
#include <Magnum/Shapes/Box.h>
#include <Magnum/DebugTools/ResourceManager.h>
#include <Magnum/DebugTools/ShapeRenderer.h>

#include <Magnum/DefaultFramebuffer.h>
#include <Magnum/Platform/Sdl2Application.h>
#include <Magnum/Renderer.h>
#include <Magnum/SceneGraph/Camera.h>
#include <Magnum/SceneGraph/Object.h>
#include <Magnum/SceneGraph/Scene.h>
#include <Magnum/SceneGraph/Drawable.h>
#include <Magnum/SceneGraph/DualQuaternionTransformation.h>

#include "configure.h"

namespace Magnum { namespace Examples {

using namespace Magnum::SceneGraph;
using namespace Magnum::Math::Literals;

typedef Scene<DualQuaternionTransformation> Scene3D;
typedef Object<DualQuaternionTransformation> Object3D;

class AudioExample: public Platform::Application {
    public:
        explicit AudioExample(const Arguments& arguments);

    private:
        void drawEvent() override;

        void keyPressEvent(KeyEvent& event);

        DebugTools::ResourceManager _manager;

        /* Audio related members */
        Audio::Context _context;
        Audio::Buffer _testBuffer;
        Audio::Source _source;
        Corrade::Containers::Array<char> _bufferData;

        /* Scene objects */
        Scene3D _scene;
        Object3D _sourceRig;
        Object3D _sourceObject;
        Object3D _cameraObject;
        SceneGraph::Camera3D _camera;
        SceneGraph::DrawableGroup3D _drawables;

        Audio::PlayableGroup3D _playables;
        Audio::Playable3D _playable;
        Audio::Listener3D _listener;

        Shapes::ShapeGroup3D _shapes;
};

AudioExample::AudioExample(const Arguments& arguments):
    Platform::Application{arguments, NoCreate},
    /* Create the audio context. Without this, sound will not be initialized:
       Needs to be done before Playables and Sources are initialized. */
    _context(Audio::Context::Configuration().setHrtf(Audio::Context::Configuration::Hrtf::Enabled)),
    _sourceRig(&_scene),
    _sourceObject(&_sourceRig),
    _cameraObject(&_scene),
    _camera(_cameraObject),
    _playable(_sourceObject, &_playables),
    _listener(_scene)
{
    /* Try 16x MSAA */
    Configuration conf;
    conf.setTitle("Magnum Audio Example")
        .setSampleCount(16);
    if(!tryCreateContext(conf))
        createContext(conf.setSampleCount(0));

    /* Setup the camera */
    _camera.setAspectRatioPolicy(SceneGraph::AspectRatioPolicy::Extend)
           .setProjectionMatrix(Matrix4::perspectiveProjection(Deg(90.0f), 1.0f, 0.001f, 100.0f))
           .setViewport(defaultFramebuffer.viewport().size());

    /* Load importer plugin */
    PluginManager::Manager<Audio::AbstractImporter> audioManager{MAGNUM_PLUGINS_AUDIOIMPORTER_DIR};
    std::unique_ptr<Audio::AbstractImporter> importer = audioManager.loadAndInstantiate("StbVorbisAudioImporter");
    if(!importer)
        std::exit(1);

    /* Load audio file from compiled resources */
    const Utility::Resource rs{"audio-data"};
    if(!importer->openData(rs.getRaw("chimes.ogg")))
        std::exit(2);

    _bufferData = importer->data(); /* Get the data from importer */
    /* Add the sample data to the buffer */
    _testBuffer.setData(importer->format(), _bufferData, importer->frequency());

    /* Make our sound source play the buffer again and again... */
    _playable.source().setBuffer(&_testBuffer);
    _playable.source().setLooping(true);
    _playable.source().play();

    /* Initial offset of the sound source */
    _sourceObject.translate({0.0f, 0.0f, -5.0f});

    /* Camera placement */
    _cameraObject.rotateX(-45.0_degf).rotateY(45.0_degf);
    _cameraObject.translate({8.0f, 10.0f, 8.0f});

    /* Setup simple shape rendering for listener and source */
    _manager.set("pink", DebugTools::ShapeRendererOptions().setColor({1.0f, 0.0f, 1.0f}));
    Shapes::Shape<Shapes::Sphere3D>* sphere = new Shapes::Shape<Shapes::Sphere3D>(_sourceObject, {{}, 0.5f}, &_shapes);
    new DebugTools::ShapeRenderer3D(*sphere, ResourceKey("pink"), &_drawables);

    _manager.set("white", DebugTools::ShapeRendererOptions().setColor({1.0f, 1.0f, 1.0f}));
    Shapes::Shape<Shapes::Box3D>* box = new Shapes::Shape<Shapes::Box3D>(_scene, {Matrix4{}}, &_shapes);
    new DebugTools::ShapeRenderer3D(*box, ResourceKey("white"), &_drawables);

    /* Enable depth testing for correct overlap of shapes */
    Renderer::enable(Renderer::Feature::DepthTest);

    /* Print hrft status information */
    Debug() << "Hrtf status:" << _context.hrtfStatus();
    Debug() << "Hrtf enabled:" << _context.isHrtfEnabled();
    Debug() << "Hrtf specifier:" << _context.hrtfSpecifierString();

    /* Loop at 60 Hz max */
    setSwapInterval(1);
    setMinimalLoopPeriod(16);
}

void AudioExample::drawEvent() {
    defaultFramebuffer.clear(FramebufferClear::Color | FramebufferClear::Depth);

    _shapes.setClean();

    /* Update listener and sound source positions */
    _listener.update({_playables});

    _camera.draw(_drawables);

    swapBuffers();
    redraw();
}

void AudioExample::keyPressEvent(KeyEvent& event) {
    if(event.key() == KeyEvent::Key::Down) {
        _sourceRig.rotateXLocal(Deg(-5.0f));
        _sourceRig.normalizeRotation();
    } else if(event.key() == KeyEvent::Key::Up) {
        _sourceRig.rotateXLocal(Deg(5.0f));
        _sourceRig.normalizeRotation();
    } else if(event.key() == KeyEvent::Key::Left) {
        _sourceRig.rotateY(Deg(5.0f));
        _sourceRig.normalizeRotation();
    } else if(event.key() == KeyEvent::Key::Right) {
        _sourceRig.rotateY(Deg(-5.0f));
        _sourceRig.normalizeRotation();
    } else if(event.key() == KeyEvent::Key::PageUp)
        _sourceObject.translate({0.0f, 0.0f, -.25f});
    else if(event.key() == KeyEvent::Key::PageDown && _sourceObject.transformation().translation().z() < 0.0f)
        _sourceObject.translate({0.0f, 0.0f, .25f});
    else if(event.key() == KeyEvent::Key::Esc)
        this->exit();

    event.setAccepted();
}

}}

MAGNUM_APPLICATION_MAIN(Magnum::Examples::AudioExample)
<|endoftext|>


<commit_before>/*******************************************************
 * Copyright (c) 2017, ArrayFire
 * All rights reserved.
 *
 * This file is distributed under 3-clause BSD license.
 * The complete license agreement can be obtained at:
 * http://arrayfire.com/licenses/BSD-3-Clause
 ********************************************************/

#include <af/autograd/Variable.hpp>
#include <af/autograd/Functions.hpp>

namespace af {
    namespace autograd {

        Variable operator +(const Variable &lhs, const Variable &rhs)
        {
            auto result = lhs.array() + rhs.array();
            auto grad_func = [](std::vector<Variable> &inputs, const Variable &grad_output) {
                inputs[0].addGrad(grad_output);
                inputs[1].addGrad(grad_output);
            };
            return Variable(result, {lhs, rhs}, grad_func);
        }

        Variable operator -(const Variable &lhs, const Variable &rhs)
        {
            auto result = lhs.array() - rhs.array();
            auto grad_func = [](std::vector<Variable> &inputs, const Variable &grad_output) {
                inputs[0].addGrad(grad_output);
                inputs[1].addGrad(negate(grad_output));
            };
            return Variable(result, {lhs, rhs}, grad_func);
        }

        Variable operator *(const Variable &lhs, const Variable &rhs)
        {
            auto result = lhs.array() * rhs.array();
            auto grad_func = [](std::vector<Variable> &inputs, const Variable &grad_output) {
                inputs[0].addGrad(grad_output * inputs[1]);
                inputs[1].addGrad(grad_output * inputs[0]);
            };
            return Variable(result, {lhs, rhs}, grad_func);
        }

        Variable operator /(const Variable &lhs, const Variable &rhs)
        {
            auto result = lhs.array() / rhs.array();
            auto grad_func = [](std::vector<Variable> &inputs, const Variable &grad_output) {
                auto inputs_1_rec = reciprocal(inputs[1]);
                auto grad_input_0 = grad_output * inputs_1_rec;
                inputs[0].addGrad(grad_input_0);
                inputs[1].addGrad(grad_input_0 * negate(inputs[0]) * inputs_1_rec);
            };
            return Variable(result, {lhs, rhs}, grad_func);
        }

#define INSTANTIATE_OPERATOR(OP)                                        \
        Variable operator OP(const double &lhs_val, const Variable &rhs) \
        {                                                               \
            auto lhs = Variable(                                        \
                af::constant(lhs_val,                                   \
                             rhs.array().dims(),                        \
                             rhs.array().type()),                       \
                false);                                                 \
            return lhs OP rhs;                                          \
        }                                                               \
        Variable operator OP(const Variable &lhs, const double &rhs_val) \
        {                                                               \
            auto rhs = Variable(                                        \
                af::constant(rhs_val,                                   \
                             lhs.array().dims(), lhs.array().type()),   \
                false);                                                 \
            return lhs OP rhs;                                          \
        }                                                               \

        INSTANTIATE_OPERATOR(+)
        INSTANTIATE_OPERATOR(-)
        INSTANTIATE_OPERATOR(*)
        INSTANTIATE_OPERATOR(/)

#undef INSTANTIATE_OPERATOR

        Variable negate(const Variable &input)
        {
            auto result = 0.0 - input.array();
            auto grad_func = [](std::vector<Variable> &inputs, const Variable &grad_output) {
                inputs[0].addGrad(negate(grad_output));
            };
            return Variable(result, {input}, grad_func);
        }

        Variable reciprocal(const Variable &input)
        {
            auto result = 1.0 / input.array();
            auto grad_func = [](std::vector<Variable> &inputs, const Variable &grad_output) {
                auto res = reciprocal(inputs[0]);
                inputs[0].addGrad(negate(grad_output) * res * res);
            };
            return Variable(result, {input}, grad_func);
        }

        Variable exp(const Variable &input)
        {
            auto result = exp(input.array());
            auto grad_func = [](std::vector<Variable> &inputs, const Variable &grad_output) {
                inputs[0].addGrad(exp(inputs[0]));
            };
            return Variable(result, {input}, grad_func);
        }

        Variable sin(const Variable &input)
        {
            auto result = sin(input.array());
            auto grad_func = [](std::vector<Variable> &inputs, const Variable &grad_output) {
                inputs[0].addGrad(cos(inputs[0]));
            };
            return Variable(result, {input}, grad_func);
        }

        Variable cos(const Variable &input)
        {
            auto result = cos(input.array());
            auto grad_func = [](std::vector<Variable> &inputs, const Variable &grad_output) {
                inputs[0].addGrad(negate(sin(inputs[0])));
            };
            return Variable(result, {input}, grad_func);
        }

        Variable tanh(const Variable &input)
        {
            auto result = tanh(input.array());
            auto grad_func = [](std::vector<Variable> &inputs, const Variable &grad_output) {
                auto tmp = tanh(inputs[0]);
                inputs[0].addGrad(1.0 - tmp * tmp);
            };
            return Variable(result, {input}, grad_func);
        }

        Variable sigmoid(const Variable &input)
        {
            auto result = sigmoid(input.array());
            auto grad_func = [](std::vector<Variable> &inputs, const Variable &grad_output) {
                auto tmp = sigmoid(inputs[0]);
                inputs[0].addGrad(tmp * (1 - tmp));
            };
            return Variable(result, {input}, grad_func);
        }

        Variable transpose(const Variable &input)
        {
            auto result = transpose(input.array());
            auto grad_func = [](std::vector<Variable> &inputs, const Variable &grad_output) {
                inputs[0].addGrad(transpose(grad_output));
            };
            return Variable(result, {input}, grad_func);
        }

        Variable expandAs(const Variable &input, const Variable &reference)
        {
            dim4 dims(1,1,1,1);
            dim4 idims = input.array().dims();
            dim4 rdims = reference.array().dims();
            for (int i = 0; i < 4; i++) {
                dims[i] = rdims[i] / idims[i];
            }
            auto result = tile(input.array(), dims);
            auto grad_func = [](std::vector<Variable> &inputs, const Variable &grad_output) {
                inputs[0].addGrad(reduceAs(grad_output, inputs[0]));
            };
            return Variable(result, {input}, grad_func);
        }

        Variable reduceAs(const Variable &input, const Variable &reference)
        {
            dim4 idims = input.array().dims();
            dim4 rdims = reference.array().dims();
            auto result = input.array();
            for (int i = 0; i < 4; i++) {
                if (idims[i] != rdims[i]) result = sum(result, i);
            }
            auto grad_func = [](std::vector<Variable> &inputs, const Variable &grad_output) {
                inputs[0].addGrad(expandAs(grad_output, inputs[0]));
            };
            return Variable(result, {input}, grad_func);
        }

        Variable matmul(const Variable &lhs, const Variable &rhs)
        {
            // lhs:Input[0] -- [M, N]
            // rhs:Input[1] -- [N, K]
            //matmul(lhs, rhs)
            // -- matmul([M, N], [N, K]) --  [M, K]
            // result:grad_output -- [M, K]
            auto result = matmul(lhs.array(), rhs.array());
            auto grad_func = [](std::vector<Variable> &inputs, const Variable &grad_output) {
                // matmulNT(grad_output, inputs[1])
                // -- matmulNT([M, K], [N, K])
                // -- matmul([M, K], [K, N]) -- [M, K]
                inputs[0].addGrad(matmulNT(grad_output, inputs[1]));
                // matmulTN(inputs[0], grad_output)
                // -- matmulTN([M, N], [M, K])
                // -- matmul([N, M], [M, K]) -- [N, K]
                inputs[1].addGrad(matmulTN(inputs[0], grad_output));
            };
            return Variable(result, {lhs, rhs}, grad_func);
        }

        Variable matmulTN(const Variable &lhs, const Variable &rhs)
        {
            // lhs:Input[0] -- [N, M]
            // rhs:Input[1] -- [N, K]
            // matmulTN(lhs, rhs)
            // -- matmulTN([N, M], [N, K])
            // -- matmul([M, N], [N, K]) -- [M, K]
            // result:grad_output -- [M, K]
            auto result = matmulTN(lhs.array(), rhs.array());
            auto grad_func = [](std::vector<Variable> &inputs, const Variable &grad_output) {
                // matmulNT(inputs[1], grad_output)
                // -- matmulNT([N, K], [M, K])
                // -- matmul([N, K], [K, M]) -- [N, M]
                inputs[0].addGrad(matmulNT(inputs[1], grad_output));
                // matmul(inputs[0], grad_output)
                // -- matmulNT([N, M], [M, K]) -- [N, K]
                inputs[1].addGrad(matmul(inputs[0], grad_output));
            };
            return Variable(result, {lhs, rhs}, grad_func);
        }

        Variable matmulNT(const Variable &lhs, const Variable &rhs)
        {
            // lhs:Input[0] -- [M, N]
            // rhs:Input[1] -- [K, N]
            // matmulNT(lhs, rhs)
            // -- matmulNT([M, N], [K, N])
            // -- matmul([M, N], [N, K]) -- [M, K]
            // result:grad_output -- [M, K]
            auto result = matmulNT(lhs.array(), rhs.array());
            auto grad_func = [](std::vector<Variable> &inputs, const Variable &grad_output) {
                // matmul(grad_output, inputs[1])
                // -- matmul([M, K], [K, N]) -- [M, N]
                inputs[0].addGrad(matmul(grad_output, inputs[1]));
                // matmulTN(grad_output, inputs[0])
                // -- matmulTN([M, K], [M, N])
                // -- matmul([K, M], [M, N]) -- [K, N]
                inputs[1].addGrad(matmulTN(grad_output, inputs[0]));
            };
            return Variable(result, {lhs, rhs}, grad_func);
        }
    }
}
<commit_msg>Fixing bugs in backward pass for activation functions<commit_after>/*******************************************************
 * Copyright (c) 2017, ArrayFire
 * All rights reserved.
 *
 * This file is distributed under 3-clause BSD license.
 * The complete license agreement can be obtained at:
 * http://arrayfire.com/licenses/BSD-3-Clause
 ********************************************************/

#include <af/autograd/Variable.hpp>
#include <af/autograd/Functions.hpp>

namespace af {
    namespace autograd {

        Variable operator +(const Variable &lhs, const Variable &rhs)
        {
            auto result = lhs.array() + rhs.array();
            auto grad_func = [](std::vector<Variable> &inputs, const Variable &grad_output) {
                inputs[0].addGrad(grad_output);
                inputs[1].addGrad(grad_output);
            };
            return Variable(result, {lhs, rhs}, grad_func);
        }

        Variable operator -(const Variable &lhs, const Variable &rhs)
        {
            auto result = lhs.array() - rhs.array();
            auto grad_func = [](std::vector<Variable> &inputs, const Variable &grad_output) {
                inputs[0].addGrad(grad_output);
                inputs[1].addGrad(negate(grad_output));
            };
            return Variable(result, {lhs, rhs}, grad_func);
        }

        Variable operator *(const Variable &lhs, const Variable &rhs)
        {
            auto result = lhs.array() * rhs.array();
            auto grad_func = [](std::vector<Variable> &inputs, const Variable &grad_output) {
                inputs[0].addGrad(grad_output * inputs[1]);
                inputs[1].addGrad(grad_output * inputs[0]);
            };
            return Variable(result, {lhs, rhs}, grad_func);
        }

        Variable operator /(const Variable &lhs, const Variable &rhs)
        {
            auto result = lhs.array() / rhs.array();
            auto grad_func = [](std::vector<Variable> &inputs, const Variable &grad_output) {
                auto inputs_1_rec = reciprocal(inputs[1]);
                auto grad_input_0 = grad_output * inputs_1_rec;
                inputs[0].addGrad(grad_input_0);
                inputs[1].addGrad(grad_input_0 * negate(inputs[0]) * inputs_1_rec);
            };
            return Variable(result, {lhs, rhs}, grad_func);
        }

#define INSTANTIATE_OPERATOR(OP)                                        \
        Variable operator OP(const double &lhs_val, const Variable &rhs) \
        {                                                               \
            auto lhs = Variable(                                        \
                af::constant(lhs_val,                                   \
                             rhs.array().dims(),                        \
                             rhs.array().type()),                       \
                false);                                                 \
            return lhs OP rhs;                                          \
        }                                                               \
        Variable operator OP(const Variable &lhs, const double &rhs_val) \
        {                                                               \
            auto rhs = Variable(                                        \
                af::constant(rhs_val,                                   \
                             lhs.array().dims(), lhs.array().type()),   \
                false);                                                 \
            return lhs OP rhs;                                          \
        }                                                               \

        INSTANTIATE_OPERATOR(+)
        INSTANTIATE_OPERATOR(-)
        INSTANTIATE_OPERATOR(*)
        INSTANTIATE_OPERATOR(/)

#undef INSTANTIATE_OPERATOR

        Variable negate(const Variable &input)
        {
            auto result = 0.0 - input.array();
            auto grad_func = [](std::vector<Variable> &inputs, const Variable &grad_output) {
                inputs[0].addGrad(negate(grad_output));
            };
            return Variable(result, {input}, grad_func);
        }

        Variable reciprocal(const Variable &input)
        {
            auto result = 1.0 / input.array();
            auto grad_func = [](std::vector<Variable> &inputs, const Variable &grad_output) {
                auto res = reciprocal(inputs[0]);
                inputs[0].addGrad(negate(grad_output) * res * res);
            };
            return Variable(result, {input}, grad_func);
        }

        Variable exp(const Variable &input)
        {
            auto result = exp(input.array());
            auto grad_func = [](std::vector<Variable> &inputs, const Variable &grad_output) {
                inputs[0].addGrad(grad_output * exp(inputs[0]));
            };
            return Variable(result, {input}, grad_func);
        }

        Variable sin(const Variable &input)
        {
            auto result = sin(input.array());
            auto grad_func = [](std::vector<Variable> &inputs, const Variable &grad_output) {
                inputs[0].addGrad(grad_output * cos(inputs[0]));
            };
            return Variable(result, {input}, grad_func);
        }

        Variable cos(const Variable &input)
        {
            auto result = cos(input.array());
            auto grad_func = [](std::vector<Variable> &inputs, const Variable &grad_output) {
                inputs[0].addGrad(grad_output * negate(sin(inputs[0])));
            };
            return Variable(result, {input}, grad_func);
        }

        Variable tanh(const Variable &input)
        {
            auto result = tanh(input.array());
            auto grad_func = [](std::vector<Variable> &inputs, const Variable &grad_output) {
                auto tmp = tanh(inputs[0]);
                inputs[0].addGrad(grad_output * (1.0 - tmp * tmp));
            };
            return Variable(result, {input}, grad_func);
        }

        Variable sigmoid(const Variable &input)
        {
            auto result = sigmoid(input.array());
            auto grad_func = [](std::vector<Variable> &inputs, const Variable &grad_output) {
                auto tmp = sigmoid(inputs[0]);
                inputs[0].addGrad(grad_output * tmp * (1 - tmp));
            };
            return Variable(result, {input}, grad_func);
        }

        Variable transpose(const Variable &input)
        {
            auto result = transpose(input.array());
            auto grad_func = [](std::vector<Variable> &inputs, const Variable &grad_output) {
                inputs[0].addGrad(transpose(grad_output));
            };
            return Variable(result, {input}, grad_func);
        }

        Variable expandAs(const Variable &input, const Variable &reference)
        {
            dim4 dims(1,1,1,1);
            dim4 idims = input.array().dims();
            dim4 rdims = reference.array().dims();
            for (int i = 0; i < 4; i++) {
                dims[i] = rdims[i] / idims[i];
            }
            auto result = tile(input.array(), dims);
            auto grad_func = [](std::vector<Variable> &inputs, const Variable &grad_output) {
                inputs[0].addGrad(reduceAs(grad_output, inputs[0]));
            };
            return Variable(result, {input}, grad_func);
        }

        Variable reduceAs(const Variable &input, const Variable &reference)
        {
            dim4 idims = input.array().dims();
            dim4 rdims = reference.array().dims();
            auto result = input.array();
            for (int i = 0; i < 4; i++) {
                if (idims[i] != rdims[i]) result = sum(result, i);
            }
            auto grad_func = [](std::vector<Variable> &inputs, const Variable &grad_output) {
                inputs[0].addGrad(expandAs(grad_output, inputs[0]));
            };
            return Variable(result, {input}, grad_func);
        }

        Variable matmul(const Variable &lhs, const Variable &rhs)
        {
            // lhs:Input[0] -- [M, N]
            // rhs:Input[1] -- [N, K]
            //matmul(lhs, rhs)
            // -- matmul([M, N], [N, K]) --  [M, K]
            // result:grad_output -- [M, K]
            auto result = matmul(lhs.array(), rhs.array());
            auto grad_func = [](std::vector<Variable> &inputs, const Variable &grad_output) {
                // matmulNT(grad_output, inputs[1])
                // -- matmulNT([M, K], [N, K])
                // -- matmul([M, K], [K, N]) -- [M, K]
                inputs[0].addGrad(matmulNT(grad_output, inputs[1]));
                // matmulTN(inputs[0], grad_output)
                // -- matmulTN([M, N], [M, K])
                // -- matmul([N, M], [M, K]) -- [N, K]
                inputs[1].addGrad(matmulTN(inputs[0], grad_output));
            };
            return Variable(result, {lhs, rhs}, grad_func);
        }

        Variable matmulTN(const Variable &lhs, const Variable &rhs)
        {
            // lhs:Input[0] -- [N, M]
            // rhs:Input[1] -- [N, K]
            // matmulTN(lhs, rhs)
            // -- matmulTN([N, M], [N, K])
            // -- matmul([M, N], [N, K]) -- [M, K]
            // result:grad_output -- [M, K]
            auto result = matmulTN(lhs.array(), rhs.array());
            auto grad_func = [](std::vector<Variable> &inputs, const Variable &grad_output) {
                // matmulNT(inputs[1], grad_output)
                // -- matmulNT([N, K], [M, K])
                // -- matmul([N, K], [K, M]) -- [N, M]
                inputs[0].addGrad(matmulNT(inputs[1], grad_output));
                // matmul(inputs[0], grad_output)
                // -- matmulNT([N, M], [M, K]) -- [N, K]
                inputs[1].addGrad(matmul(inputs[0], grad_output));
            };
            return Variable(result, {lhs, rhs}, grad_func);
        }

        Variable matmulNT(const Variable &lhs, const Variable &rhs)
        {
            // lhs:Input[0] -- [M, N]
            // rhs:Input[1] -- [K, N]
            // matmulNT(lhs, rhs)
            // -- matmulNT([M, N], [K, N])
            // -- matmul([M, N], [N, K]) -- [M, K]
            // result:grad_output -- [M, K]
            auto result = matmulNT(lhs.array(), rhs.array());
            auto grad_func = [](std::vector<Variable> &inputs, const Variable &grad_output) {
                // matmul(grad_output, inputs[1])
                // -- matmul([M, K], [K, N]) -- [M, N]
                inputs[0].addGrad(matmul(grad_output, inputs[1]));
                // matmulTN(grad_output, inputs[0])
                // -- matmulTN([M, K], [M, N])
                // -- matmul([K, M], [M, N]) -- [K, N]
                inputs[1].addGrad(matmulTN(grad_output, inputs[0]));
            };
            return Variable(result, {lhs, rhs}, grad_func);
        }
    }
}
<|endoftext|>