<commit_before>//
//  libavg - Media Playback Engine.
//  Copyright (C) 2003-2008 Ulrich von Zadow
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2 of the License, or (at your option) any later version.
//
//  This library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//  Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with this library; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
//  Current versions can be found at www.libavg.de
//

#include "VectorNode.h"

#include "NodeDefinition.h"
#include "SDLDisplayEngine.h"
#include "OGLSurface.h"
#include "Image.h"

#include "../base/Exception.h"
#include "../base/Logger.h"
#include "../base/ScopeTimer.h"
#include "../base/Exception.h"

#include "../graphics/VertexArray.h"
#include "../graphics/Filterfliprgb.h"

#include <Magick++.h>

#include <iostream>
#include <sstream>

using namespace std;
using namespace boost;

namespace avg {

NodeDefinition VectorNode::createDefinition()
{
    return NodeDefinition("vector")
        .extendDefinition(Node::createDefinition())
        .addArg(Arg<string>("color", "FFFFFF", false, offsetof(VectorNode, m_sColorName)))
        .addArg(Arg<double>("strokewidth", 1, false, offsetof(VectorNode, m_StrokeWidth)))
        .addArg(Arg<string>("texhref", "", false, offsetof(VectorNode, m_TexHRef)))
        ;
}

VectorNode::VectorNode(const ArgList& Args)
    : m_pImage(new Image("", true))
{
    m_TexHRef = Args.getArgVal<string>("texhref");
    setTexHRef(m_TexHRef);
}

VectorNode::~VectorNode()
{
}

void VectorNode::setRenderingEngines(DisplayEngine * pDisplayEngine,
        AudioEngine * pAudioEngine)
{
    setDrawNeeded(true);
    m_Color = colorStringToColor(m_sColorName);
    m_pImage->moveToGPU(dynamic_cast<SDLDisplayEngine*>(pDisplayEngine));
    Node::setRenderingEngines(pDisplayEngine, pAudioEngine);
    if (isTextured()) {
        createTexture();
        downloadTexture();
    }

    m_pVertexArray = VertexArrayPtr(new VertexArray(getNumVertexes(), getNumIndexes(),
            100, 100));
    m_OldOpacity = -1;
}

void VectorNode::connect()
{
    Node::connect();
    checkReload();
}

void VectorNode::disconnect()
{
    m_pVertexArray = VertexArrayPtr();
    m_pImage->moveToCPU();
    deleteTexture();

    Node::disconnect();
}

const std::string& VectorNode::getTexHRef() const
{
    return m_TexHRef;
}

void VectorNode::setTexHRef(const string& href)
{
    m_TexHRef = href;
    checkReload();
}

static ProfilingZone PrerenderProfilingZone("VectorNode::prerender");
static ProfilingZone VAProfilingZone("VectorNode::update VA");
static ProfilingZone VASizeProfilingZone("VectorNode::resize VA");

void VectorNode::preRender()
{
    ScopeTimer Timer(PrerenderProfilingZone);
    double curOpacity = getEffectiveOpacity();

    if (m_bVASizeChanged) {
        ScopeTimer Timer(VASizeProfilingZone);
        m_pVertexArray->changeSize(getNumVertexes(), getNumIndexes());
        m_bVASizeChanged = false;
    }
    {
        ScopeTimer Timer(VAProfilingZone);
        if (m_bDrawNeeded || curOpacity != m_OldOpacity) {
            m_pVertexArray->reset();
            calcVertexes(m_pVertexArray, curOpacity);
            m_pVertexArray->update();
            m_bDrawNeeded = false;
            m_OldOpacity = curOpacity;
        }
    }

}

void VectorNode::maybeRender(const DRect& Rect)
{
    assert(getState() == NS_CANRENDER);
    if (getEffectiveOpacity() > 0.01) {
        if (getID() != "") {
            AVG_TRACE(Logger::BLTS, "Rendering " << getTypeStr() <<
                    " with ID " << getID());
        } else {
            AVG_TRACE(Logger::BLTS, "Rendering " << getTypeStr());
        }
        render(Rect);
    }
}

static ProfilingZone RenderProfilingZone("VectorNode::render");

void VectorNode::render(const DRect& rect)
{
    ScopeTimer Timer(RenderProfilingZone);
    SDLDisplayEngine * pEngine = getDisplayEngine();
    if (isTextured()) {
        glproc::ActiveTexture(GL_TEXTURE0);
        int TextureMode = pEngine->getTextureMode();
        glBindTexture(TextureMode, m_TexID);
        glTexParameteri(TextureMode, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        glTexParameteri(TextureMode, GL_TEXTURE_WRAP_T, GL_REPEAT);
        OGLErrorCheck(AVG_ERR_VIDEO_GENERAL,
                "VectorNode::render: glTexParameteri()");
    }
    pEngine->enableTexture(isTextured());
    pEngine->enableGLColorArray(!isTextured());
    m_pVertexArray->draw();
}

void VectorNode::checkReload()
{
    bool bOldImageExists = isTextured();
    string sLastFilename = m_pImage->getFilename();
    Node::checkReload(m_TexHRef, m_pImage);
    if (m_pImage->getState() == Image::GPU &&
        (sLastFilename != m_pImage->getFilename() || !bOldImageExists))
    {
        createTexture();
        downloadTexture();
    }
}

void VectorNode::setColor(const string& sColor)
{
    if (m_sColorName != sColor) {
        m_sColorName = sColor;
        m_Color = colorStringToColor(m_sColorName);
        m_bDrawNeeded = true;
    }
}

const string& VectorNode::getColor() const
{
    return m_sColorName;
}

void VectorNode::setStrokeWidth(double width)
{
    if (width != m_StrokeWidth) {
        m_bDrawNeeded = true;
        m_StrokeWidth = width;
    }
}

double VectorNode::getStrokeWidth() const
{
    return m_StrokeWidth;
}

Pixel32 VectorNode::getColorVal() const
{
    return m_Color;
}

void VectorNode::updateLineData(VertexArrayPtr& pVertexArray, double opacity,
        const DPoint& p1, const DPoint& p2, double TC1, double TC2)
{
    Pixel32 color = getColorVal();
    color.setA((unsigned char)(opacity*255));

    WideLine wl(p1, p2, getStrokeWidth());
    int curVertex = pVertexArray->getCurVert();
    pVertexArray->appendPos(wl.pl0, calcTexCoord(DPoint(TC1, 1)), color);
    pVertexArray->appendPos(wl.pr0, calcTexCoord(DPoint(TC1, 0)), color);
    pVertexArray->appendPos(wl.pl1, calcTexCoord(DPoint(TC2, 1)), color);
    pVertexArray->appendPos(wl.pr1, calcTexCoord(DPoint(TC2, 0)), color);
    pVertexArray->appendQuadIndexes(curVertex+1, curVertex, curVertex+3, curVertex+2);
}

void VectorNode::setDrawNeeded(bool bSizeChanged)
{
    m_bDrawNeeded = true;
    if (bSizeChanged) {
        m_bVASizeChanged = true;
    }
}

DPoint VectorNode::calcTexCoord(const DPoint& origCoord)
{
    SDLDisplayEngine * pEngine = dynamic_cast<SDLDisplayEngine*>(getDisplayEngine());
    if (pEngine->getTextureMode() == GL_TEXTURE_2D || !isTextured()) {
        return origCoord;
    } else {
        DPoint size = DPoint(m_pImage->getSize());
        return origCoord*size;
    }
}

void VectorNode::createTexture()
{
    PixelFormat pf = m_pImage->getPixelFormat();
    IntPoint size = m_pImage->getSize();

    SDLDisplayEngine* pEngine = getDisplayEngine();
    glGenTextures(1, &m_TexID);
    OGLErrorCheck(AVG_ERR_VIDEO_GENERAL, "VectorNode::createTexture: glGenTextures()");
    glproc::ActiveTexture(GL_TEXTURE0);
    int TextureMode = pEngine->getTextureMode();
    glBindTexture(TextureMode, m_TexID);
    OGLErrorCheck(AVG_ERR_VIDEO_GENERAL, "VectorNode::createTexture: glBindTexture()");
    glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);

    GLenum DestMode = pEngine->getOGLDestMode(pf);
    char * pPixels = 0;
    if (TextureMode == GL_TEXTURE_2D) {
        // Make sure the texture is transparent and black before loading stuff
        // into it to avoid garbage at the borders.
        int TexMemNeeded = size.x*size.y*Bitmap::getBytesPerPixel(pf);
        pPixels = new char[TexMemNeeded];
        memset(pPixels, 0, TexMemNeeded);
    }
    glTexImage2D(TextureMode, 0, DestMode, size.x, size.y, 0,
            pEngine->getOGLSrcMode(pf), pEngine->getOGLPixelType(pf), pPixels);
    OGLErrorCheck(AVG_ERR_VIDEO_GENERAL,
            "VectorNode::createTexture: glTexImage2D()");
    if (TextureMode == GL_TEXTURE_2D) {
        free(pPixels);
    }
}

void VectorNode::downloadTexture() const
{
    SDLDisplayEngine* pEngine = getDisplayEngine();
    OGLSurface* pSurface = m_pImage->getSurface();
    PixelFormat pf = m_pImage->getPixelFormat();
    IntPoint size = m_pImage->getSize();
    pSurface->bindPBO();
    int TextureMode = pEngine->getTextureMode();
    glBindTexture(TextureMode, m_TexID);
    OGLErrorCheck(AVG_ERR_VIDEO_GENERAL,
            "VectorNode::downloadTexture: glBindTexture()");
    glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
    glTexSubImage2D(TextureMode, 0, 0, 0, size.x, size.y,
            pEngine->getOGLSrcMode(pf), pEngine->getOGLPixelType(pf), 0);
    OGLErrorCheck(AVG_ERR_VIDEO_GENERAL,
            "VectorNode::downloadTexture: glTexSubImage2D()");
    pSurface->unbindPBO();
}

void VectorNode::deleteTexture()
{
    glDeleteTextures(1, &m_TexID);
}

bool VectorNode::isTextured() const
{
    return (m_pImage->getState() != Image::NOT_AVAILABLE);
}

WideLine::WideLine(const DPoint& p0, const DPoint& p1, double width)
    : pt0(p0),
      pt1(p1)
{
    DPoint m = (pt1-pt0);
    m.normalize();
    DPoint w = DPoint(m.y, -m.x)*width/2;
    pl0 = p0-w;
    pr0 = p0+w;
    pl1 = p1-w;
    pr1 = p1+w;
    dir = DPoint(w.y, -w.x);
}

std::ostream& operator<<(std::ostream& os, const WideLine& line)
{
    os << "(" << line.pt0 << "," << line.pt1 << ")";
    return os;
}

}
<commit_msg>texturedvectors branch: Fixed VectorNode GL_REPEAT bug.<commit_after>//
//  libavg - Media Playback Engine.
//  Copyright (C) 2003-2008 Ulrich von Zadow
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2 of the License, or (at your option) any later version.
//
//  This library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//  Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with this library; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
//  Current versions can be found at www.libavg.de
//

#include "VectorNode.h"

#include "NodeDefinition.h"
#include "SDLDisplayEngine.h"
#include "OGLSurface.h"
#include "Image.h"

#include "../base/Exception.h"
#include "../base/Logger.h"
#include "../base/ScopeTimer.h"
#include "../base/Exception.h"

#include "../graphics/VertexArray.h"
#include "../graphics/Filterfliprgb.h"

#include <Magick++.h>

#include <iostream>
#include <sstream>

using namespace std;
using namespace boost;

namespace avg {

NodeDefinition VectorNode::createDefinition()
{
    return NodeDefinition("vector")
        .extendDefinition(Node::createDefinition())
        .addArg(Arg<string>("color", "FFFFFF", false, offsetof(VectorNode, m_sColorName)))
        .addArg(Arg<double>("strokewidth", 1, false, offsetof(VectorNode, m_StrokeWidth)))
        .addArg(Arg<string>("texhref", "", false, offsetof(VectorNode, m_TexHRef)))
        ;
}

VectorNode::VectorNode(const ArgList& Args)
    : m_pImage(new Image("", true))
{
    m_TexHRef = Args.getArgVal<string>("texhref");
    setTexHRef(m_TexHRef);
}

VectorNode::~VectorNode()
{
}

void VectorNode::setRenderingEngines(DisplayEngine * pDisplayEngine,
        AudioEngine * pAudioEngine)
{
    setDrawNeeded(true);
    m_Color = colorStringToColor(m_sColorName);
    m_pImage->moveToGPU(dynamic_cast<SDLDisplayEngine*>(pDisplayEngine));
    Node::setRenderingEngines(pDisplayEngine, pAudioEngine);
    if (isTextured()) {
        createTexture();
        downloadTexture();
    }

    m_pVertexArray = VertexArrayPtr(new VertexArray(getNumVertexes(), getNumIndexes(),
            100, 100));
    m_OldOpacity = -1;
}

void VectorNode::connect()
{
    Node::connect();
    checkReload();
}

void VectorNode::disconnect()
{
    m_pVertexArray = VertexArrayPtr();
    m_pImage->moveToCPU();
    deleteTexture();

    Node::disconnect();
}

const std::string& VectorNode::getTexHRef() const
{
    return m_TexHRef;
}

void VectorNode::setTexHRef(const string& href)
{
    m_TexHRef = href;
    checkReload();
}

static ProfilingZone PrerenderProfilingZone("VectorNode::prerender");
static ProfilingZone VAProfilingZone("VectorNode::update VA");
static ProfilingZone VASizeProfilingZone("VectorNode::resize VA");

void VectorNode::preRender()
{
    ScopeTimer Timer(PrerenderProfilingZone);
    double curOpacity = getEffectiveOpacity();

    if (m_bVASizeChanged) {
        ScopeTimer Timer(VASizeProfilingZone);
        m_pVertexArray->changeSize(getNumVertexes(), getNumIndexes());
        m_bVASizeChanged = false;
    }
    {
        ScopeTimer Timer(VAProfilingZone);
        if (m_bDrawNeeded || curOpacity != m_OldOpacity) {
            m_pVertexArray->reset();
            calcVertexes(m_pVertexArray, curOpacity);
            m_pVertexArray->update();
            m_bDrawNeeded = false;
            m_OldOpacity = curOpacity;
        }
    }

}

void VectorNode::maybeRender(const DRect& Rect)
{
    assert(getState() == NS_CANRENDER);
    if (getEffectiveOpacity() > 0.01) {
        if (getID() != "") {
            AVG_TRACE(Logger::BLTS, "Rendering " << getTypeStr() <<
                    " with ID " << getID());
        } else {
            AVG_TRACE(Logger::BLTS, "Rendering " << getTypeStr());
        }
        render(Rect);
    }
}

static ProfilingZone RenderProfilingZone("VectorNode::render");

void VectorNode::render(const DRect& rect)
{
    ScopeTimer Timer(RenderProfilingZone);
    SDLDisplayEngine * pEngine = getDisplayEngine();
    if (isTextured()) {
        glproc::ActiveTexture(GL_TEXTURE0);
        int TextureMode = pEngine->getTextureMode();
        glBindTexture(TextureMode, m_TexID);
        glTexParameteri(TextureMode, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        glTexParameteri(TextureMode, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
        OGLErrorCheck(AVG_ERR_VIDEO_GENERAL,
                "VectorNode::render: glTexParameteri()");
    }
    pEngine->enableTexture(isTextured());
    pEngine->enableGLColorArray(!isTextured());
    m_pVertexArray->draw();
}

void VectorNode::checkReload()
{
    bool bOldImageExists = isTextured();
    string sLastFilename = m_pImage->getFilename();
    Node::checkReload(m_TexHRef, m_pImage);
    if (m_pImage->getState() == Image::GPU &&
        (sLastFilename != m_pImage->getFilename() || !bOldImageExists))
    {
        createTexture();
        downloadTexture();
    }
}

void VectorNode::setColor(const string& sColor)
{
    if (m_sColorName != sColor) {
        m_sColorName = sColor;
        m_Color = colorStringToColor(m_sColorName);
        m_bDrawNeeded = true;
    }
}

const string& VectorNode::getColor() const
{
    return m_sColorName;
}

void VectorNode::setStrokeWidth(double width)
{
    if (width != m_StrokeWidth) {
        m_bDrawNeeded = true;
        m_StrokeWidth = width;
    }
}

double VectorNode::getStrokeWidth() const
{
    return m_StrokeWidth;
}

Pixel32 VectorNode::getColorVal() const
{
    return m_Color;
}

void VectorNode::updateLineData(VertexArrayPtr& pVertexArray, double opacity,
        const DPoint& p1, const DPoint& p2, double TC1, double TC2)
{
    Pixel32 color = getColorVal();
    color.setA((unsigned char)(opacity*255));

    WideLine wl(p1, p2, getStrokeWidth());
    int curVertex = pVertexArray->getCurVert();
    pVertexArray->appendPos(wl.pl0, calcTexCoord(DPoint(TC1, 1)), color);
    pVertexArray->appendPos(wl.pr0, calcTexCoord(DPoint(TC1, 0)), color);
    pVertexArray->appendPos(wl.pl1, calcTexCoord(DPoint(TC2, 1)), color);
    pVertexArray->appendPos(wl.pr1, calcTexCoord(DPoint(TC2, 0)), color);
    pVertexArray->appendQuadIndexes(curVertex+1, curVertex, curVertex+3, curVertex+2);
}

void VectorNode::setDrawNeeded(bool bSizeChanged)
{
    m_bDrawNeeded = true;
    if (bSizeChanged) {
        m_bVASizeChanged = true;
    }
}

DPoint VectorNode::calcTexCoord(const DPoint& origCoord)
{
    SDLDisplayEngine * pEngine = dynamic_cast<SDLDisplayEngine*>(getDisplayEngine());
    if (pEngine->getTextureMode() == GL_TEXTURE_2D || !isTextured()) {
        return origCoord;
    } else {
        DPoint size = DPoint(m_pImage->getSize());
        return origCoord*size;
    }
}

void VectorNode::createTexture()
{
    PixelFormat pf = m_pImage->getPixelFormat();
    IntPoint size = m_pImage->getSize();

    SDLDisplayEngine* pEngine = getDisplayEngine();
    glGenTextures(1, &m_TexID);
    OGLErrorCheck(AVG_ERR_VIDEO_GENERAL, "VectorNode::createTexture: glGenTextures()");
    glproc::ActiveTexture(GL_TEXTURE0);
    int TextureMode = pEngine->getTextureMode();
    glBindTexture(TextureMode, m_TexID);
    OGLErrorCheck(AVG_ERR_VIDEO_GENERAL, "VectorNode::createTexture: glBindTexture()");
    glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);

    GLenum DestMode = pEngine->getOGLDestMode(pf);
    char * pPixels = 0;
    if (TextureMode == GL_TEXTURE_2D) {
        // Make sure the texture is transparent and black before loading stuff
        // into it to avoid garbage at the borders.
        int TexMemNeeded = size.x*size.y*Bitmap::getBytesPerPixel(pf);
        pPixels = new char[TexMemNeeded];
        memset(pPixels, 0, TexMemNeeded);
    }
    glTexImage2D(TextureMode, 0, DestMode, size.x, size.y, 0,
            pEngine->getOGLSrcMode(pf), pEngine->getOGLPixelType(pf), pPixels);
    OGLErrorCheck(AVG_ERR_VIDEO_GENERAL,
            "VectorNode::createTexture: glTexImage2D()");
    if (TextureMode == GL_TEXTURE_2D) {
        free(pPixels);
    }
}

void VectorNode::downloadTexture() const
{
    SDLDisplayEngine* pEngine = getDisplayEngine();
    OGLSurface* pSurface = m_pImage->getSurface();
    PixelFormat pf = m_pImage->getPixelFormat();
    IntPoint size = m_pImage->getSize();
    pSurface->bindPBO();
    int TextureMode = pEngine->getTextureMode();
    glBindTexture(TextureMode, m_TexID);
    OGLErrorCheck(AVG_ERR_VIDEO_GENERAL,
            "VectorNode::downloadTexture: glBindTexture()");
    glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
    glTexSubImage2D(TextureMode, 0, 0, 0, size.x, size.y,
            pEngine->getOGLSrcMode(pf), pEngine->getOGLPixelType(pf), 0);
    OGLErrorCheck(AVG_ERR_VIDEO_GENERAL,
            "VectorNode::downloadTexture: glTexSubImage2D()");
    pSurface->unbindPBO();
}

void VectorNode::deleteTexture()
{
    glDeleteTextures(1, &m_TexID);
}

bool VectorNode::isTextured() const
{
    return (m_pImage->getState() != Image::NOT_AVAILABLE);
}

WideLine::WideLine(const DPoint& p0, const DPoint& p1, double width)
    : pt0(p0),
      pt1(p1)
{
    DPoint m = (pt1-pt0);
    m.normalize();
    DPoint w = DPoint(m.y, -m.x)*width/2;
    pl0 = p0-w;
    pr0 = p0+w;
    pl1 = p1-w;
    pr1 = p1+w;
    dir = DPoint(w.y, -w.x);
}

std::ostream& operator<<(std::ostream& os, const WideLine& line)
{
    os << "(" << line.pt0 << "," << line.pt1 << ")";
    return os;
}

}
<|endoftext|>


<commit_before>#ifndef RADIUMENGINE_DEBUG_DISPLAY_HPP_
#define RADIUMENGINE_DEBUG_DISPLAY_HPP_

#include <Engine/RaEngine.hpp>

/// This file's main purpose is to declare a set of macros to allow drawing
/// primitives from everywhere in the code, for debug purposes.
/// These macros can be completely disabled by #defining the following constant :

// define RA_DISABLE_DEBUG_DISPLAY

#include <Core/Math/ColorPresets.hpp>
#include <Core/Utils/Singleton.hpp>

#include <Engine/Component/Component.hpp>
#include <Engine/Entity/Entity.hpp>

#ifndef RA_DISABLE_DEBUG_DISPLAY
#    include <Engine/Renderer/RenderObject/Primitives/DrawPrimitives.hpp>
#endif

namespace Ra {
namespace Engine {
#ifndef RA_DISABLE_DEBUG_DISPLAY

/// Component for debug drawing. @see SystemEntity.
class RA_ENGINE_API DebugComponent : public Component {
  public:
    DebugComponent( Entity* entity ) : Component( "Debug", entity ) {}

    void initialize() override {}

    /// Access render object through RO manager
    RenderObject* getRenderObject( Core::Index idx );
};

#endif

/// Component for UI drawing. @see SystemEntity.
class RA_ENGINE_API UiComponent : public Component {
  public:
    UiComponent( Entity* entity ) : Component( "UI", entity ) {}

    void initialize() override {}
};

/// This entity allows to add UI and debug drawables from everywhere in the code.
/// It should have only one component and its transform should not change.
class RA_ENGINE_API SystemEntity : public Entity {
    RA_SINGLETON_INTERFACE( SystemEntity );

  public:
    SystemEntity();

    virtual ~SystemEntity(){};

    /// Ignore raycast queries
    virtual void rayCastQuery( const Core::Ray& r ) const override {}

#ifndef RA_DISABLE_DEBUG_DISPLAY
    /// Access the debug component
    static DebugComponent* dbgCmp();

#endif
    /// Access the UI Component
    static UiComponent* uiCmp();
};

} // namespace Engine
} // namespace Ra

#ifndef RA_DISABLE_DEBUG_DISPLAY
/// Macros for debug drawing. All coordinates are in world space.
#    define RA_DISPLAY_POINT( p, color, scale )              \
        Ra::Engine::SystemEntity::dbgCmp()->addRenderObject( \
            Ra::Engine::DrawPrimitives::Primitive(           \
                Ra::Engine::SystemEntity::dbgCmp(),          \
                Ra::Engine::DrawPrimitives::Point( p, color, scale ) ) )

#    define RA_DISPLAY_VECTOR( p, v, color )                 \
        Ra::Engine::SystemEntity::dbgCmp()->addRenderObject( \
            Ra::Engine::DrawPrimitives::Primitive(           \
                Ra::Engine::SystemEntity::dbgCmp(),          \
                Ra::Engine::DrawPrimitives::Vector( p, v, color ) ) )

#    define RA_DISPLAY_RAY( r, color )                                                 \
        Ra::Engine::SystemEntity::dbgCmp()->addRenderObject(                           \
            Ra::Engine::DrawPrimitives::Primitive( Ra::Engine::SystemEntity::dbgCmp(), \
                                                   Ra::Engine::DrawPrimitives::Ray( r, color ) ) )

#    define RA_DISPLAY_CIRCLE( c, n, r, color )              \
        Ra::Engine::SystemEntity::dbgCmp()->addRenderObject( \
            Ra::Engine::DrawPrimitives::Primitive(           \
                Ra::Engine::SystemEntity::dbgCmp(),          \
                Ra::Engine::DrawPrimitives::Circle( c, n, r, 20, color ) ) )

#    define RA_DISPLAY_TRIANGLE( a, b, c, color )            \
        Ra::Engine::SystemEntity::dbgCmp()->addRenderObject( \
            Ra::Engine::DrawPrimitives::Primitive(           \
                Ra::Engine::SystemEntity::dbgCmp(),          \
                Ra::Engine::DrawPrimitives::Triangle( a, b, c, color ) ) )

#    define RA_DISPLAY_NORMAL( p, n, color, scale )          \
        Ra::Engine::SystemEntity::dbgCmp()->addRenderObject( \
            Ra::Engine::DrawPrimitives::Primitive(           \
                Ra::Engine::SystemEntity::dbgCmp(),          \
                Ra::Engine::DrawPrimitives::Normal( p, n, color, scale ) ) )

#    define RA_DISPLAY_FRAME( t, scale )                     \
        Ra::Engine::SystemEntity::dbgCmp()->addRenderObject( \
            Ra::Engine::DrawPrimitives::Primitive(           \
                Ra::Engine::SystemEntity::dbgCmp(),          \
                Ra::Engine::DrawPrimitives::Frame( t, scale ) ) )

#    define RA_DISPLAY_AABB( a, color )                      \
        Ra::Engine::SystemEntity::dbgCmp()->addRenderObject( \
            Ra::Engine::DrawPrimitives::Primitive(           \
                Ra::Engine::SystemEntity::dbgCmp(),          \
                Ra::Engine::DrawPrimitives::AABB( a, color ) ) )

#    define RA_DISPLAY_OBB( a, color )                                                 \
        Ra::Engine::SystemEntity::dbgCmp()->addRenderObject(                           \
            Ra::Engine::DrawPrimitives::Primitive( Ra::Engine::SystemEntity::dbgCmp(), \
                                                   Ra::Engine::DrawPrimitives::OBB( a, color ) ) )

#    define RA_DISPLAY_SPHERE( c, r, color )                 \
        Ra::Engine::SystemEntity::dbgCmp()->addRenderObject( \
            Ra::Engine::DrawPrimitives::Primitive(           \
                Ra::Engine::SystemEntity::dbgCmp(),          \
                Ra::Engine::DrawPrimitives::Sphere( c, r, color ) ) )

#    define RA_DISPLAY_CAPSULE( p1, p2, r, color )           \
        Ra::Engine::SystemEntity::dbgCmp()->addRenderObject( \
            Ra::Engine::DrawPrimitives::Primitive(           \
                Ra::Engine::SystemEntity::dbgCmp(),          \
                Ra::Engine::DrawPrimitives::Capsule( p1, p2, r, color ) ) )

#    define RA_DISPLAY_LINE_ONCE( a, b, color ) \
        Ra::Engine::DebugRender::getInstance()->drawLine( a, b, color )

#else // if debug display is disabled

#    define RA_DISPLAY_POINT( p, color, scale )     // Nothing
#    define RA_DISPLAY_VECTOR( p, v, color )        // ...
#    define RA_DISPLAY_RAY( r, color )              // ...
#    define RA_DISPLAY_CIRCLE( c, n, r, color )     // ...
#    define RA_DISPLAY_TRIANGLE( a, b, c, color )   // ...
#    define RA_DISPLAY_NORMAL( p, n, color, scale ) // ...
#    define RA_DISPLAY_FRAME( t, scale )            // ...
#    define RA_DISPLAY_AABB( a, color )             // ...
#    define RA_DISPLAY_OBB( a, color )              // ...
#    define RA_DISPLAY_SPHERE( c, r, color )        // ...
#    define RA_DISPLAY_CAPSULE( p1, p2, r, color )  // ...
#    define RA_DISPLAY_LINE_ONCE( a, b, color )     // ...

#endif //! defined DISABLED_DEBUG_DISPLAY

#endif // RADIUMENGINE_DEBUG_DISPLAY_HPP_
<commit_msg>Fix DISPLAY MACRO<commit_after>#ifndef RADIUMENGINE_DEBUG_DISPLAY_HPP_
#define RADIUMENGINE_DEBUG_DISPLAY_HPP_

#include <Engine/RaEngine.hpp>

/// This file's main purpose is to declare a set of macros to allow drawing
/// primitives from everywhere in the code, for debug purposes.
/// These macros can be completely disabled by #defining the following constant :

// define RA_DISABLE_DEBUG_DISPLAY

#include <Core/Math/ColorPresets.hpp>
#include <Core/Utils/Singleton.hpp>

#include <Engine/Component/Component.hpp>
#include <Engine/Entity/Entity.hpp>

#ifndef RA_DISABLE_DEBUG_DISPLAY
#    include <Engine/Renderer/RenderObject/Primitives/DrawPrimitives.hpp>
#endif

namespace Ra {
namespace Engine {
#ifndef RA_DISABLE_DEBUG_DISPLAY

/// Component for debug drawing. @see SystemEntity.
class RA_ENGINE_API DebugComponent : public Component {
  public:
    DebugComponent( Entity* entity ) : Component( "Debug", entity ) {}

    void initialize() override {}

    /// Access render object through RO manager
    RenderObject* getRenderObject( Core::Index idx );
};

#endif

/// Component for UI drawing. @see SystemEntity.
class RA_ENGINE_API UiComponent : public Component {
  public:
    UiComponent( Entity* entity ) : Component( "UI", entity ) {}

    void initialize() override {}
};

/// This entity allows to add UI and debug drawables from everywhere in the code.
/// It should have only one component and its transform should not change.
class RA_ENGINE_API SystemEntity : public Entity {
    RA_SINGLETON_INTERFACE( SystemEntity );

  public:
    SystemEntity();

    virtual ~SystemEntity(){};

    /// Ignore raycast queries
    virtual void rayCastQuery( const Core::Ray& r ) const override {}

#ifndef RA_DISABLE_DEBUG_DISPLAY
    /// Access the debug component
    static DebugComponent* dbgCmp();

#endif
    /// Access the UI Component
    static UiComponent* uiCmp();
};

} // namespace Engine
} // namespace Ra

#ifndef RA_DISABLE_DEBUG_DISPLAY
/// Macros for debug drawing. All coordinates are in world space.
#    define RA_DISPLAY_POINT( p, color, scale )              \
        Ra::Engine::SystemEntity::dbgCmp()->addRenderObject( \
            Ra::Engine::DrawPrimitives::Primitive(           \
                Ra::Engine::SystemEntity::dbgCmp(),          \
                Ra::Engine::DrawPrimitives::Point( p, color, scale ) ) )

#    define RA_DISPLAY_VECTOR( p, v, color )                 \
        Ra::Engine::SystemEntity::dbgCmp()->addRenderObject( \
            Ra::Engine::DrawPrimitives::Primitive(           \
                Ra::Engine::SystemEntity::dbgCmp(),          \
                Ra::Engine::DrawPrimitives::Vector( p, v, color ) ) )

#    define RA_DISPLAY_RAY( r, color )                                                 \
        Ra::Engine::SystemEntity::dbgCmp()->addRenderObject(                           \
            Ra::Engine::DrawPrimitives::Primitive( Ra::Engine::SystemEntity::dbgCmp(), \
                                                   Ra::Engine::DrawPrimitives::Ray( r, color ) ) )

#    define RA_DISPLAY_CIRCLE( c, n, r, color )              \
        Ra::Engine::SystemEntity::dbgCmp()->addRenderObject( \
            Ra::Engine::DrawPrimitives::Primitive(           \
                Ra::Engine::SystemEntity::dbgCmp(),          \
                Ra::Engine::DrawPrimitives::Circle( c, n, r, 20, color ) ) )

#    define RA_DISPLAY_TRIANGLE( a, b, c, color )            \
        Ra::Engine::SystemEntity::dbgCmp()->addRenderObject( \
            Ra::Engine::DrawPrimitives::Primitive(           \
                Ra::Engine::SystemEntity::dbgCmp(),          \
                Ra::Engine::DrawPrimitives::Triangle( a, b, c, color ) ) )

#    define RA_DISPLAY_NORMAL( p, n, color, scale )          \
        Ra::Engine::SystemEntity::dbgCmp()->addRenderObject( \
            Ra::Engine::DrawPrimitives::Primitive(           \
                Ra::Engine::SystemEntity::dbgCmp(),          \
                Ra::Engine::DrawPrimitives::Normal( p, n, color, scale ) ) )

#    define RA_DISPLAY_FRAME( t, scale )                     \
        Ra::Engine::SystemEntity::dbgCmp()->addRenderObject( \
            Ra::Engine::DrawPrimitives::Primitive(           \
                Ra::Engine::SystemEntity::dbgCmp(),          \
                Ra::Engine::DrawPrimitives::Frame( t, scale ) ) )

#    define RA_DISPLAY_AABB( a, color )                      \
        Ra::Engine::SystemEntity::dbgCmp()->addRenderObject( \
            Ra::Engine::DrawPrimitives::Primitive(           \
                Ra::Engine::SystemEntity::dbgCmp(),          \
                Ra::Engine::DrawPrimitives::AABB( a, color ) ) )

#    define RA_DISPLAY_OBB( a, color )                                                 \
        Ra::Engine::SystemEntity::dbgCmp()->addRenderObject(                           \
            Ra::Engine::DrawPrimitives::Primitive( Ra::Engine::SystemEntity::dbgCmp(), \
                                                   Ra::Engine::DrawPrimitives::OBB( a, color ) ) )

#    define RA_DISPLAY_SPHERE( c, r, color )                 \
        Ra::Engine::SystemEntity::dbgCmp()->addRenderObject( \
            Ra::Engine::DrawPrimitives::Primitive(           \
                Ra::Engine::SystemEntity::dbgCmp(),          \
                Ra::Engine::DrawPrimitives::Sphere( c, r, color ) ) )

#    define RA_DISPLAY_CAPSULE( p1, p2, r, color )           \
        Ra::Engine::SystemEntity::dbgCmp()->addRenderObject( \
            Ra::Engine::DrawPrimitives::Primitive(           \
                Ra::Engine::SystemEntity::dbgCmp(),          \
                Ra::Engine::DrawPrimitives::Capsule( p1, p2, r, color ) ) )

#    define RA_DISPLAY_LINE( a, b, color )                   \
        Ra::Engine::SystemEntity::dbgCmp()->addRenderObject( \
            Ra::Engine::DrawPrimitives::Primitive(           \
                Ra::Engine::SystemEntity::dbgCmp(),          \
                Ra::Engine::DrawPrimitives::Line( a, b, color ) ) )

#else // if debug display is disabled

#    define RA_DISPLAY_POINT( p, color, scale )     // Nothing
#    define RA_DISPLAY_VECTOR( p, v, color )        // ...
#    define RA_DISPLAY_RAY( r, color )              // ...
#    define RA_DISPLAY_CIRCLE( c, n, r, color )     // ...
#    define RA_DISPLAY_TRIANGLE( a, b, c, color )   // ...
#    define RA_DISPLAY_NORMAL( p, n, color, scale ) // ...
#    define RA_DISPLAY_FRAME( t, scale )            // ...
#    define RA_DISPLAY_AABB( a, color )             // ...
#    define RA_DISPLAY_OBB( a, color )              // ...
#    define RA_DISPLAY_SPHERE( c, r, color )        // ...
#    define RA_DISPLAY_CAPSULE( p1, p2, r, color )  // ...
#    define RA_DISPLAY_LINE( a, b, color )          // ...

#endif //! defined DISABLED_DEBUG_DISPLAY

#endif // RADIUMENGINE_DEBUG_DISPLAY_HPP_
<|endoftext|>


<commit_before>//! name the boost unit test module
#define BOOST_TEST_MODULE NVTUpdaterTestsMPI
#include "MPITestSetup.h"

#include "HOOMDMath.h"
#include "ExecutionConfiguration.h"
#include "System.h"
#include "TwoStepNVT.h"
#include "IntegratorTwoStep.h"
#include "AllPairPotentials.h"
#include "NeighborListBinned.h"
#include "RandomGenerator.h"

#include <boost/python.hpp>
#include <boost/mpi.hpp>
#include <boost/shared_ptr.hpp>

#include <math.h>

#include "Communicator.h"
#include "DomainDecomposition.h"

#ifdef ENABLE_CUDA
#include "CellListGPU.h"
#include "NeighborListGPUBinned.h"
#include "TwoStepNVTGPU.h"
#include "ComputeThermoGPU.h"
#include "CommunicatorGPU.h"
#endif

using namespace boost;

void test_nvt_integrator_mpi(boost::shared_ptr<ExecutionConfiguration> exec_conf)
{
    // initialize two random particle system
    Scalar phi_p = 0.2;
    unsigned int N = 20000;
    Scalar L = pow(M_PI/6.0/phi_p*Scalar(N),1.0/3.0);
    BoxDim box_g(L);
    RandomGenerator rand_init(exec_conf, box_g, 12345);
    std::vector<string> types;
    types.push_back("A");
    std::vector<uint> bonds;
    std::vector<string> bond_types;
    rand_init.addGenerator((int)N, boost::shared_ptr<PolymerParticleGenerator>(new PolymerParticleGenerator(exec_conf, 1.0, types, bonds, bonds, bond_types, 100)));
    rand_init.setSeparationRadius("A", .4);

    rand_init.generate();

    boost::shared_ptr<SnapshotSystemData> snap;
    snap = rand_init.getSnapshot();

    boost::shared_ptr<DomainDecomposition> decomposition(new DomainDecomposition(exec_conf,snap->global_box.getL(), 0));

    shared_ptr<SystemDefinition> sysdef_1(new SystemDefinition(snap, exec_conf,decomposition));
    shared_ptr<SystemDefinition> sysdef_2(new SystemDefinition(snap, exec_conf));

    shared_ptr<ParticleData> pdata_1 = sysdef_1->getParticleData();
    shared_ptr<ParticleData> pdata_2 = sysdef_2->getParticleData();

    boost::shared_ptr<Communicator> comm;
#ifdef ENABLE_CUDA
    if (exec_conf->isCUDAEnabled())
        comm = shared_ptr<Communicator>(new CommunicatorGPU(sysdef_1, decomposition));
    else
#endif
        comm = boost::shared_ptr<Communicator>(new Communicator(sysdef_1,decomposition));

    shared_ptr<ParticleSelector> selector_all_1(new ParticleSelectorTag(sysdef_1, 0, pdata_1->getNGlobal()-1));
    shared_ptr<ParticleGroup> group_all_1(new ParticleGroup(sysdef_1, selector_all_1));

    shared_ptr<ParticleSelector> selector_all_2(new ParticleSelectorTag(sysdef_2, 0, pdata_2->getNGlobal()-1));
    shared_ptr<ParticleGroup> group_all_2(new ParticleGroup(sysdef_2, selector_all_2));

    Scalar r_cut = Scalar(3.0);
    Scalar r_buff = Scalar(0.8);
    shared_ptr<NeighborList> nlist_1(new NeighborListBinned(sysdef_1, r_cut, r_buff));
    shared_ptr<NeighborList> nlist_2(new NeighborListBinned(sysdef_2, r_cut, r_buff));

    nlist_1->setStorageMode(NeighborList::full);
    nlist_2->setStorageMode(NeighborList::full);

    nlist_1->setCommunicator(comm);

    shared_ptr<PotentialPairLJ> fc_1 = shared_ptr<PotentialPairLJ>(new PotentialPairLJ(sysdef_1, nlist_1));
    shared_ptr<PotentialPairLJ> fc_2 = shared_ptr<PotentialPairLJ>(new PotentialPairLJ(sysdef_2, nlist_2));

    fc_1->setRcut(0, 0, r_cut);
    fc_2->setRcut(0, 0, r_cut);

    // setup some values for alpha and sigma
    Scalar epsilon = Scalar(1.0);
    Scalar sigma = Scalar(1.0);
    Scalar alpha = Scalar(1.0);
    Scalar lj1 = Scalar(4.0) * epsilon * pow(sigma,Scalar(12.0));
    Scalar lj2 = alpha * Scalar(4.0) * epsilon * pow(sigma,Scalar(6.0));
    fc_1->setParams(0,0,make_scalar2(lj1,lj2));
    fc_2->setParams(0,0,make_scalar2(lj1,lj2));

    Scalar deltaT = Scalar(0.005);
    Scalar Q = Scalar(2.0);
    Scalar T = Scalar(1.5/3.0);
    Scalar tau = sqrt(Q / (Scalar(3.0) * T));
    shared_ptr<VariantConst> T_variant_1(new VariantConst(T));
    shared_ptr<VariantConst> T_variant_2(new VariantConst(T));
    shared_ptr<IntegratorTwoStep> nvt_1(new IntegratorTwoStep(sysdef_1, deltaT));
    shared_ptr<IntegratorTwoStep> nvt_2(new IntegratorTwoStep(sysdef_2, deltaT));
    shared_ptr<ComputeThermo> thermo_1 = shared_ptr<ComputeThermo>(new ComputeThermo(sysdef_1,group_all_1));
    thermo_1->setCommunicator(comm);
    shared_ptr<ComputeThermo> thermo_2 = shared_ptr<ComputeThermo>(new ComputeThermo(sysdef_2,group_all_2));

    shared_ptr<TwoStepNVT> two_step_nvt_1;
    shared_ptr<TwoStepNVT> two_step_nvt_2;
#ifdef ENABLE_CUDA
    if (exec_conf->isCUDAEnabled())
        {
        two_step_nvt_1 = boost::shared_ptr<TwoStepNVT>(new TwoStepNVTGPU(sysdef_1, group_all_1, thermo_1, tau, T_variant_1));
        two_step_nvt_2 = boost::shared_ptr<TwoStepNVT>(new TwoStepNVTGPU(sysdef_2, group_all_2, thermo_2, tau, T_variant_2));
        }
    else
#endif
    two_step_nvt_1 = boost::shared_ptr<TwoStepNVT>(new TwoStepNVT(sysdef_1, group_all_1, thermo_1, tau, T_variant_1));
    two_step_nvt_2 = boost::shared_ptr<TwoStepNVT>(new TwoStepNVT(sysdef_2, group_all_2, thermo_2, tau, T_variant_2));

    nvt_1->addIntegrationMethod(two_step_nvt_1);
    nvt_1->addForceCompute(fc_1);
    nvt_1->setCommunicator(comm);

    nvt_2->addIntegrationMethod(two_step_nvt_2);
    nvt_2->addForceCompute(fc_2);

    unsigned int ndof = nvt_1->getNDOF(group_all_1);
    BOOST_CHECK_EQUAL(ndof, nvt_2->getNDOF(group_all_2));
    thermo_1->setNDOF(ndof);
    thermo_2->setNDOF(ndof);

    nvt_1->prepRun(0);
    nvt_2->prepRun(0);

    SnapshotParticleData snap_1(N);
    SnapshotParticleData snap_2(N);
    for (int i=0; i< 100; i++)
        {
        // compare temperatures
        if (exec_conf->getRank() == 0)
            BOOST_CHECK_CLOSE(thermo_1->getTemperature(), thermo_2->getTemperature(), tol_small);

//       if (world->rank() ==0)
//           std::cout << "step " << i << std::endl;
        Scalar rough_tol = 15.0;

        // in the first five steps, compare all accelerations and velocities
        // beyond this number of steps, trajectories will generally diverge, since they are chaotic
        // compare the snapshot of the parallel simulation
        if (i < 5)
            {
            pdata_1->takeSnapshot(snap_1);
            // ... against the serial simulation
            pdata_2->takeSnapshot(snap_2);

            if (exec_conf->getRank() == 0)
                {
                // check position, velocity and acceleration
                for (unsigned int j = 0; j < N; j++)
                    {
                    // we do not check positions (or we would need to pull back vectors over the boundaries)
                    //MY_BOOST_CHECK_CLOSE(snap_1.pos[j].x, snap_2.pos[j].x, rough_tol);
                    //MY_BOOST_CHECK_CLOSE(snap_1.pos[j].y, snap_2.pos[j].y, rough_tol);
                    //MY_BOOST_CHECK_CLOSE(snap_1.pos[j].z, snap_2.pos[j].z, rough_tol);

                    MY_BOOST_CHECK_CLOSE(snap_1.vel[j].x, snap_2.vel[j].x, rough_tol);
                    MY_BOOST_CHECK_CLOSE(snap_1.vel[j].y, snap_2.vel[j].y, rough_tol);
                    MY_BOOST_CHECK_CLOSE(snap_1.vel[j].z, snap_2.vel[j].z, rough_tol);

                    MY_BOOST_CHECK_CLOSE(snap_1.accel[j].x, snap_2.accel[j].x, rough_tol);
                    MY_BOOST_CHECK_CLOSE(snap_1.accel[j].y, snap_2.accel[j].y, rough_tol);
                    MY_BOOST_CHECK_CLOSE(snap_1.accel[j].z, snap_2.accel[j].z, rough_tol);
                    }
                }
            }
        nvt_1->update(i);
        nvt_2->update(i);
        }

}

//! Tests MPI domain decomposition with NVT integrator
BOOST_AUTO_TEST_CASE( DomainDecomposition_NVT_test )
    {
    test_nvt_integrator_mpi(exec_conf_cpu);
    }

#ifdef ENABLE_CUDA
//! Tests MPI domain decomposition with NVT integrator on the GPU
BOOST_AUTO_TEST_CASE( DomainDecomposition_NVT_test_GPU )
    {
    test_nvt_integrator_mpi(exec_conf_gpu);
    }
#endif
<commit_msg>Fixed NVT MPI unit test<commit_after>//! name the boost unit test module
#define BOOST_TEST_MODULE NVTUpdaterTestsMPI
#include "MPITestSetup.h"

#include "HOOMDMath.h"
#include "ExecutionConfiguration.h"
#include "System.h"
#include "TwoStepNVT.h"
#include "IntegratorTwoStep.h"
#include "AllPairPotentials.h"
#include "NeighborListBinned.h"
#include "RandomGenerator.h"

#include <boost/python.hpp>
#include <boost/mpi.hpp>
#include <boost/shared_ptr.hpp>

#include <math.h>

#include "Communicator.h"
#include "DomainDecomposition.h"

#ifdef ENABLE_CUDA
#include "CellListGPU.h"
#include "NeighborListGPUBinned.h"
#include "TwoStepNVTGPU.h"
#include "ComputeThermoGPU.h"
#include "CommunicatorGPU.h"
#endif

using namespace boost;

void test_nvt_integrator_mpi(boost::shared_ptr<ExecutionConfiguration> exec_conf)
{
    // initialize random particle system
    Scalar phi_p = 0.2;
    unsigned int N = 20000;
    Scalar L = pow(M_PI/6.0/phi_p*Scalar(N),1.0/3.0);
    BoxDim box_g(L);
    RandomGenerator rand_init(exec_conf, box_g, 12345);
    std::vector<string> types;
    types.push_back("A");
    std::vector<uint> bonds;
    std::vector<string> bond_types;
    rand_init.addGenerator((int)N, boost::shared_ptr<PolymerParticleGenerator>(new PolymerParticleGenerator(exec_conf, 1.0, types, bonds, bonds, bond_types, 100)));
    rand_init.setSeparationRadius("A", .4);

    rand_init.generate();

    boost::shared_ptr<SnapshotSystemData> snap;
    snap = rand_init.getSnapshot();

    boost::shared_ptr<DomainDecomposition> decomposition(new DomainDecomposition(exec_conf,snap->global_box.getL(), 0));

    shared_ptr<SystemDefinition> sysdef_1(new SystemDefinition(snap, exec_conf,decomposition));

    // initialize a second system (single proc) on rank zero
    shared_ptr<SystemDefinition> sysdef_2;
    if (exec_conf->getRank() == 0)
        sysdef_2 = shared_ptr<SystemDefinition>(new SystemDefinition(snap, exec_conf));

    shared_ptr<ParticleData> pdata_1 = sysdef_1->getParticleData();

    shared_ptr<ParticleData> pdata_2;
    if (exec_conf->getRank() == 0)
        pdata_2 = sysdef_2->getParticleData();

    boost::shared_ptr<Communicator> comm;
#ifdef ENABLE_CUDA
    if (exec_conf->isCUDAEnabled())
        comm = shared_ptr<Communicator>(new CommunicatorGPU(sysdef_1, decomposition));
    else
#endif
        comm = boost::shared_ptr<Communicator>(new Communicator(sysdef_1,decomposition));

    shared_ptr<ParticleSelector> selector_all_1(new ParticleSelectorTag(sysdef_1, 0, pdata_1->getNGlobal()-1));
    shared_ptr<ParticleGroup> group_all_1(new ParticleGroup(sysdef_1, selector_all_1));

    shared_ptr<ParticleSelector> selector_all_2;
    shared_ptr<ParticleGroup> group_all_2;
    if (exec_conf->getRank() ==0)
        {
        selector_all_2 = shared_ptr<ParticleSelector>(new ParticleSelectorTag(sysdef_2, 0, pdata_2->getNGlobal()-1));
        group_all_2 = shared_ptr<ParticleGroup>(new ParticleGroup(sysdef_2, selector_all_2));
        }

    Scalar r_cut = Scalar(3.0);
    Scalar r_buff = Scalar(0.8);
    shared_ptr<NeighborList> nlist_1(new NeighborListBinned(sysdef_1, r_cut, r_buff));

    nlist_1->setStorageMode(NeighborList::full);
    nlist_1->setCommunicator(comm);
    shared_ptr<PotentialPairLJ> fc_1 = shared_ptr<PotentialPairLJ>(new PotentialPairLJ(sysdef_1, nlist_1));

    fc_1->setRcut(0, 0, r_cut);

    // setup some values for alpha and sigma
    Scalar epsilon = Scalar(1.0);
    Scalar sigma = Scalar(1.0);
    Scalar alpha = Scalar(1.0);
    Scalar lj1 = Scalar(4.0) * epsilon * pow(sigma,Scalar(12.0));
    Scalar lj2 = alpha * Scalar(4.0) * epsilon * pow(sigma,Scalar(6.0));
    fc_1->setParams(0,0,make_scalar2(lj1,lj2));

    shared_ptr<NeighborList> nlist_2;
    shared_ptr<PotentialPairLJ> fc_2;
    if (exec_conf->getRank() == 0)
        {
        nlist_2 = shared_ptr<NeighborList>(new NeighborListBinned(sysdef_2, r_cut, r_buff));
        nlist_2->setStorageMode(NeighborList::full);
        fc_2 = shared_ptr<PotentialPairLJ>(new PotentialPairLJ(sysdef_2, nlist_2));
        fc_2->setRcut(0, 0, r_cut);
        fc_2->setParams(0,0,make_scalar2(lj1,lj2));
        }

    Scalar deltaT = Scalar(0.005);
    Scalar Q = Scalar(2.0);
    Scalar T = Scalar(1.5/3.0);
    Scalar tau = sqrt(Q / (Scalar(3.0) * T));
    shared_ptr<VariantConst> T_variant_1(new VariantConst(T));
    shared_ptr<IntegratorTwoStep> nvt_1(new IntegratorTwoStep(sysdef_1, deltaT));
    shared_ptr<ComputeThermo> thermo_1 = shared_ptr<ComputeThermo>(new ComputeThermo(sysdef_1,group_all_1));
    thermo_1->setCommunicator(comm);

    shared_ptr<VariantConst> T_variant_2;
    shared_ptr<IntegratorTwoStep> nvt_2;
    shared_ptr<ComputeThermo> thermo_2;

    if (exec_conf->getRank()==0)
        {
        T_variant_2 = shared_ptr<VariantConst>(new VariantConst(T));
        nvt_2  = shared_ptr<IntegratorTwoStep>(new IntegratorTwoStep(sysdef_2, deltaT));
        thermo_2 = shared_ptr<ComputeThermo>(new ComputeThermo(sysdef_2,group_all_2));
        }

    shared_ptr<TwoStepNVT> two_step_nvt_1;
    shared_ptr<TwoStepNVT> two_step_nvt_2;
#ifdef ENABLE_CUDA
    if (exec_conf->isCUDAEnabled())
        {
        two_step_nvt_1 = boost::shared_ptr<TwoStepNVT>(new TwoStepNVTGPU(sysdef_1, group_all_1, thermo_1, tau, T_variant_1));
        if (exec_conf->getRank() == 0)
            two_step_nvt_2 = boost::shared_ptr<TwoStepNVT>(new TwoStepNVTGPU(sysdef_2, group_all_2, thermo_2, tau, T_variant_2));
        }
    else
#endif
        {
        two_step_nvt_1 = boost::shared_ptr<TwoStepNVT>(new TwoStepNVT(sysdef_1, group_all_1, thermo_1, tau, T_variant_1));
        if (exec_conf->getRank() == 0)
            two_step_nvt_2 = boost::shared_ptr<TwoStepNVT>(new TwoStepNVT(sysdef_2, group_all_2, thermo_2, tau, T_variant_2));
        }

    nvt_1->addIntegrationMethod(two_step_nvt_1);
    nvt_1->addForceCompute(fc_1);
    nvt_1->setCommunicator(comm);

    if (exec_conf->getRank() == 0)
        {
        nvt_2->addIntegrationMethod(two_step_nvt_2);
        nvt_2->addForceCompute(fc_2);
        }

    unsigned int ndof = nvt_1->getNDOF(group_all_1);
    if (exec_conf->getRank() == 0)
        BOOST_CHECK_EQUAL(ndof, nvt_2->getNDOF(group_all_2));

    thermo_1->setNDOF(ndof);

    if (exec_conf->getRank() == 0)
        thermo_2->setNDOF(ndof);

    nvt_1->prepRun(0);

    if (exec_conf->getRank() == 0)
        nvt_2->prepRun(0);

    SnapshotParticleData snap_1(N);
    SnapshotParticleData snap_2(N);
    for (int i=0; i< 100; i++)
        {
        // compare temperatures
        if (exec_conf->getRank() == 0)
            BOOST_CHECK_CLOSE(thermo_1->getTemperature(), thermo_2->getTemperature(), tol_small);

//       if (world->rank() ==0)
//           std::cout << "step " << i << std::endl;
        Scalar rough_tol = 15.0;

        // in the first five steps, compare all accelerations and velocities
        // beyond this number of steps, trajectories will generally diverge, since they are chaotic
        // compare the snapshot of the parallel simulation
        if (i < 5)
            {
            pdata_1->takeSnapshot(snap_1);
            // ... against the serial simulation

            if (exec_conf->getRank() == 0)
                {
                pdata_2->takeSnapshot(snap_2);
                // check position, velocity and acceleration
                for (unsigned int j = 0; j < N; j++)
                    {
                    // we do not check positions (or we would need to pull back vectors over the boundaries)
                    //MY_BOOST_CHECK_CLOSE(snap_1.pos[j].x, snap_2.pos[j].x, rough_tol);
                    //MY_BOOST_CHECK_CLOSE(snap_1.pos[j].y, snap_2.pos[j].y, rough_tol);
                    //MY_BOOST_CHECK_CLOSE(snap_1.pos[j].z, snap_2.pos[j].z, rough_tol);

                    MY_BOOST_CHECK_CLOSE(snap_1.vel[j].x, snap_2.vel[j].x, rough_tol);
                    MY_BOOST_CHECK_CLOSE(snap_1.vel[j].y, snap_2.vel[j].y, rough_tol);
                    MY_BOOST_CHECK_CLOSE(snap_1.vel[j].z, snap_2.vel[j].z, rough_tol);

                    MY_BOOST_CHECK_CLOSE(snap_1.accel[j].x, snap_2.accel[j].x, rough_tol);
                    MY_BOOST_CHECK_CLOSE(snap_1.accel[j].y, snap_2.accel[j].y, rough_tol);
                    MY_BOOST_CHECK_CLOSE(snap_1.accel[j].z, snap_2.accel[j].z, rough_tol);
                    }
                }
            }
        nvt_1->update(i);
        if (exec_conf->getRank() == 0)
            nvt_2->update(i);
        }

}

//! Tests MPI domain decomposition with NVT integrator
BOOST_AUTO_TEST_CASE( DomainDecomposition_NVT_test )
    {
    test_nvt_integrator_mpi(exec_conf_cpu);
    }

#ifdef ENABLE_CUDA
//! Tests MPI domain decomposition with NVT integrator on the GPU
BOOST_AUTO_TEST_CASE( DomainDecomposition_NVT_test_GPU )
    {
    test_nvt_integrator_mpi(exec_conf_gpu);
    }
#endif
<|endoftext|>


<commit_before>/*
 * This file is open source software, licensed to you under the terms
 * of the Apache License, Version 2.0 (the "License").  See the NOTICE file
 * distributed with this work for additional information regarding copyright
 * ownership.  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.
 */
/*
 * Copyright (C) 2014 Cloudius Systems, Ltd.
 */

#ifndef CIRCULAR_BUFFER_HH_
#define CIRCULAR_BUFFER_HH_

// A growable double-ended queue container that can be efficiently
// extended (and shrunk) from both ends.  Implementation is a single
// storage vector.
//
// Similar to libstdc++'s std::deque, except that it uses a single level
// store, and so is more efficient for simple stored items.
// Similar to boost::circular_buffer_space_optimized, except it uses
// uninitialized storage for unoccupied elements (and thus move/copy
// constructors instead of move/copy assignments, which are less efficient).

#include "transfer.hh"
#include "bitops.hh"
#include <memory>
#include <algorithm>

template <typename T, typename Alloc = std::allocator<T>>
class circular_buffer {
    struct impl : Alloc {
        T* storage = nullptr;
        // begin, end interpreted (mod capacity)
        size_t begin = 0;
        size_t end = 0;
        size_t capacity = 0;
    };
    impl _impl;
public:
    using value_type = T;
    using size_type = size_t;
    using reference = T&;
    using pointer = T*;
    using const_reference = const T&;
    using const_pointer = const T*;
public:
    circular_buffer() = default;
    circular_buffer(circular_buffer&& X);
    circular_buffer(const circular_buffer& X) = delete;
    ~circular_buffer();
    circular_buffer& operator=(const circular_buffer&) = delete;
    circular_buffer& operator=(circular_buffer&& b) noexcept;
    void push_front(const T& data);
    void push_front(T&& data);
    template <typename... A>
    void emplace_front(A&&... args);
    void push_back(const T& data);
    void push_back(T&& data);
    template <typename... A>
    void emplace_back(A&&... args);
    T& front();
    T& back();
    void pop_front();
    void pop_back();
    bool empty() const;
    size_t size() const;
    size_t capacity() const;
    void reserve(size_t);
    T& operator[](size_t idx);
    template <typename Func>
    void for_each(Func func);
    // access an element, may return wrong or destroyed element
    // only useful if you do not rely on data accuracy (e.g. prefetch)
    T& access_element_unsafe(size_t idx);
private:
    void expand();
    void expand(size_t);
    void maybe_expand(size_t nr = 1);
    size_t mask(size_t idx) const;

    template<typename CB, typename ValueType>
    struct cbiterator : std::iterator<std::random_access_iterator_tag, ValueType> {
        typedef std::iterator<std::random_access_iterator_tag, ValueType> super_t;

        ValueType& operator*() const { return cb->_impl.storage[cb->mask(idx)]; }
        ValueType* operator->() const { return &cb->_impl.storage[cb->mask(idx)]; }
        // prefix
        cbiterator<CB, ValueType>& operator++() {
            idx++;
            return *this;
        }
        // postfix
        cbiterator<CB, ValueType> operator++(int unused) {
            auto v = *this;
            idx++;
            return v;
        }
        // prefix
        cbiterator<CB, ValueType>& operator--() {
            idx--;
            return *this;
        }
        // postfix
        cbiterator<CB, ValueType> operator--(int unused) {
            auto v = *this;
            idx--;
            return v;
        }
        cbiterator<CB, ValueType> operator+(typename super_t::difference_type n) const {
            return cbiterator<CB, ValueType>(cb, idx + n);
        }
        cbiterator<CB, ValueType> operator-(typename super_t::difference_type n) const {
            return cbiterator<CB, ValueType>(cb, idx - n);
        }
        cbiterator<CB, ValueType>& operator+=(typename super_t::difference_type n) {
            idx += n;
            return *this;
        }
        cbiterator<CB, ValueType>& operator-=(typename super_t::difference_type n) {
            idx -= n;
            return *this;
        }
        bool operator==(const cbiterator<CB, ValueType>& rhs) const {
            return idx == rhs.idx;
        }
        bool operator!=(const cbiterator<CB, ValueType>& rhs) const {
            return idx != rhs.idx;
        }
        bool operator<(const cbiterator<CB, ValueType>& rhs) const {
            return idx < rhs.idx;
        }
        bool operator>(const cbiterator<CB, ValueType>& rhs) const {
            return idx > rhs.idx;
        }
        bool operator>=(const cbiterator<CB, ValueType>& rhs) const {
            return idx >= rhs.idx;
        }
        bool operator<=(const cbiterator<CB, ValueType>& rhs) const {
            return idx <= rhs.idx;
        }
       typename super_t::difference_type operator-(const cbiterator<CB, ValueType>& rhs) const {
            return idx - rhs.idx;
        }
    private:
        CB* cb;
        size_t idx;
        cbiterator<CB, ValueType>(CB* b, size_t i) : cb(b), idx(i) {}
        friend class circular_buffer;
    };
    friend class iterator;

public:
    typedef cbiterator<circular_buffer, T> iterator;
    typedef cbiterator<const circular_buffer, const T> const_iterator;

    iterator begin() {
        return iterator(this, _impl.begin);
    }
    const_iterator begin() const {
        return const_iterator(this, _impl.begin);
    }
    iterator end() {
        return iterator(this, _impl.end);
    }
    const_iterator end() const {
        return const_iterator(this, _impl.end);
    }
    const_iterator cbegin() const {
        return const_iterator(this, _impl.begin);
    }
    const_iterator cend() const {
        return const_iterator(this, _impl.end);
    }
};

template <typename T, typename Alloc>
inline
size_t
circular_buffer<T, Alloc>::mask(size_t idx) const {
    return idx & (_impl.capacity - 1);
}

template <typename T, typename Alloc>
inline
bool
circular_buffer<T, Alloc>::empty() const {
    return _impl.begin == _impl.end;
}

template <typename T, typename Alloc>
inline
size_t
circular_buffer<T, Alloc>::size() const {
    return _impl.end - _impl.begin;
}

template <typename T, typename Alloc>
inline
size_t
circular_buffer<T, Alloc>::capacity() const {
    return _impl.capacity;
}

template <typename T, typename Alloc>
inline
void
circular_buffer<T, Alloc>::reserve(size_t size) {
    if (capacity() < size) {
        // Make sure that the new capacity is a power of two.
        expand(size_t(1) << log2ceil(size));
    }
}

template <typename T, typename Alloc>
inline
circular_buffer<T, Alloc>::circular_buffer(circular_buffer&& x)
    : _impl(std::move(x._impl)) {
    x._impl = {};
}

template <typename T, typename Alloc>
inline
circular_buffer<T, Alloc>& circular_buffer<T, Alloc>::operator=(circular_buffer&& x) noexcept {
    if (this != &x) {
        this->~circular_buffer();
        new (this) circular_buffer(std::move(x));
    }
    return *this;
}

template <typename T, typename Alloc>
template <typename Func>
inline
void
circular_buffer<T, Alloc>::for_each(Func func) {
    auto s = _impl.storage;
    auto m = _impl.capacity - 1;
    for (auto i = _impl.begin; i != _impl.end; ++i) {
        func(s[i & m]);
    }
}

template <typename T, typename Alloc>
inline
circular_buffer<T, Alloc>::~circular_buffer() {
    for_each([this] (T& obj) {
        _impl.destroy(&obj);
    });
    _impl.deallocate(_impl.storage, _impl.capacity);
}

template <typename T, typename Alloc>
void
circular_buffer<T, Alloc>::expand() {
    expand(std::max<size_t>(_impl.capacity * 2, 1));
}

template <typename T, typename Alloc>
void
circular_buffer<T, Alloc>::expand(size_t new_cap) {
    auto new_storage = _impl.allocate(new_cap);
    auto p = new_storage;
    try {
        for_each([this, &p] (T& obj) {
            transfer_pass1(_impl, &obj, p);
            p++;
        });
    } catch (...) {
        while (p != new_storage) {
            _impl.destroy(--p);
        }
        _impl.deallocate(new_storage, new_cap);
        throw;
    }
    p = new_storage;
    for_each([this, &p] (T& obj) {
        transfer_pass2(_impl, &obj, p++);
    });
    std::swap(_impl.storage, new_storage);
    std::swap(_impl.capacity, new_cap);
    _impl.begin = 0;
    _impl.end = p - _impl.storage;
    _impl.deallocate(new_storage, new_cap);
}

template <typename T, typename Alloc>
inline
void
circular_buffer<T, Alloc>::maybe_expand(size_t nr) {
    if (_impl.end - _impl.begin + nr > _impl.capacity) {
        expand();
    }
}

template <typename T, typename Alloc>
inline
void
circular_buffer<T, Alloc>::push_front(const T& data) {
    maybe_expand();
    auto p = &_impl.storage[mask(_impl.begin - 1)];
    _impl.construct(p, data);
    --_impl.begin;
}

template <typename T, typename Alloc>
inline
void
circular_buffer<T, Alloc>::push_front(T&& data) {
    maybe_expand();
    auto p = &_impl.storage[mask(_impl.begin - 1)];
    _impl.construct(p, std::move(data));
    --_impl.begin;
}

template <typename T, typename Alloc>
template <typename... Args>
inline
void
circular_buffer<T, Alloc>::emplace_front(Args&&... args) {
    maybe_expand();
    auto p = &_impl.storage[mask(_impl.begin - 1)];
    _impl.construct(p, std::forward<Args>(args)...);
    --_impl.begin;
}

template <typename T, typename Alloc>
inline
void
circular_buffer<T, Alloc>::push_back(const T& data) {
    maybe_expand();
    auto p = &_impl.storage[mask(_impl.end)];
    _impl.construct(p, data);
    ++_impl.end;
}

template <typename T, typename Alloc>
inline
void
circular_buffer<T, Alloc>::push_back(T&& data) {
    maybe_expand();
    auto p = &_impl.storage[mask(_impl.end)];
    _impl.construct(p, std::move(data));
    ++_impl.end;
}

template <typename T, typename Alloc>
template <typename... Args>
inline
void
circular_buffer<T, Alloc>::emplace_back(Args&&... args) {
    maybe_expand();
    auto p = &_impl.storage[mask(_impl.end)];
    _impl.construct(p, std::forward<Args>(args)...);
    ++_impl.end;
}

template <typename T, typename Alloc>
inline
T&
circular_buffer<T, Alloc>::front() {
    return _impl.storage[mask(_impl.begin)];
}

template <typename T, typename Alloc>
inline
T&
circular_buffer<T, Alloc>::back() {
    return _impl.storage[mask(_impl.end - 1)];
}

template <typename T, typename Alloc>
inline
void
circular_buffer<T, Alloc>::pop_front() {
    _impl.destroy(&front());
    ++_impl.begin;
}

template <typename T, typename Alloc>
inline
void
circular_buffer<T, Alloc>::pop_back() {
    _impl.destroy(&back());
    --_impl.end;
}

template <typename T, typename Alloc>
inline
T&
circular_buffer<T, Alloc>::operator[](size_t idx) {
    return _impl.storage[mask(_impl.begin + idx)];
}

template <typename T, typename Alloc>
inline
T&
circular_buffer<T, Alloc>::access_element_unsafe(size_t idx) {
    return _impl.storage[mask(_impl.begin + idx)];
}

#endif /* CIRCULAR_BUFFER_HH_ */
<commit_msg>circular_buffer: Introduce erase()<commit_after>/*
 * This file is open source software, licensed to you under the terms
 * of the Apache License, Version 2.0 (the "License").  See the NOTICE file
 * distributed with this work for additional information regarding copyright
 * ownership.  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.
 */
/*
 * Copyright (C) 2014 Cloudius Systems, Ltd.
 */

#ifndef CIRCULAR_BUFFER_HH_
#define CIRCULAR_BUFFER_HH_

// A growable double-ended queue container that can be efficiently
// extended (and shrunk) from both ends.  Implementation is a single
// storage vector.
//
// Similar to libstdc++'s std::deque, except that it uses a single level
// store, and so is more efficient for simple stored items.
// Similar to boost::circular_buffer_space_optimized, except it uses
// uninitialized storage for unoccupied elements (and thus move/copy
// constructors instead of move/copy assignments, which are less efficient).

#include "transfer.hh"
#include "bitops.hh"
#include <memory>
#include <algorithm>

template <typename T, typename Alloc = std::allocator<T>>
class circular_buffer {
    struct impl : Alloc {
        T* storage = nullptr;
        // begin, end interpreted (mod capacity)
        size_t begin = 0;
        size_t end = 0;
        size_t capacity = 0;
    };
    impl _impl;
public:
    using value_type = T;
    using size_type = size_t;
    using reference = T&;
    using pointer = T*;
    using const_reference = const T&;
    using const_pointer = const T*;
public:
    circular_buffer() = default;
    circular_buffer(circular_buffer&& X);
    circular_buffer(const circular_buffer& X) = delete;
    ~circular_buffer();
    circular_buffer& operator=(const circular_buffer&) = delete;
    circular_buffer& operator=(circular_buffer&& b) noexcept;
    void push_front(const T& data);
    void push_front(T&& data);
    template <typename... A>
    void emplace_front(A&&... args);
    void push_back(const T& data);
    void push_back(T&& data);
    template <typename... A>
    void emplace_back(A&&... args);
    T& front();
    T& back();
    void pop_front();
    void pop_back();
    bool empty() const;
    size_t size() const;
    size_t capacity() const;
    void reserve(size_t);
    T& operator[](size_t idx);
    template <typename Func>
    void for_each(Func func);
    // access an element, may return wrong or destroyed element
    // only useful if you do not rely on data accuracy (e.g. prefetch)
    T& access_element_unsafe(size_t idx);
private:
    void expand();
    void expand(size_t);
    void maybe_expand(size_t nr = 1);
    size_t mask(size_t idx) const;

    template<typename CB, typename ValueType>
    struct cbiterator : std::iterator<std::random_access_iterator_tag, ValueType> {
        typedef std::iterator<std::random_access_iterator_tag, ValueType> super_t;

        ValueType& operator*() const { return cb->_impl.storage[cb->mask(idx)]; }
        ValueType* operator->() const { return &cb->_impl.storage[cb->mask(idx)]; }
        // prefix
        cbiterator<CB, ValueType>& operator++() {
            idx++;
            return *this;
        }
        // postfix
        cbiterator<CB, ValueType> operator++(int unused) {
            auto v = *this;
            idx++;
            return v;
        }
        // prefix
        cbiterator<CB, ValueType>& operator--() {
            idx--;
            return *this;
        }
        // postfix
        cbiterator<CB, ValueType> operator--(int unused) {
            auto v = *this;
            idx--;
            return v;
        }
        cbiterator<CB, ValueType> operator+(typename super_t::difference_type n) const {
            return cbiterator<CB, ValueType>(cb, idx + n);
        }
        cbiterator<CB, ValueType> operator-(typename super_t::difference_type n) const {
            return cbiterator<CB, ValueType>(cb, idx - n);
        }
        cbiterator<CB, ValueType>& operator+=(typename super_t::difference_type n) {
            idx += n;
            return *this;
        }
        cbiterator<CB, ValueType>& operator-=(typename super_t::difference_type n) {
            idx -= n;
            return *this;
        }
        bool operator==(const cbiterator<CB, ValueType>& rhs) const {
            return idx == rhs.idx;
        }
        bool operator!=(const cbiterator<CB, ValueType>& rhs) const {
            return idx != rhs.idx;
        }
        bool operator<(const cbiterator<CB, ValueType>& rhs) const {
            return idx < rhs.idx;
        }
        bool operator>(const cbiterator<CB, ValueType>& rhs) const {
            return idx > rhs.idx;
        }
        bool operator>=(const cbiterator<CB, ValueType>& rhs) const {
            return idx >= rhs.idx;
        }
        bool operator<=(const cbiterator<CB, ValueType>& rhs) const {
            return idx <= rhs.idx;
        }
       typename super_t::difference_type operator-(const cbiterator<CB, ValueType>& rhs) const {
            return idx - rhs.idx;
        }
    private:
        CB* cb;
        size_t idx;
        cbiterator<CB, ValueType>(CB* b, size_t i) : cb(b), idx(i) {}
        friend class circular_buffer;
    };
    friend class iterator;

public:
    typedef cbiterator<circular_buffer, T> iterator;
    typedef cbiterator<const circular_buffer, const T> const_iterator;

    iterator begin() {
        return iterator(this, _impl.begin);
    }
    const_iterator begin() const {
        return const_iterator(this, _impl.begin);
    }
    iterator end() {
        return iterator(this, _impl.end);
    }
    const_iterator end() const {
        return const_iterator(this, _impl.end);
    }
    const_iterator cbegin() const {
        return const_iterator(this, _impl.begin);
    }
    const_iterator cend() const {
        return const_iterator(this, _impl.end);
    }
    iterator erase(iterator first, iterator last);
};

template <typename T, typename Alloc>
inline
size_t
circular_buffer<T, Alloc>::mask(size_t idx) const {
    return idx & (_impl.capacity - 1);
}

template <typename T, typename Alloc>
inline
bool
circular_buffer<T, Alloc>::empty() const {
    return _impl.begin == _impl.end;
}

template <typename T, typename Alloc>
inline
size_t
circular_buffer<T, Alloc>::size() const {
    return _impl.end - _impl.begin;
}

template <typename T, typename Alloc>
inline
size_t
circular_buffer<T, Alloc>::capacity() const {
    return _impl.capacity;
}

template <typename T, typename Alloc>
inline
void
circular_buffer<T, Alloc>::reserve(size_t size) {
    if (capacity() < size) {
        // Make sure that the new capacity is a power of two.
        expand(size_t(1) << log2ceil(size));
    }
}

template <typename T, typename Alloc>
inline
circular_buffer<T, Alloc>::circular_buffer(circular_buffer&& x)
    : _impl(std::move(x._impl)) {
    x._impl = {};
}

template <typename T, typename Alloc>
inline
circular_buffer<T, Alloc>& circular_buffer<T, Alloc>::operator=(circular_buffer&& x) noexcept {
    if (this != &x) {
        this->~circular_buffer();
        new (this) circular_buffer(std::move(x));
    }
    return *this;
}

template <typename T, typename Alloc>
template <typename Func>
inline
void
circular_buffer<T, Alloc>::for_each(Func func) {
    auto s = _impl.storage;
    auto m = _impl.capacity - 1;
    for (auto i = _impl.begin; i != _impl.end; ++i) {
        func(s[i & m]);
    }
}

template <typename T, typename Alloc>
inline
circular_buffer<T, Alloc>::~circular_buffer() {
    for_each([this] (T& obj) {
        _impl.destroy(&obj);
    });
    _impl.deallocate(_impl.storage, _impl.capacity);
}

template <typename T, typename Alloc>
void
circular_buffer<T, Alloc>::expand() {
    expand(std::max<size_t>(_impl.capacity * 2, 1));
}

template <typename T, typename Alloc>
void
circular_buffer<T, Alloc>::expand(size_t new_cap) {
    auto new_storage = _impl.allocate(new_cap);
    auto p = new_storage;
    try {
        for_each([this, &p] (T& obj) {
            transfer_pass1(_impl, &obj, p);
            p++;
        });
    } catch (...) {
        while (p != new_storage) {
            _impl.destroy(--p);
        }
        _impl.deallocate(new_storage, new_cap);
        throw;
    }
    p = new_storage;
    for_each([this, &p] (T& obj) {
        transfer_pass2(_impl, &obj, p++);
    });
    std::swap(_impl.storage, new_storage);
    std::swap(_impl.capacity, new_cap);
    _impl.begin = 0;
    _impl.end = p - _impl.storage;
    _impl.deallocate(new_storage, new_cap);
}

template <typename T, typename Alloc>
inline
void
circular_buffer<T, Alloc>::maybe_expand(size_t nr) {
    if (_impl.end - _impl.begin + nr > _impl.capacity) {
        expand();
    }
}

template <typename T, typename Alloc>
inline
void
circular_buffer<T, Alloc>::push_front(const T& data) {
    maybe_expand();
    auto p = &_impl.storage[mask(_impl.begin - 1)];
    _impl.construct(p, data);
    --_impl.begin;
}

template <typename T, typename Alloc>
inline
void
circular_buffer<T, Alloc>::push_front(T&& data) {
    maybe_expand();
    auto p = &_impl.storage[mask(_impl.begin - 1)];
    _impl.construct(p, std::move(data));
    --_impl.begin;
}

template <typename T, typename Alloc>
template <typename... Args>
inline
void
circular_buffer<T, Alloc>::emplace_front(Args&&... args) {
    maybe_expand();
    auto p = &_impl.storage[mask(_impl.begin - 1)];
    _impl.construct(p, std::forward<Args>(args)...);
    --_impl.begin;
}

template <typename T, typename Alloc>
inline
void
circular_buffer<T, Alloc>::push_back(const T& data) {
    maybe_expand();
    auto p = &_impl.storage[mask(_impl.end)];
    _impl.construct(p, data);
    ++_impl.end;
}

template <typename T, typename Alloc>
inline
void
circular_buffer<T, Alloc>::push_back(T&& data) {
    maybe_expand();
    auto p = &_impl.storage[mask(_impl.end)];
    _impl.construct(p, std::move(data));
    ++_impl.end;
}

template <typename T, typename Alloc>
template <typename... Args>
inline
void
circular_buffer<T, Alloc>::emplace_back(Args&&... args) {
    maybe_expand();
    auto p = &_impl.storage[mask(_impl.end)];
    _impl.construct(p, std::forward<Args>(args)...);
    ++_impl.end;
}

template <typename T, typename Alloc>
inline
T&
circular_buffer<T, Alloc>::front() {
    return _impl.storage[mask(_impl.begin)];
}

template <typename T, typename Alloc>
inline
T&
circular_buffer<T, Alloc>::back() {
    return _impl.storage[mask(_impl.end - 1)];
}

template <typename T, typename Alloc>
inline
void
circular_buffer<T, Alloc>::pop_front() {
    _impl.destroy(&front());
    ++_impl.begin;
}

template <typename T, typename Alloc>
inline
void
circular_buffer<T, Alloc>::pop_back() {
    _impl.destroy(&back());
    --_impl.end;
}

template <typename T, typename Alloc>
inline
T&
circular_buffer<T, Alloc>::operator[](size_t idx) {
    return _impl.storage[mask(_impl.begin + idx)];
}

template <typename T, typename Alloc>
inline
T&
circular_buffer<T, Alloc>::access_element_unsafe(size_t idx) {
    return _impl.storage[mask(_impl.begin + idx)];
}

template <typename T, typename Alloc>
inline
typename circular_buffer<T, Alloc>::iterator
circular_buffer<T, Alloc>::erase(iterator first, iterator last) {
    static_assert(std::is_nothrow_move_assignable<T>::value, "erase() assumes move assignment does not throw");
    if (first == last) {
        return last;
    }
    // Move to the left or right depending on which would result in least amount of moves.
    // This also guarantees that iterators will be stable when removing from either front or back.
    if (std::distance(begin(), first) < std::distance(last, end())) {
        auto new_start = std::move_backward(begin(), first, last);
        auto i = begin();
        while (i < new_start) {
            _impl.destroy(&*i++);
        }
        _impl.begin = new_start.idx;
        return last;
    } else {
        auto new_end = std::move(last, end(), first);
        auto i = new_end;
        auto e = end();
        while (i < e) {
            _impl.destroy(&*i++);
        }
        _impl.end = new_end.idx;
        return first;
    }
}

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


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

#include "chrome/common/ipc_message.h"

#include "base/logging.h"
#include "build/build_config.h"

namespace IPC {

//------------------------------------------------------------------------------

Message::~Message() {
}

Message::Message()
    : Pickle(sizeof(Header)) {
  header()->routing = header()->type = header()->flags = 0;
#if defined(OS_POSIX)
  header()->num_fds = 0;
#endif
  InitLoggingVariables();
}

Message::Message(int32 routing_id, uint16 type, PriorityValue priority)
    : Pickle(sizeof(Header)) {
  header()->routing = routing_id;
  header()->type = type;
  header()->flags = priority;
#if defined(OS_POSIX)
  header()->num_fds = 0;
#endif
  InitLoggingVariables();
}

Message::Message(const char* data, int data_len) : Pickle(data, data_len) {
  InitLoggingVariables();
}

Message::Message(const Message& other) : Pickle(other) {
  InitLoggingVariables();
  descriptor_set_.TakeFrom(&other.descriptor_set_);
}

void Message::InitLoggingVariables() {
#ifdef IPC_MESSAGE_LOG_ENABLED
  received_time_ = 0;
  dont_log_ = false;
  log_data_ = NULL;
#endif
}

Message& Message::operator=(const Message& other) {
  *static_cast<Pickle*>(this) = other;
  return *this;
}

#ifdef IPC_MESSAGE_LOG_ENABLED
void Message::set_sent_time(int64 time) {
  DCHECK((header()->flags & HAS_SENT_TIME_BIT) == 0);
  header()->flags |= HAS_SENT_TIME_BIT;
  WriteInt64(time);
}

int64 Message::sent_time() const {
  if ((header()->flags & HAS_SENT_TIME_BIT) == 0)
    return 0;

  const char* data = end_of_payload();
  data -= sizeof(int64);
  return *(reinterpret_cast<const int64*>(data));
}

void Message::set_received_time(int64 time) const {
  received_time_ = time;
}
#endif

}  // namespace IPC

<commit_msg>Windows: build fix<commit_after>// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/common/ipc_message.h"

#include "base/logging.h"
#include "build/build_config.h"

namespace IPC {

//------------------------------------------------------------------------------

Message::~Message() {
}

Message::Message()
    : Pickle(sizeof(Header)) {
  header()->routing = header()->type = header()->flags = 0;
#if defined(OS_POSIX)
  header()->num_fds = 0;
#endif
  InitLoggingVariables();
}

Message::Message(int32 routing_id, uint16 type, PriorityValue priority)
    : Pickle(sizeof(Header)) {
  header()->routing = routing_id;
  header()->type = type;
  header()->flags = priority;
#if defined(OS_POSIX)
  header()->num_fds = 0;
#endif
  InitLoggingVariables();
}

Message::Message(const char* data, int data_len) : Pickle(data, data_len) {
  InitLoggingVariables();
}

Message::Message(const Message& other) : Pickle(other) {
  InitLoggingVariables();
#if defined(OS_POSIX)
  descriptor_set_.TakeFrom(&other.descriptor_set_);
#endif
}

void Message::InitLoggingVariables() {
#ifdef IPC_MESSAGE_LOG_ENABLED
  received_time_ = 0;
  dont_log_ = false;
  log_data_ = NULL;
#endif
}

Message& Message::operator=(const Message& other) {
  *static_cast<Pickle*>(this) = other;
  return *this;
}

#ifdef IPC_MESSAGE_LOG_ENABLED
void Message::set_sent_time(int64 time) {
  DCHECK((header()->flags & HAS_SENT_TIME_BIT) == 0);
  header()->flags |= HAS_SENT_TIME_BIT;
  WriteInt64(time);
}

int64 Message::sent_time() const {
  if ((header()->flags & HAS_SENT_TIME_BIT) == 0)
    return 0;

  const char* data = end_of_payload();
  data -= sizeof(int64);
  return *(reinterpret_cast<const int64*>(data));
}

void Message::set_received_time(int64 time) const {
  received_time_ = time;
}
#endif

}  // namespace IPC

<|endoftext|>