<commit_before>// Ouzel by Elviss Strazdins

#include <cassert>
#include <algorithm>
#include "Camera.hpp"
#include "Actor.hpp"
#include "Layer.hpp"
#include "../core/Engine.hpp"
#include "../graphics/Graphics.hpp"
#include "../graphics/RenderDevice.hpp"

namespace ouzel::scene
{
    Camera::Camera(const math::Matrix<float, 4>& initProjection):
        projectionMode{ProjectionMode::custom}, projection{initProjection}

    {
        calculateViewProjection();
    }

    Camera::Camera(const math::Size<float, 2>& initTargetContentSize, ScaleMode initScaleMode):
        projectionMode{ProjectionMode::orthographic},
        targetContentSize{initTargetContentSize},
        scaleMode{initScaleMode}
    {
        calculateViewProjection();
    }

    Camera::Camera(float initFov, float initNearPlane, float initFarPlane):
        projectionMode{ProjectionMode::perspective},
        fov{initFov},
        nearPlane{initNearPlane},
        farPlane{initFarPlane}
    {
        calculateViewProjection();
    }

    Camera::~Camera()
    {
        if (layer) layer->removeCamera(*this);
    }

    void Camera::setActor(Actor* newActor)
    {
        Component::setActor(newActor);

        viewProjectionDirty = inverseViewProjectionDirty = true;
    }

    void Camera::setLayer(Layer* newLayer)
    {
        if (layer) layer->removeCamera(*this);

        Component::setLayer(newLayer);

        if (layer) layer->addCamera(*this);
    }

    void Camera::updateTransform()
    {
        Component::updateTransform();

        viewProjectionDirty = inverseViewProjectionDirty = true;
    }

    void Camera::calculateProjection() const
    {
        const math::Size<std::uint32_t, 2> renderTargetSize = renderTarget ?
            !renderTarget->getColorTextures().empty() ?
                renderTarget->getColorTextures()[0]->getSize() :
                renderTarget->getDepthTexture() ?
                    renderTarget->getDepthTexture()->getSize() :
                    math::Size<std::uint32_t, 2>{} :
            engine->getGraphics().getSize();

        renderViewport.position.v[0] = renderTargetSize.v[0] * viewport.position.v[0];
        renderViewport.position.v[1] = renderTargetSize.v[1] * viewport.position.v[1];
        renderViewport.size.v[0] = renderTargetSize.v[0] * viewport.size.v[0];
        renderViewport.size.v[1] = renderTargetSize.v[1] * viewport.size.v[1];

        assert(renderViewport.size.v[0] > 0.0F && renderViewport.size.v[1] > 0.0F);

        if (targetContentSize.v[0] > 0.0F && targetContentSize.v[1] > 0.0F)
        {
            contentScale.v[0] = renderViewport.size.v[0] / targetContentSize.v[0];
            contentScale.v[1] = renderViewport.size.v[1] / targetContentSize.v[1];

            switch (scaleMode)
            {
                case ScaleMode::noScale:
                {
                    break;
                }
                case ScaleMode::exactFit:
                {
                    contentScale.v[0] = 1.0F;
                    contentScale.v[1] = 1.0F;
                    break;
                }
                case ScaleMode::noBorder:
                {
                    contentScale.v[0] = contentScale.v[1] = std::max(contentScale.v[0], contentScale.v[1]);
                    break;
                }
                case ScaleMode::showAll:
                {
                    contentScale.v[0] = contentScale.v[1] = std::min(contentScale.v[0], contentScale.v[1]);
                    break;
                }
                default:
                    return;
            }

            contentSize = math::Size<float, 2>{
                renderViewport.size.v[0] / contentScale.v[0],
                renderViewport.size.v[1] / contentScale.v[1]
            };
            contentPosition = math::Vector<float, 2>{
                (contentSize.v[0] - targetContentSize.v[0]) / 2.0F,
                (contentSize.v[1] - targetContentSize.v[1]) / 2.0F
            };
        }
        else
        {
            contentScale = math::Vector<float, 2>{1.0F, 1.0F};
            contentSize = math::Size<float, 2>{renderViewport.size.v[0], renderViewport.size.v[1]};
            contentPosition = math::Vector<float, 2>{0.0F, 0.0F};
        }

        switch (projectionMode)
        {
            case ProjectionMode::custom:
                // do nothing
                break;
            case ProjectionMode::orthographic:
                setOrthographic(projection, contentSize.v[0], contentSize.v[1], -1.0F, 1.0F);
                break;
            case ProjectionMode::perspective:
                setPerspective(projection, fov, contentSize.v[0] / contentSize.v[1], nearPlane, farPlane);
                break;
            default:
                return;
        }

        projectionDirty = false;
        viewProjectionDirty = inverseViewProjectionDirty = true;
    }

    const math::Matrix<float, 4>& Camera::getViewProjection() const
    {
        if (viewProjectionDirty) calculateViewProjection();

        return viewProjection;
    }

    const math::Matrix<float, 4>& Camera::getRenderViewProjection() const
    {
        if (viewProjectionDirty) calculateViewProjection();

        return renderViewProjection;
    }

    const math::Matrix<float, 4>& Camera::getInverseViewProjection() const
    {
        if (inverseViewProjectionDirty)
        {
            inverseViewProjection = getViewProjection();
            invert(inverseViewProjection);

            inverseViewProjectionDirty = false;
        }

        return inverseViewProjection;
    }

    void Camera::calculateViewProjection() const
    {
        if (projectionDirty) calculateProjection();

        if (actor)
        {
            viewProjection = projection * actor->getInverseTransform();

            renderViewProjection = engine->getGraphics().getDevice()->getProjectionTransform(renderTarget != nullptr) * viewProjection;

            viewProjectionDirty = false;
        }
    }

    math::Vector<float, 3> Camera::convertNormalizedToWorld(const math::Vector<float, 2>& normalizedPosition) const
    {
        // convert window normalized to viewport clip position
        auto result = math::Vector<float, 3>{((normalizedPosition.v[0] - viewport.position.v[0]) / viewport.size.v[0] - 0.5F) * 2.0F,
                               (((1.0F - normalizedPosition.v[1]) - viewport.position.v[1]) / viewport.size.v[1] - 0.5F) * 2.0F,
                               0.0F};

        transformPoint(getInverseViewProjection(), result);

        return result;
    }

    math::Vector<float, 2> Camera::convertWorldToNormalized(const math::Vector<float, 3>& normalizedPosition) const
    {
        math::Vector<float, 3> result = normalizedPosition;
        transformPoint(getViewProjection(), result);

        // convert viewport clip position to window normalized
        return math::Vector<float, 2>{
            (result.v[0] / 2.0F + 0.5F) * viewport.size.v[0] + viewport.position.v[0],
            1.0F - ((result.v[1] / 2.0F + 0.5F) * viewport.size.v[1] + viewport.position.v[1])
        };
    }

    bool Camera::checkVisibility(const math::Matrix<float, 4>& boxTransform, const math::Box<float, 3>& box) const
    {
        if (projectionMode == ProjectionMode::orthographic)
        {
            // calculate center point of the box
            const auto diff = math::Vector<float, 2>{box.max - box.min};

            // offset the center point, so that it is relative to 0,0
            math::Vector<float, 3> v3p{
                box.min.v[0] + diff.v[0] / 2.0F,
                box.min.v[1] + diff.v[1] / 2.0F, 0.0F
            };

            // apply local transform to the center point
            transformPoint(boxTransform, v3p);

            // tranform the center to viewport's clip space
            const auto clipPos = math::Vector<float, 4>{v3p.v[0], v3p.v[1], v3p.v[2], 1.0F} * getViewProjection();

            assert(clipPos.v[3] != 0.0F);

            // normalize position of the center point
            const math::Vector<float, 2> v2p{
                (clipPos.v[0] / clipPos.v[3] + 1.0F) * 0.5F,
                (clipPos.v[1] / clipPos.v[3] + 1.0F) * 0.5F
            };

            // calculate half size
            const math::Size<float, 2> halfSize{diff.v[0] / 2.0F, diff.v[1] / 2.0F};

            // convert content size to world coordinates
            math::Size<float, 2> halfWorldSize{
                std::max(std::fabs(halfSize.v[0] * boxTransform.m.v[0] + halfSize.v[1] * boxTransform.m.v[4]),
                         std::fabs(halfSize.v[0] * boxTransform.m.v[0] - halfSize.v[1] * boxTransform.m.v[4])),
                std::max(std::fabs(halfSize.v[0] * boxTransform.m.v[1] + halfSize.v[1] * boxTransform.m.v[5]),
                         std::fabs(halfSize.v[0] * boxTransform.m.v[1] - halfSize.v[1] * boxTransform.m.v[5]))
            };

            // scale half size by camera projection to get the size in clip space coordinates
            halfWorldSize.v[0] *= (std::fabs(viewProjection.m.v[0]) + std::fabs(viewProjection.m.v[4])) / 2.0F;
            halfWorldSize.v[1] *= (std::fabs(viewProjection.m.v[1]) + std::fabs(viewProjection.m.v[5])) / 2.0F;

            // create visible rect in clip space
            const math::Rect<float> visibleRect{
                -halfWorldSize.v[0],
                -halfWorldSize.v[1],
                1.0F + halfWorldSize.v[0] * 2.0F,
                1.0F + halfWorldSize.v[1] * 2.0F
            };

            return containsPoint(visibleRect, v2p);
        }
        else
        {
            const auto modelViewProjection = getViewProjection() * boxTransform;
            const auto frustum = getFrustum(modelViewProjection);
            return isBoxInside(frustum, box);
        }
    }

    void Camera::setViewport(const math::Rect<float>& newViewport)
    {
        viewport = newViewport;
        projectionDirty = viewProjectionDirty = inverseViewProjectionDirty = true;
    }

    void Camera::setScaleMode(ScaleMode newScaleMode)
    {
        scaleMode = newScaleMode;
        projectionDirty = viewProjectionDirty = inverseViewProjectionDirty = true;
    }

    void Camera::setTargetContentSize(const math::Size<float, 2>& newTargetContentSize)
    {
        targetContentSize = newTargetContentSize;
        projectionDirty = viewProjectionDirty = inverseViewProjectionDirty = true;
    }

    void Camera::setRenderTarget(graphics::RenderTarget* newRenderTarget)
    {
        renderTarget = newRenderTarget;
        projectionDirty = viewProjectionDirty = inverseViewProjectionDirty = true;
    }

    void Camera::setDepthTest(bool newDepthTest)
    {
        depthTest = newDepthTest;

        if (depthTest)
            depthStencilState = std::make_unique<graphics::DepthStencilState>(engine->getGraphics(),
                                                                              true, true,
                                                                              graphics::CompareFunction::lessEqual,
                                                                              false,
                                                                              0xFFFFFFFF,
                                                                              0xFFFFFFFF,
                                                                              graphics::StencilOperation::keep,
                                                                              graphics::StencilOperation::keep,
                                                                              graphics::StencilOperation::keep,
                                                                              graphics::CompareFunction::always,
                                                                              graphics::StencilOperation::keep,
                                                                              graphics::StencilOperation::keep,
                                                                              graphics::StencilOperation::keep,
                                                                              graphics::CompareFunction::always);
        else
            depthStencilState.reset();
    }
}
<commit_msg>Remove the calculateViewProjection call from the constructors of Camera<commit_after>// Ouzel by Elviss Strazdins

#include <cassert>
#include <algorithm>
#include "Camera.hpp"
#include "Actor.hpp"
#include "Layer.hpp"
#include "../core/Engine.hpp"
#include "../graphics/Graphics.hpp"
#include "../graphics/RenderDevice.hpp"

namespace ouzel::scene
{
    Camera::Camera(const math::Matrix<float, 4>& initProjection):
        projectionMode{ProjectionMode::custom}, projection{initProjection}

    {
    }

    Camera::Camera(const math::Size<float, 2>& initTargetContentSize, ScaleMode initScaleMode):
        projectionMode{ProjectionMode::orthographic},
        targetContentSize{initTargetContentSize},
        scaleMode{initScaleMode}
    {
    }

    Camera::Camera(float initFov, float initNearPlane, float initFarPlane):
        projectionMode{ProjectionMode::perspective},
        fov{initFov},
        nearPlane{initNearPlane},
        farPlane{initFarPlane}
    {
    }

    Camera::~Camera()
    {
        if (layer) layer->removeCamera(*this);
    }

    void Camera::setActor(Actor* newActor)
    {
        Component::setActor(newActor);

        viewProjectionDirty = inverseViewProjectionDirty = true;
    }

    void Camera::setLayer(Layer* newLayer)
    {
        if (layer) layer->removeCamera(*this);

        Component::setLayer(newLayer);

        if (layer) layer->addCamera(*this);
    }

    void Camera::updateTransform()
    {
        Component::updateTransform();

        viewProjectionDirty = inverseViewProjectionDirty = true;
    }

    void Camera::calculateProjection() const
    {
        const math::Size<std::uint32_t, 2> renderTargetSize = renderTarget ?
            !renderTarget->getColorTextures().empty() ?
                renderTarget->getColorTextures()[0]->getSize() :
                renderTarget->getDepthTexture() ?
                    renderTarget->getDepthTexture()->getSize() :
                    math::Size<std::uint32_t, 2>{} :
            engine->getGraphics().getSize();

        renderViewport.position.v[0] = renderTargetSize.v[0] * viewport.position.v[0];
        renderViewport.position.v[1] = renderTargetSize.v[1] * viewport.position.v[1];
        renderViewport.size.v[0] = renderTargetSize.v[0] * viewport.size.v[0];
        renderViewport.size.v[1] = renderTargetSize.v[1] * viewport.size.v[1];

        assert(renderViewport.size.v[0] > 0.0F && renderViewport.size.v[1] > 0.0F);

        if (targetContentSize.v[0] > 0.0F && targetContentSize.v[1] > 0.0F)
        {
            contentScale.v[0] = renderViewport.size.v[0] / targetContentSize.v[0];
            contentScale.v[1] = renderViewport.size.v[1] / targetContentSize.v[1];

            switch (scaleMode)
            {
                case ScaleMode::noScale:
                {
                    break;
                }
                case ScaleMode::exactFit:
                {
                    contentScale.v[0] = 1.0F;
                    contentScale.v[1] = 1.0F;
                    break;
                }
                case ScaleMode::noBorder:
                {
                    contentScale.v[0] = contentScale.v[1] = std::max(contentScale.v[0], contentScale.v[1]);
                    break;
                }
                case ScaleMode::showAll:
                {
                    contentScale.v[0] = contentScale.v[1] = std::min(contentScale.v[0], contentScale.v[1]);
                    break;
                }
                default:
                    return;
            }

            contentSize = math::Size<float, 2>{
                renderViewport.size.v[0] / contentScale.v[0],
                renderViewport.size.v[1] / contentScale.v[1]
            };
            contentPosition = math::Vector<float, 2>{
                (contentSize.v[0] - targetContentSize.v[0]) / 2.0F,
                (contentSize.v[1] - targetContentSize.v[1]) / 2.0F
            };
        }
        else
        {
            contentScale = math::Vector<float, 2>{1.0F, 1.0F};
            contentSize = math::Size<float, 2>{renderViewport.size.v[0], renderViewport.size.v[1]};
            contentPosition = math::Vector<float, 2>{0.0F, 0.0F};
        }

        switch (projectionMode)
        {
            case ProjectionMode::custom:
                // do nothing
                break;
            case ProjectionMode::orthographic:
                setOrthographic(projection, contentSize.v[0], contentSize.v[1], -1.0F, 1.0F);
                break;
            case ProjectionMode::perspective:
                setPerspective(projection, fov, contentSize.v[0] / contentSize.v[1], nearPlane, farPlane);
                break;
            default:
                return;
        }

        projectionDirty = false;
        viewProjectionDirty = inverseViewProjectionDirty = true;
    }

    const math::Matrix<float, 4>& Camera::getViewProjection() const
    {
        if (viewProjectionDirty) calculateViewProjection();

        return viewProjection;
    }

    const math::Matrix<float, 4>& Camera::getRenderViewProjection() const
    {
        if (viewProjectionDirty) calculateViewProjection();

        return renderViewProjection;
    }

    const math::Matrix<float, 4>& Camera::getInverseViewProjection() const
    {
        if (inverseViewProjectionDirty)
        {
            inverseViewProjection = getViewProjection();
            invert(inverseViewProjection);

            inverseViewProjectionDirty = false;
        }

        return inverseViewProjection;
    }

    void Camera::calculateViewProjection() const
    {
        if (projectionDirty) calculateProjection();

        if (actor)
        {
            viewProjection = projection * actor->getInverseTransform();

            renderViewProjection = engine->getGraphics().getDevice()->getProjectionTransform(renderTarget != nullptr) * viewProjection;

            viewProjectionDirty = false;
        }
    }

    math::Vector<float, 3> Camera::convertNormalizedToWorld(const math::Vector<float, 2>& normalizedPosition) const
    {
        // convert window normalized to viewport clip position
        auto result = math::Vector<float, 3>{((normalizedPosition.v[0] - viewport.position.v[0]) / viewport.size.v[0] - 0.5F) * 2.0F,
                               (((1.0F - normalizedPosition.v[1]) - viewport.position.v[1]) / viewport.size.v[1] - 0.5F) * 2.0F,
                               0.0F};

        transformPoint(getInverseViewProjection(), result);

        return result;
    }

    math::Vector<float, 2> Camera::convertWorldToNormalized(const math::Vector<float, 3>& normalizedPosition) const
    {
        math::Vector<float, 3> result = normalizedPosition;
        transformPoint(getViewProjection(), result);

        // convert viewport clip position to window normalized
        return math::Vector<float, 2>{
            (result.v[0] / 2.0F + 0.5F) * viewport.size.v[0] + viewport.position.v[0],
            1.0F - ((result.v[1] / 2.0F + 0.5F) * viewport.size.v[1] + viewport.position.v[1])
        };
    }

    bool Camera::checkVisibility(const math::Matrix<float, 4>& boxTransform, const math::Box<float, 3>& box) const
    {
        if (projectionMode == ProjectionMode::orthographic)
        {
            // calculate center point of the box
            const auto diff = math::Vector<float, 2>{box.max - box.min};

            // offset the center point, so that it is relative to 0,0
            math::Vector<float, 3> v3p{
                box.min.v[0] + diff.v[0] / 2.0F,
                box.min.v[1] + diff.v[1] / 2.0F, 0.0F
            };

            // apply local transform to the center point
            transformPoint(boxTransform, v3p);

            // tranform the center to viewport's clip space
            const auto clipPos = math::Vector<float, 4>{v3p.v[0], v3p.v[1], v3p.v[2], 1.0F} * getViewProjection();

            assert(clipPos.v[3] != 0.0F);

            // normalize position of the center point
            const math::Vector<float, 2> v2p{
                (clipPos.v[0] / clipPos.v[3] + 1.0F) * 0.5F,
                (clipPos.v[1] / clipPos.v[3] + 1.0F) * 0.5F
            };

            // calculate half size
            const math::Size<float, 2> halfSize{diff.v[0] / 2.0F, diff.v[1] / 2.0F};

            // convert content size to world coordinates
            math::Size<float, 2> halfWorldSize{
                std::max(std::fabs(halfSize.v[0] * boxTransform.m.v[0] + halfSize.v[1] * boxTransform.m.v[4]),
                         std::fabs(halfSize.v[0] * boxTransform.m.v[0] - halfSize.v[1] * boxTransform.m.v[4])),
                std::max(std::fabs(halfSize.v[0] * boxTransform.m.v[1] + halfSize.v[1] * boxTransform.m.v[5]),
                         std::fabs(halfSize.v[0] * boxTransform.m.v[1] - halfSize.v[1] * boxTransform.m.v[5]))
            };

            // scale half size by camera projection to get the size in clip space coordinates
            halfWorldSize.v[0] *= (std::fabs(viewProjection.m.v[0]) + std::fabs(viewProjection.m.v[4])) / 2.0F;
            halfWorldSize.v[1] *= (std::fabs(viewProjection.m.v[1]) + std::fabs(viewProjection.m.v[5])) / 2.0F;

            // create visible rect in clip space
            const math::Rect<float> visibleRect{
                -halfWorldSize.v[0],
                -halfWorldSize.v[1],
                1.0F + halfWorldSize.v[0] * 2.0F,
                1.0F + halfWorldSize.v[1] * 2.0F
            };

            return containsPoint(visibleRect, v2p);
        }
        else
        {
            const auto modelViewProjection = getViewProjection() * boxTransform;
            const auto frustum = getFrustum(modelViewProjection);
            return isBoxInside(frustum, box);
        }
    }

    void Camera::setViewport(const math::Rect<float>& newViewport)
    {
        viewport = newViewport;
        projectionDirty = viewProjectionDirty = inverseViewProjectionDirty = true;
    }

    void Camera::setScaleMode(ScaleMode newScaleMode)
    {
        scaleMode = newScaleMode;
        projectionDirty = viewProjectionDirty = inverseViewProjectionDirty = true;
    }

    void Camera::setTargetContentSize(const math::Size<float, 2>& newTargetContentSize)
    {
        targetContentSize = newTargetContentSize;
        projectionDirty = viewProjectionDirty = inverseViewProjectionDirty = true;
    }

    void Camera::setRenderTarget(graphics::RenderTarget* newRenderTarget)
    {
        renderTarget = newRenderTarget;
        projectionDirty = viewProjectionDirty = inverseViewProjectionDirty = true;
    }

    void Camera::setDepthTest(bool newDepthTest)
    {
        depthTest = newDepthTest;

        if (depthTest)
            depthStencilState = std::make_unique<graphics::DepthStencilState>(engine->getGraphics(),
                                                                              true, true,
                                                                              graphics::CompareFunction::lessEqual,
                                                                              false,
                                                                              0xFFFFFFFF,
                                                                              0xFFFFFFFF,
                                                                              graphics::StencilOperation::keep,
                                                                              graphics::StencilOperation::keep,
                                                                              graphics::StencilOperation::keep,
                                                                              graphics::CompareFunction::always,
                                                                              graphics::StencilOperation::keep,
                                                                              graphics::StencilOperation::keep,
                                                                              graphics::StencilOperation::keep,
                                                                              graphics::CompareFunction::always);
        else
            depthStencilState.reset();
    }
}
<|endoftext|>


<commit_before>#include "buffer_t.h"
#include "JITCompiledModule.h"
#include "CodeGen.h"
#include "LLVM_Headers.h"
#include "Debug.h"

#include <string>

namespace Halide {
namespace Internal {

using std::string;

using namespace llvm;

// Wraps an execution engine. Takes ownership of the given module and
// the memory for jit compiled code.
class JITModuleHolder {
public:
    mutable RefCount ref_count;

    JITModuleHolder(llvm::ExecutionEngine *ee, llvm::Module *m, void (*shutdown)()) :
        execution_engine(ee),
        module(m),
        context(&m->getContext()),
        shutdown_thread_pool(shutdown) {
    }

    ~JITModuleHolder() {
        for (size_t i = 0; i < cleanup_routines.size(); i++) {
            void *ptr = reinterpret_bits<void *>(cleanup_routines[i]);
            debug(1) << "Calling target specific cleanup routine at " << ptr << "\n";
            (*cleanup_routines[i])();
        }

        shutdown_thread_pool();
        delete execution_engine;
        delete context;
        // No need to delete the module - deleting the execution engine should take care of that.
    }

    ExecutionEngine *execution_engine;
    Module *module;
    LLVMContext *context;
    void (*shutdown_thread_pool)();

    /** Do any target-specific module cleanup. */
    std::vector<void (*)()> cleanup_routines;
};

template<>
EXPORT RefCount &ref_count<JITModuleHolder>(const JITModuleHolder *f) {return f->ref_count;}

template<>
EXPORT void destroy<JITModuleHolder>(const JITModuleHolder *f) {delete f;}

namespace {

#ifdef __arm__
// On ARM we need to track the addresses of all the functions we
// retrieve so that we can flush the icache.
char *start, *end;
#endif

// Retrieve a function pointer from an llvm module, possibly by
// compiling it. Returns it by assigning to the last argument.
template<typename FP>
void hook_up_function_pointer(ExecutionEngine *ee, Module *mod, const string &name, bool must_succeed, FP *result) {

    assert(mod && ee);

    debug(2) << "Retrieving " << name << " from module\n";
    llvm::Function *fn = mod->getFunction(name);
    if (!fn) {
        if (must_succeed) {
            std::cerr << "Could not find function " << name << " in module\n";
            assert(false);
        } else {
            *result = NULL;
            return;
        }
    }

    debug(2) << "JIT Compiling " << name << "\n";
    void *f = ee->getPointerToFunction(fn);
    if (!f && must_succeed) {
        std::cerr << "Compiling " << name << " returned NULL\n";
        assert(false);
    }

    debug(2) << "Function " << name << " is at " << f << "\n";

    *result = reinterpret_bits<FP>(f);

    #ifdef __arm__
    if (start == NULL) {
        start = (char *)f;
        end = (char *)f;
    } else {
        start = std::min(start, (char *)f);
        end = std::max(end, (char *)f+32);
    }
    #endif
}

}

void JITCompiledModule::compile_module(CodeGen *cg, llvm::Module *m, const string &function_name) {

    // Make the execution engine
    debug(2) << "Creating new execution engine\n";
    string error_string;

    TargetOptions options;
    options.LessPreciseFPMADOption = true;
    options.NoFramePointerElim = false;
    options.AllowFPOpFusion = FPOpFusion::Fast;
    options.UnsafeFPMath = true;
    options.NoInfsFPMath = true;
    options.NoNaNsFPMath = true;
    options.HonorSignDependentRoundingFPMathOption = false;
    options.UseSoftFloat = false;
    options.FloatABIType =
        cg->use_soft_float_abi() ? FloatABI::Soft : FloatABI::Hard;
    options.NoZerosInBSS = false;
    options.GuaranteedTailCallOpt = false;
    options.DisableTailCalls = false;
    options.StackAlignmentOverride = 0;
    options.TrapFuncName = "";
    options.PositionIndependentExecutable = true;
    options.EnableSegmentedStacks = false;
    options.UseInitArray = false;

    EngineBuilder engine_builder(m);
    engine_builder.setTargetOptions(options);
    engine_builder.setErrorStr(&error_string);
    engine_builder.setEngineKind(EngineKind::JIT);
    #ifdef USE_MCJIT
    engine_builder.setUseMCJIT(true);
    JITMemoryManager *memory_manager = JITMemoryManager::CreateDefaultMemManager();
    engine_builder.setJITMemoryManager(memory_manager);
    #else
    engine_builder.setUseMCJIT(false);
    #endif
    engine_builder.setOptLevel(CodeGenOpt::Aggressive);
    engine_builder.setMCPU(cg->mcpu());
    engine_builder.setMAttrs(vec<string>(cg->mattrs()));
    ExecutionEngine *ee = engine_builder.create();
    if (!ee) std::cerr << error_string << "\n";
    assert(ee && "Couldn't create execution engine");
    // TODO: I don't think this is necessary, we shouldn't have any static constructors
    // ee->runStaticConstructorsDestructors(...);

    #ifdef __arm__
    start = end = NULL;
    #endif

    // Do any target-specific initialization
    cg->jit_init(ee, m);

    // Retrieve function pointers from the compiled module (which also
    // triggers compilation)
    debug(1) << "JIT compiling...\n";

    hook_up_function_pointer(ee, m, function_name, true, &function);

    void *function_address = reinterpret_bits<void *>(function);
    debug(1) << "JIT compiled function pointer " << function_address << "\n";

    hook_up_function_pointer(ee, m, function_name + "_jit_wrapper", true, &wrapped_function);
    hook_up_function_pointer(ee, m, "halide_copy_to_host", false, &copy_to_host);
    hook_up_function_pointer(ee, m, "halide_copy_to_dev", false, &copy_to_dev);
    hook_up_function_pointer(ee, m, "halide_free_dev_buffer", false, &free_dev_buffer);
    hook_up_function_pointer(ee, m, "halide_set_error_handler", true, &set_error_handler);
    hook_up_function_pointer(ee, m, "halide_set_custom_allocator", true, &set_custom_allocator);
    hook_up_function_pointer(ee, m, "halide_set_custom_do_par_for", true, &set_custom_do_par_for);
    hook_up_function_pointer(ee, m, "halide_set_custom_do_task", true, &set_custom_do_task);
    hook_up_function_pointer(ee, m, "halide_shutdown_thread_pool", true, &shutdown_thread_pool);

    debug(2) << "Finalizing object\n";
    ee->finalizeObject();

    // Stash the various objects that need to stay alive behind a reference-counted pointer.
    module = new JITModuleHolder(ee, m, shutdown_thread_pool);

    // Do any target-specific post-compilation module meddling
    cg->jit_finalize(ee, m, &module.ptr->cleanup_routines);

    #ifdef USE_MCJIT
    // Forcibly flushes the cache on arm
    memory_manager->finalizeMemory();
    #endif

    #ifdef __arm__
    // Flush each function from the dcache so that it gets pulled into
    // the icache correctly.

    // finalizeMemory should have done the trick, but as of Aug 28
    // 2013, it doesn't work unless we also manually flush the
    // cache. Otherwise the icache's view of the code is missing the
    // relocations, which gets really confusing to debug, because
    // gdb's view of the code uses the dcache, so the disassembly
    // isn't right.
    debug(2) << "Flushing cache from " << (void *)start
             << " to " << (void *)end << "\n";
    __clear_cache(start, end);
    #endif
}

}
}
<commit_msg>Remove call to finalizeMemory for the benefit of llvm 3.3<commit_after>#include "buffer_t.h"
#include "JITCompiledModule.h"
#include "CodeGen.h"
#include "LLVM_Headers.h"
#include "Debug.h"

#include <string>

namespace Halide {
namespace Internal {

using std::string;

using namespace llvm;

// Wraps an execution engine. Takes ownership of the given module and
// the memory for jit compiled code.
class JITModuleHolder {
public:
    mutable RefCount ref_count;

    JITModuleHolder(llvm::ExecutionEngine *ee, llvm::Module *m, void (*shutdown)()) :
        execution_engine(ee),
        module(m),
        context(&m->getContext()),
        shutdown_thread_pool(shutdown) {
    }

    ~JITModuleHolder() {
        for (size_t i = 0; i < cleanup_routines.size(); i++) {
            void *ptr = reinterpret_bits<void *>(cleanup_routines[i]);
            debug(1) << "Calling target specific cleanup routine at " << ptr << "\n";
            (*cleanup_routines[i])();
        }

        shutdown_thread_pool();
        delete execution_engine;
        delete context;
        // No need to delete the module - deleting the execution engine should take care of that.
    }

    ExecutionEngine *execution_engine;
    Module *module;
    LLVMContext *context;
    void (*shutdown_thread_pool)();

    /** Do any target-specific module cleanup. */
    std::vector<void (*)()> cleanup_routines;
};

template<>
EXPORT RefCount &ref_count<JITModuleHolder>(const JITModuleHolder *f) {return f->ref_count;}

template<>
EXPORT void destroy<JITModuleHolder>(const JITModuleHolder *f) {delete f;}

namespace {

#ifdef __arm__
// On ARM we need to track the addresses of all the functions we
// retrieve so that we can flush the icache.
char *start, *end;
#endif

// Retrieve a function pointer from an llvm module, possibly by
// compiling it. Returns it by assigning to the last argument.
template<typename FP>
void hook_up_function_pointer(ExecutionEngine *ee, Module *mod, const string &name, bool must_succeed, FP *result) {

    assert(mod && ee);

    debug(2) << "Retrieving " << name << " from module\n";
    llvm::Function *fn = mod->getFunction(name);
    if (!fn) {
        if (must_succeed) {
            std::cerr << "Could not find function " << name << " in module\n";
            assert(false);
        } else {
            *result = NULL;
            return;
        }
    }

    debug(2) << "JIT Compiling " << name << "\n";
    void *f = ee->getPointerToFunction(fn);
    if (!f && must_succeed) {
        std::cerr << "Compiling " << name << " returned NULL\n";
        assert(false);
    }

    debug(2) << "Function " << name << " is at " << f << "\n";

    *result = reinterpret_bits<FP>(f);

    #ifdef __arm__
    if (start == NULL) {
        start = (char *)f;
        end = (char *)f;
    } else {
        start = std::min(start, (char *)f);
        end = std::max(end, (char *)f+32);
    }
    #endif
}

}

void JITCompiledModule::compile_module(CodeGen *cg, llvm::Module *m, const string &function_name) {

    // Make the execution engine
    debug(2) << "Creating new execution engine\n";
    string error_string;

    TargetOptions options;
    options.LessPreciseFPMADOption = true;
    options.NoFramePointerElim = false;
    options.AllowFPOpFusion = FPOpFusion::Fast;
    options.UnsafeFPMath = true;
    options.NoInfsFPMath = true;
    options.NoNaNsFPMath = true;
    options.HonorSignDependentRoundingFPMathOption = false;
    options.UseSoftFloat = false;
    options.FloatABIType =
        cg->use_soft_float_abi() ? FloatABI::Soft : FloatABI::Hard;
    options.NoZerosInBSS = false;
    options.GuaranteedTailCallOpt = false;
    options.DisableTailCalls = false;
    options.StackAlignmentOverride = 0;
    options.TrapFuncName = "";
    options.PositionIndependentExecutable = true;
    options.EnableSegmentedStacks = false;
    options.UseInitArray = false;

    EngineBuilder engine_builder(m);
    engine_builder.setTargetOptions(options);
    engine_builder.setErrorStr(&error_string);
    engine_builder.setEngineKind(EngineKind::JIT);
    #ifdef USE_MCJIT
    engine_builder.setUseMCJIT(true);
    JITMemoryManager *memory_manager = JITMemoryManager::CreateDefaultMemManager();
    engine_builder.setJITMemoryManager(memory_manager);
    #else
    engine_builder.setUseMCJIT(false);
    #endif
    engine_builder.setOptLevel(CodeGenOpt::Aggressive);
    engine_builder.setMCPU(cg->mcpu());
    engine_builder.setMAttrs(vec<string>(cg->mattrs()));
    ExecutionEngine *ee = engine_builder.create();
    if (!ee) std::cerr << error_string << "\n";
    assert(ee && "Couldn't create execution engine");
    // TODO: I don't think this is necessary, we shouldn't have any static constructors
    // ee->runStaticConstructorsDestructors(...);

    #ifdef __arm__
    start = end = NULL;
    #endif

    // Do any target-specific initialization
    cg->jit_init(ee, m);

    // Retrieve function pointers from the compiled module (which also
    // triggers compilation)
    debug(1) << "JIT compiling...\n";

    hook_up_function_pointer(ee, m, function_name, true, &function);

    void *function_address = reinterpret_bits<void *>(function);
    debug(1) << "JIT compiled function pointer " << function_address << "\n";

    hook_up_function_pointer(ee, m, function_name + "_jit_wrapper", true, &wrapped_function);
    hook_up_function_pointer(ee, m, "halide_copy_to_host", false, &copy_to_host);
    hook_up_function_pointer(ee, m, "halide_copy_to_dev", false, &copy_to_dev);
    hook_up_function_pointer(ee, m, "halide_free_dev_buffer", false, &free_dev_buffer);
    hook_up_function_pointer(ee, m, "halide_set_error_handler", true, &set_error_handler);
    hook_up_function_pointer(ee, m, "halide_set_custom_allocator", true, &set_custom_allocator);
    hook_up_function_pointer(ee, m, "halide_set_custom_do_par_for", true, &set_custom_do_par_for);
    hook_up_function_pointer(ee, m, "halide_set_custom_do_task", true, &set_custom_do_task);
    hook_up_function_pointer(ee, m, "halide_shutdown_thread_pool", true, &shutdown_thread_pool);

    debug(2) << "Finalizing object\n";
    ee->finalizeObject();

    // Stash the various objects that need to stay alive behind a reference-counted pointer.
    module = new JITModuleHolder(ee, m, shutdown_thread_pool);

    // Do any target-specific post-compilation module meddling
    cg->jit_finalize(ee, m, &module.ptr->cleanup_routines);

    #ifdef __arm__
    // Flush each function from the dcache so that it gets pulled into
    // the icache correctly.

    // finalizeMemory should have done the trick, but as of Aug 28
    // 2013, it doesn't work unless we also manually flush the
    // cache. Otherwise the icache's view of the code is missing the
    // relocations, which gets really confusing to debug, because
    // gdb's view of the code uses the dcache, so the disassembly
    // isn't right.
    debug(2) << "Flushing cache from " << (void *)start
             << " to " << (void *)end << "\n";
    __clear_cache(start, end);
    #endif
}

}
}
<|endoftext|>


<commit_before>#include "GridMap.hpp"
#include <cmath>
#include "wrap2pi.h"

// basic constructor
GridMap::GridMap(ros::NodeHandle &private_nh) : cells(nullptr), grid_mutex(), seq(0), M_PI2(M_PI/2) {

    // the frame id
    private_nh.param<std::string>("grid_map_frame_id", frame_id, "map");

    // the grid map dimensions
    // the width
    private_nh.param("grid_map_width", width, 4000);

    // update width2
    width2 = width >> 1;

    // the height
    private_nh.param("grid_map_height", height, 4000);

    // update the height2
    height2 = height >> 1;

    // updates the grid map array size
    size = width*height;

    // range max
    private_nh.param("grid_map_range_max", range_max, 15.0);

    // resolution
    private_nh.param("grid_map_resolution", resolution, 0.05);

    // update the limit displacement
    displacement = range_max/resolution;

    // the alpha2 parameter
    private_nh.param("grid_map_alpha_2", alpha2, resolution*0.75);

    // the beta2 parameter
    private_nh.param("grid_map_beta_2", beta2, 0.008726646259971648);

    // origin x
    private_nh.param("grid_map_origin_x", origin_x, 0.0);

    // origin y
    private_nh.param("grid_map_origin_y", origin_y, 0.0);

    // orientation
    private_nh.param("grid_map_orientation", orientation, 0.0);

    // allocate the memmory
    cells = new MapCell[size];
    if (nullptr == cells) {
        throw std::bad_alloc();
    }

    float div = 1.0/(float)width;

    for (int i = 0; i < size; i++) {
        // set the status to undefined
        cells[i].status = 0;

        // calculates the world coordinates to every cell
        cells[i].xi = (origin_x + (i%width - width2)*resolution);
        cells[i].yi = (origin_y + (i*div - height2)*resolution);

    }

}

// basic destructor
GridMap::~GridMap() {
    if (nullptr != cells) {
        delete cells;
    }
}

// update the grid map
void GridMap::updateGridMap(const geometry_msgs::Pose& pose, const sensor_msgs::LaserScanConstPtr& ls) {

    tf::Quaternion qt(pose.orientation.x, pose.orientation.y, pose.orientation.z, pose.orientation.w);

    tf::Matrix3x3 m(qt);
    double theta, p_roll, p_pitch;
    m.getRPY(p_roll, p_pitch, theta);

    int leftLimit, rigthLimit, downLimit, upLimit;

    int x_map = std::floor((pose.position.x - origin_x)/resolution + 0.5) + width2;
    int y_map = std::floor((pose.position.y - origin_y)/resolution + 0.5) + height2;

    leftLimit = x_map - displacement;
    if (0 > leftLimit) {
        leftLimit = 0;
    }

    rigthLimit = x_map + displacement;
    if (width < rigthLimit) {
        rigthLimit = width;
    }

    upLimit = y_map + displacement;
    if (height < upLimit) {
        upLimit = height;
    }

    downLimit = y_map - displacement;
    if (0 > downLimit) {
        downLimit = 0;
    }

    // crictical area
    grid_mutex.lock();

    for (int j = downLimit; j < upLimit; j++) {
        for (int i = leftLimit; i < rigthLimit; i++) {

            MapCell *cell = &cells[MAP_INDEX(i, j)];

            if (4 > abs(i - x_map) && 4 > abs(j - y_map) && 1 > cell->status) {

                cell->status = -100;

            } else {

                cell->dist = std::sqrt(std::pow(cell->xi - pose.position.x, 2) + std::pow(cell->yi - pose.position.y, 2));

                cell->angle = mrpt::math::angDistance(theta, mrpt::math::wrapToPi(atan2(cell->yi - pose.position.y, cell->xi - pose.position.x)));

                // verify the perceptual field
                if (-M_PI2 <= cell->angle && M_PI2 >= cell->angle && cell->dist <= range_max) {

                    inverse_sensor_model(cell, ls);

                }

            }

        }

    }

    // unlock the grid
    grid_mutex.unlock();

}

// the inverse sensor model
void GridMap::inverse_sensor_model(MapCell *cell, const sensor_msgs::LaserScanConstPtr ls) {

    double range = ls->ranges[0];
    double angle = fabs(mrpt::math::angDistance(cell->angle, ls->angle_min));

    // iterate over the laser beams to find the nearest one
    for (int i = 1; i < ls->ranges.size(); i++) {

        double tmp = fabs(mrpt::math::angDistance(cell->angle, ls->angle_min + (i * ls->angle_increment)));

        if (tmp < angle) {
            range = ls->ranges[i];
            angle = tmp;
        } else {
            // it can be stoped
            break;
        }
    }

    // verify the update cases
   if (cell->dist <= range + alpha2 && angle <= beta2 && range <= range_max) {

        if (fabs(cell->dist - range) <= alpha2) {

            if (100 > cell->status) {

                if (-20 < cell->status) {

                    cell->status += 20;

                } else {

                    cell->status += 5;

                }

            }

        } else if (cell->dist < range) {

            if (-100 < cell->status) {

                if (0 > cell->status) {

                    cell->status -= 5;

                } else {

                    cell->status -= 1;

                }

            }

        }

    }

}

// draw the map
void GridMap::exportGridMap(nav_msgs::OccupancyGrid &occupancy) {

    // lock the map
//     grid_mutex.lock();

    // set the sequence
    occupancy.header.seq = seq;

    // time stamp
    occupancy.header.stamp = ros::Time::now();

    // frame_id
    occupancy.header.frame_id = (frame_id);

    // the meta data
    occupancy.info.map_load_time = ros::Time::now();

    // resolution
    occupancy.info.resolution = resolution;

    // width
    occupancy.info.width = width;

    // height
    occupancy.info.height = height;

    // origin - position
    occupancy.info.origin.position.x = origin_x - width2*resolution;
    occupancy.info.origin.position.y = origin_y - height2*resolution;
    occupancy.info.origin.position.z = 0.0;

    // origin - orientation
    occupancy.info.origin.orientation.x = 0.0;
    occupancy.info.origin.orientation.y = 0.0;
    occupancy.info.origin.orientation.z = 0.0;
    occupancy.info.origin.orientation.w = 1.0;

    // copy the cells
    for (int i = 0; i < size; i++) {

        if (0 < cells[i].status) {

            occupancy.data[i] = 100;

        } else if (-5 > cells[i].status) {

            occupancy.data[i] = 0;

        } else {

            occupancy.data[i] = -1;

        }
    }

    // unlock the map
//     grid_mutex.unlock();

    return;
}

<commit_msg>Confident<commit_after>#include "GridMap.hpp"
#include <cmath>
#include "wrap2pi.h"

// basic constructor
GridMap::GridMap(ros::NodeHandle &private_nh) : cells(nullptr), grid_mutex(), seq(0), M_PI2(M_PI/2) {

    // the frame id
    private_nh.param<std::string>("grid_map_frame_id", frame_id, "map");

    // the grid map dimensions
    // the width
    private_nh.param("grid_map_width", width, 4000);

    // update width2
    width2 = width >> 1;

    // the height
    private_nh.param("grid_map_height", height, 4000);

    // update the height2
    height2 = height >> 1;

    // updates the grid map array size
    size = width*height;

    // range max
    private_nh.param("grid_map_range_max", range_max, 15.0);

    // resolution
    private_nh.param("grid_map_resolution", resolution, 0.05);

    // update the limit displacement
    displacement = range_max/resolution;

    // the alpha2 parameter
    private_nh.param("grid_map_alpha_2", alpha2, resolution*0.75);

    // the beta2 parameter
    private_nh.param("grid_map_beta_2", beta2, 0.008726646259971648);

    // origin x
    private_nh.param("grid_map_origin_x", origin_x, 0.0);

    // origin y
    private_nh.param("grid_map_origin_y", origin_y, 0.0);

    // orientation
    private_nh.param("grid_map_orientation", orientation, 0.0);

    // allocate the memmory
    cells = new MapCell[size];
    if (nullptr == cells) {
        throw std::bad_alloc();
    }

    float div = 1.0/(float)width;

    for (int i = 0; i < size; i++) {
        // set the status to undefined
        cells[i].status = 0;

        // calculates the world coordinates to every cell
        cells[i].xi = (origin_x + (i%width - width2)*resolution);
        cells[i].yi = (origin_y + (i*div - height2)*resolution);

    }

}

// basic destructor
GridMap::~GridMap() {
    if (nullptr != cells) {
        delete cells;
    }
}

// update the grid map
void GridMap::updateGridMap(const geometry_msgs::Pose& pose, const sensor_msgs::LaserScanConstPtr& ls) {

    tf::Quaternion qt(pose.orientation.x, pose.orientation.y, pose.orientation.z, pose.orientation.w);

    tf::Matrix3x3 m(qt);
    double theta, p_roll, p_pitch;
    m.getRPY(p_roll, p_pitch, theta);

    int leftLimit, rigthLimit, downLimit, upLimit;

    int x_map = std::floor((pose.position.x - origin_x)/resolution + 0.5) + width2;
    int y_map = std::floor((pose.position.y - origin_y)/resolution + 0.5) + height2;

    leftLimit = x_map - displacement;
    if (0 > leftLimit) {
        leftLimit = 0;
    }

    rigthLimit = x_map + displacement;
    if (width < rigthLimit) {
        rigthLimit = width;
    }

    upLimit = y_map + displacement;
    if (height < upLimit) {
        upLimit = height;
    }

    downLimit = y_map - displacement;
    if (0 > downLimit) {
        downLimit = 0;
    }

    // crictical area
    grid_mutex.lock();

    for (int j = downLimit; j < upLimit; j++) {
        for (int i = leftLimit; i < rigthLimit; i++) {

            MapCell *cell = &cells[MAP_INDEX(i, j)];

            if (4 > abs(i - x_map) && 4 > abs(j - y_map) && 1 > cell->status) {

                cell->status = -100;

            } else {

                cell->dist = std::sqrt(std::pow(cell->xi - pose.position.x, 2) + std::pow(cell->yi - pose.position.y, 2));

                cell->angle = mrpt::math::angDistance(theta, mrpt::math::wrapToPi(atan2(cell->yi - pose.position.y, cell->xi - pose.position.x)));

                // verify the perceptual field
                if (-M_PI2 <= cell->angle && M_PI2 >= cell->angle && cell->dist <= range_max) {

                    inverse_sensor_model(cell, ls);

                }

            }

        }

    }

    // unlock the grid
    grid_mutex.unlock();

}

// the inverse sensor model
void GridMap::inverse_sensor_model(MapCell *cell, const sensor_msgs::LaserScanConstPtr ls) {

    double range = ls->ranges[0];
    double angle = fabs(mrpt::math::angDistance(cell->angle, ls->angle_min));

    // iterate over the laser beams to find the nearest one
    for (int i = 1; i < ls->ranges.size(); i++) {

        double tmp = fabs(mrpt::math::angDistance(cell->angle, ls->angle_min + (i * ls->angle_increment)));

        if (tmp < angle) {
            range = ls->ranges[i];
            angle = tmp;
        } else {
            // it can be stoped
            break;
        }
    }

    // verify the update cases
   if (cell->dist <= range + alpha2 && angle <= beta2 && range <= range_max) {

        if (fabs(cell->dist - range) <= alpha2) {

            if (100 > cell->status) {

                if (-20 < cell->status) {

                    cell->status += 20;

                } else {

                    cell->status += 5;

                }

            }

        } else if (cell->dist < range) {

            if (-100 < cell->status) {

                if (0 > cell->status) {

                    cell->status -= 10;

                } else {

                    cell->status -= 5;

                }

            }

        }

    }

}

// draw the map
void GridMap::exportGridMap(nav_msgs::OccupancyGrid &occupancy) {

    // lock the map
//     grid_mutex.lock();

    // set the sequence
    occupancy.header.seq = seq;

    // time stamp
    occupancy.header.stamp = ros::Time::now();

    // frame_id
    occupancy.header.frame_id = (frame_id);

    // the meta data
    occupancy.info.map_load_time = ros::Time::now();

    // resolution
    occupancy.info.resolution = resolution;

    // width
    occupancy.info.width = width;

    // height
    occupancy.info.height = height;

    // origin - position
    occupancy.info.origin.position.x = origin_x - width2*resolution;
    occupancy.info.origin.position.y = origin_y - height2*resolution;
    occupancy.info.origin.position.z = 0.0;

    // origin - orientation
    occupancy.info.origin.orientation.x = 0.0;
    occupancy.info.origin.orientation.y = 0.0;
    occupancy.info.origin.orientation.z = 0.0;
    occupancy.info.origin.orientation.w = 1.0;

    // copy the cells
    for (int i = 0; i < size; i++) {

        if (0 < cells[i].status) {

            occupancy.data[i] = 100;

        } else if (-5 > cells[i].status) {

            occupancy.data[i] = 0;

        } else {

            occupancy.data[i] = -1;

        }
    }

    // unlock the map
//     grid_mutex.unlock();

    return;
}

<|endoftext|>


<commit_before>#include "../include/avl_tree.h"
#include "gtest/gtest.h"
#include <sstream>

TEST(insertNodeWithKeyTest, LeftLeftHeavyCase1) {
    avl_tree<int> avlt;
    avlt.insertNodeWithKey(2);
    avlt.insertNodeWithKey(1);
    avlt.insertNodeWithKey(0);
    stringstream ss;
    avlt.printTree(ss);
    string expectedOutput =
        string("\t2\n") +
        string("1\n") +
        string("\t0\n");
    EXPECT_EQ(ss.str(), expectedOutput);
    auto node2 = avlt.getNodeWithKey(2);
    auto node1 = avlt.getNodeWithKey(1);
    auto node0 = avlt.getNodeWithKey(0);
    // test parents
    EXPECT_EQ(node2->getParent(), node1);
    EXPECT_EQ(node1->getParent(), nullptr);
    EXPECT_EQ(node0->getParent(), node1);
    // test heights
    EXPECT_EQ(node2->getHeight(), 0);
    EXPECT_EQ(node1->getHeight(), 1);
    EXPECT_EQ(node0->getHeight(), 0);
}

TEST(insertNodeWithKeyTest, LeftLeftHeavyCase2) {
    avl_tree<int> avlt;
    avlt.insertNodeWithKey(4);
    avlt.insertNodeWithKey(2);
    avlt.insertNodeWithKey(5);
    avlt.insertNodeWithKey(1);
    avlt.insertNodeWithKey(3);
    avlt.insertNodeWithKey(0);
    stringstream ss;
    avlt.printTree(ss);
    string expectedOutput =
        string("\t\t5\n") +
        string("\t4\n") +
        string("\t\t3\n") +
        string("2\n") +
        string("\t1\n") +
        string("\t\t0\n");
    EXPECT_EQ(ss.str(), expectedOutput);
    auto node5 = avlt.getNodeWithKey(5);
    auto node4 = avlt.getNodeWithKey(4);
    auto node3 = avlt.getNodeWithKey(3);
    auto node2 = avlt.getNodeWithKey(2);
    auto node1 = avlt.getNodeWithKey(1);
    auto node0 = avlt.getNodeWithKey(0);
    // test parents
    EXPECT_EQ(node5->getParent(), node4);
    EXPECT_EQ(node4->getParent(), node2);
    EXPECT_EQ(node3->getParent(), node4);
    EXPECT_EQ(node2->getParent(), nullptr);
    EXPECT_EQ(node1->getParent(), node2);
    EXPECT_EQ(node0->getParent(), node1);
    // test heights
    EXPECT_EQ(node5->getHeight(), 0);
    EXPECT_EQ(node4->getHeight(), 1);
    EXPECT_EQ(node3->getHeight(), 0);
    EXPECT_EQ(node2->getHeight(), 2);
    EXPECT_EQ(node1->getHeight(), 1);
    EXPECT_EQ(node0->getHeight(), 0);
}

TEST(insertNodeWithKeyTest, LeftRightHeavyCase1) {
    avl_tree<int> avlt;
    avlt.insertNodeWithKey(2);
    avlt.insertNodeWithKey(0);
    avlt.insertNodeWithKey(1);
    stringstream ss;
    avlt.printTree(ss);
    string expectedOutput =
        string("\t2\n") +
        string("1\n") +
        string("\t0\n");
    EXPECT_EQ(ss.str(), expectedOutput);
    auto node2 = avlt.getNodeWithKey(2);
    auto node1 = avlt.getNodeWithKey(1);
    auto node0 = avlt.getNodeWithKey(0);
    // test parents
    EXPECT_EQ(node2->getParent(), node1);
    EXPECT_EQ(node1->getParent(), nullptr);
    EXPECT_EQ(node0->getParent(), node1);
    // test heights
    EXPECT_EQ(node2->getHeight(), 0);
    EXPECT_EQ(node1->getHeight(), 1);
    EXPECT_EQ(node0->getHeight(), 0);
}

TEST(insertNodeWithKeyTest, LeftRightHeavyCase2) {
    avl_tree<int> avlt;
    avlt.insertNodeWithKey(4);
    avlt.insertNodeWithKey(1);
    avlt.insertNodeWithKey(5);
    avlt.insertNodeWithKey(0);
    avlt.insertNodeWithKey(2);
    avlt.insertNodeWithKey(3);
    stringstream ss;
    avlt.printTree(ss);
    string expectedOutput =
        string("\t\t5\n") +
        string("\t4\n") +
        string("\t\t3\n") +
        string("2\n") +
        string("\t1\n") +
        string("\t\t0\n");
    EXPECT_EQ(ss.str(), expectedOutput);
    auto node5 = avlt.getNodeWithKey(5);
    auto node4 = avlt.getNodeWithKey(4);
    auto node3 = avlt.getNodeWithKey(3);
    auto node2 = avlt.getNodeWithKey(2);
    auto node1 = avlt.getNodeWithKey(1);
    auto node0 = avlt.getNodeWithKey(0);
    // test parents
    EXPECT_EQ(node5->getParent(), node4);
    EXPECT_EQ(node4->getParent(), node2);
    EXPECT_EQ(node3->getParent(), node4);
    EXPECT_EQ(node2->getParent(), nullptr);
    EXPECT_EQ(node1->getParent(), node2);
    EXPECT_EQ(node0->getParent(), node1);
    // test heights
    EXPECT_EQ(node5->getHeight(), 0);
    EXPECT_EQ(node4->getHeight(), 1);
    EXPECT_EQ(node3->getHeight(), 0);
    EXPECT_EQ(node2->getHeight(), 2);
    EXPECT_EQ(node1->getHeight(), 1);
    EXPECT_EQ(node0->getHeight(), 0);
}

TEST(insertNodeWithKeyTest, RightRightHeavyCase1) {
    avl_tree<int> avlt;
    avlt.insertNodeWithKey(0);
    avlt.insertNodeWithKey(1);
    avlt.insertNodeWithKey(2);
    stringstream ss;
    avlt.printTree(ss);
    string expectedOutput =
        string("\t2\n") +
        string("1\n") +
        string("\t0\n");
    EXPECT_EQ(ss.str(), expectedOutput);
    auto node2 = avlt.getNodeWithKey(2);
    auto node1 = avlt.getNodeWithKey(1);
    auto node0 = avlt.getNodeWithKey(0);
    // test parents
    EXPECT_EQ(node2->getParent(), node1);
    EXPECT_EQ(node1->getParent(), nullptr);
    EXPECT_EQ(node0->getParent(), node1);
    // test heights
    EXPECT_EQ(node2->getHeight(), 0);
    EXPECT_EQ(node1->getHeight(), 1);
    EXPECT_EQ(node0->getHeight(), 0);
}

TEST(insertNodeWithKeyTest, RightRightHeavyCase2) {
    avl_tree<int> avlt;
    avlt.insertNodeWithKey(1);
    avlt.insertNodeWithKey(0);
    avlt.insertNodeWithKey(3);
    avlt.insertNodeWithKey(2);
    avlt.insertNodeWithKey(4);
    avlt.insertNodeWithKey(5);
    stringstream ss;
    avlt.printTree(ss);
    string expectedOutput =
        string("\t\t5\n") +
        string("\t4\n") +
        string("3\n") +
        string("\t\t2\n") +
        string("\t1\n") +
        string("\t\t0\n");
    EXPECT_EQ(ss.str(), expectedOutput);
    auto node5 = avlt.getNodeWithKey(5);
    auto node4 = avlt.getNodeWithKey(4);
    auto node3 = avlt.getNodeWithKey(3);
    auto node2 = avlt.getNodeWithKey(2);
    auto node1 = avlt.getNodeWithKey(1);
    auto node0 = avlt.getNodeWithKey(0);
    // test parents
    EXPECT_EQ(node5->getParent(), node4);
    EXPECT_EQ(node4->getParent(), node3);
    EXPECT_EQ(node3->getParent(), nullptr);
    EXPECT_EQ(node2->getParent(), node1);
    EXPECT_EQ(node1->getParent(), node3);
    EXPECT_EQ(node0->getParent(), node1);
    // test heights
    EXPECT_EQ(node5->getHeight(), 0);
    EXPECT_EQ(node4->getHeight(), 1);
    EXPECT_EQ(node3->getHeight(), 2);
    EXPECT_EQ(node2->getHeight(), 0);
    EXPECT_EQ(node1->getHeight(), 1);
    EXPECT_EQ(node0->getHeight(), 0);
}

TEST(insertNodeWithKeyTest, RightLeftHeavyCase1) {
    avl_tree<int> avlt;
    avlt.insertNodeWithKey(0);
    avlt.insertNodeWithKey(2);
    avlt.insertNodeWithKey(1);
    stringstream ss;
    avlt.printTree(ss);
    string expectedOutput =
        string("\t2\n") +
        string("1\n") +
        string("\t0\n");
    EXPECT_EQ(ss.str(), expectedOutput);
    auto node2 = avlt.getNodeWithKey(2);
    auto node1 = avlt.getNodeWithKey(1);
    auto node0 = avlt.getNodeWithKey(0);
    // test parents
    EXPECT_EQ(node2->getParent(), node1);
    EXPECT_EQ(node1->getParent(), nullptr);
    EXPECT_EQ(node0->getParent(), node1);
    // test heights
    EXPECT_EQ(node2->getHeight(), 0);
    EXPECT_EQ(node1->getHeight(), 1);
    EXPECT_EQ(node0->getHeight(), 0);
}

TEST(insertNodeWithKeyTest, RightLeftHeavyCase2) {
    avl_tree<int> avlt;
    avlt.insertNodeWithKey(1);
    avlt.insertNodeWithKey(0);
    avlt.insertNodeWithKey(4);
    avlt.insertNodeWithKey(3);
    avlt.insertNodeWithKey(5);
    avlt.insertNodeWithKey(2);
    stringstream ss;
    avlt.printTree(ss);
    string expectedOutput =
        string("\t\t5\n") +
        string("\t4\n") +
        string("3\n") +
        string("\t\t2\n") +
        string("\t1\n") +
        string("\t\t0\n");
    EXPECT_EQ(ss.str(), expectedOutput);
    auto node5 = avlt.getNodeWithKey(5);
    auto node4 = avlt.getNodeWithKey(4);
    auto node3 = avlt.getNodeWithKey(3);
    auto node2 = avlt.getNodeWithKey(2);
    auto node1 = avlt.getNodeWithKey(1);
    auto node0 = avlt.getNodeWithKey(0);
    // test parents
    EXPECT_EQ(node5->getParent(), node4);
    EXPECT_EQ(node4->getParent(), node3);
    EXPECT_EQ(node3->getParent(), nullptr);
    EXPECT_EQ(node2->getParent(), node1);
    EXPECT_EQ(node1->getParent(), node3);
    EXPECT_EQ(node0->getParent(), node1);
    // test heights
    EXPECT_EQ(node5->getHeight(), 0);
    EXPECT_EQ(node4->getHeight(), 1);
    EXPECT_EQ(node3->getHeight(), 2);
    EXPECT_EQ(node2->getHeight(), 0);
    EXPECT_EQ(node1->getHeight(), 1);
    EXPECT_EQ(node0->getHeight(), 0);
}<commit_msg>Add avl_tree_unittest:TEST(deleteNodeWithKeyTest, RightChildWithOnlyRightChild) Add avl_tree_unittest:TEST(deleteNodeWithKeyTest, LeftChildWithOnlyLeftChild) Add avl_tree_unittest:TEST(deleteNodeWithKeyTest, RightChildWithNoChildren) Add avl_tree_unittest:TEST(deleteNodeWithKeyTest, LeftChildWithNoChildren) Add avl_tree_unittest:TEST(deleteNodeWithKeyTest, WithBothChildrenWhereSuccessorIsRightChild)<commit_after>#include "../include/avl_tree.h"
#include "gtest/gtest.h"
#include <sstream>

TEST(insertNodeWithKeyTest, LeftLeftHeavyCase1) {
    avl_tree<int> avlt;
    avlt.insertNodeWithKey(2);
    avlt.insertNodeWithKey(1);
    avlt.insertNodeWithKey(0);
    stringstream ss;
    avlt.printTree(ss);
    string expectedOutput =
        string("\t2\n") +
        string("1\n") +
        string("\t0\n");
    EXPECT_EQ(ss.str(), expectedOutput);
    auto node2 = avlt.getNodeWithKey(2);
    auto node1 = avlt.getNodeWithKey(1);
    auto node0 = avlt.getNodeWithKey(0);
    // test parents
    EXPECT_EQ(node2->getParent(), node1);
    EXPECT_EQ(node1->getParent(), nullptr);
    EXPECT_EQ(node0->getParent(), node1);
    // test heights
    EXPECT_EQ(node2->getHeight(), 0);
    EXPECT_EQ(node1->getHeight(), 1);
    EXPECT_EQ(node0->getHeight(), 0);
}

TEST(insertNodeWithKeyTest, LeftLeftHeavyCase2) {
    avl_tree<int> avlt;
    avlt.insertNodeWithKey(4);
    avlt.insertNodeWithKey(2);
    avlt.insertNodeWithKey(5);
    avlt.insertNodeWithKey(1);
    avlt.insertNodeWithKey(3);
    avlt.insertNodeWithKey(0);
    stringstream ss;
    avlt.printTree(ss);
    string expectedOutput =
        string("\t\t5\n") +
        string("\t4\n") +
        string("\t\t3\n") +
        string("2\n") +
        string("\t1\n") +
        string("\t\t0\n");
    EXPECT_EQ(ss.str(), expectedOutput);
    auto node5 = avlt.getNodeWithKey(5);
    auto node4 = avlt.getNodeWithKey(4);
    auto node3 = avlt.getNodeWithKey(3);
    auto node2 = avlt.getNodeWithKey(2);
    auto node1 = avlt.getNodeWithKey(1);
    auto node0 = avlt.getNodeWithKey(0);
    // test parents
    EXPECT_EQ(node5->getParent(), node4);
    EXPECT_EQ(node4->getParent(), node2);
    EXPECT_EQ(node3->getParent(), node4);
    EXPECT_EQ(node2->getParent(), nullptr);
    EXPECT_EQ(node1->getParent(), node2);
    EXPECT_EQ(node0->getParent(), node1);
    // test heights
    EXPECT_EQ(node5->getHeight(), 0);
    EXPECT_EQ(node4->getHeight(), 1);
    EXPECT_EQ(node3->getHeight(), 0);
    EXPECT_EQ(node2->getHeight(), 2);
    EXPECT_EQ(node1->getHeight(), 1);
    EXPECT_EQ(node0->getHeight(), 0);
}

TEST(insertNodeWithKeyTest, LeftRightHeavyCase1) {
    avl_tree<int> avlt;
    avlt.insertNodeWithKey(2);
    avlt.insertNodeWithKey(0);
    avlt.insertNodeWithKey(1);
    stringstream ss;
    avlt.printTree(ss);
    string expectedOutput =
        string("\t2\n") +
        string("1\n") +
        string("\t0\n");
    EXPECT_EQ(ss.str(), expectedOutput);
    auto node2 = avlt.getNodeWithKey(2);
    auto node1 = avlt.getNodeWithKey(1);
    auto node0 = avlt.getNodeWithKey(0);
    // test parents
    EXPECT_EQ(node2->getParent(), node1);
    EXPECT_EQ(node1->getParent(), nullptr);
    EXPECT_EQ(node0->getParent(), node1);
    // test heights
    EXPECT_EQ(node2->getHeight(), 0);
    EXPECT_EQ(node1->getHeight(), 1);
    EXPECT_EQ(node0->getHeight(), 0);
}

TEST(insertNodeWithKeyTest, LeftRightHeavyCase2) {
    avl_tree<int> avlt;
    avlt.insertNodeWithKey(4);
    avlt.insertNodeWithKey(1);
    avlt.insertNodeWithKey(5);
    avlt.insertNodeWithKey(0);
    avlt.insertNodeWithKey(2);
    avlt.insertNodeWithKey(3);
    stringstream ss;
    avlt.printTree(ss);
    string expectedOutput =
        string("\t\t5\n") +
        string("\t4\n") +
        string("\t\t3\n") +
        string("2\n") +
        string("\t1\n") +
        string("\t\t0\n");
    EXPECT_EQ(ss.str(), expectedOutput);
    auto node5 = avlt.getNodeWithKey(5);
    auto node4 = avlt.getNodeWithKey(4);
    auto node3 = avlt.getNodeWithKey(3);
    auto node2 = avlt.getNodeWithKey(2);
    auto node1 = avlt.getNodeWithKey(1);
    auto node0 = avlt.getNodeWithKey(0);
    // test parents
    EXPECT_EQ(node5->getParent(), node4);
    EXPECT_EQ(node4->getParent(), node2);
    EXPECT_EQ(node3->getParent(), node4);
    EXPECT_EQ(node2->getParent(), nullptr);
    EXPECT_EQ(node1->getParent(), node2);
    EXPECT_EQ(node0->getParent(), node1);
    // test heights
    EXPECT_EQ(node5->getHeight(), 0);
    EXPECT_EQ(node4->getHeight(), 1);
    EXPECT_EQ(node3->getHeight(), 0);
    EXPECT_EQ(node2->getHeight(), 2);
    EXPECT_EQ(node1->getHeight(), 1);
    EXPECT_EQ(node0->getHeight(), 0);
}

TEST(insertNodeWithKeyTest, RightRightHeavyCase1) {
    avl_tree<int> avlt;
    avlt.insertNodeWithKey(0);
    avlt.insertNodeWithKey(1);
    avlt.insertNodeWithKey(2);
    stringstream ss;
    avlt.printTree(ss);
    string expectedOutput =
        string("\t2\n") +
        string("1\n") +
        string("\t0\n");
    EXPECT_EQ(ss.str(), expectedOutput);
    auto node2 = avlt.getNodeWithKey(2);
    auto node1 = avlt.getNodeWithKey(1);
    auto node0 = avlt.getNodeWithKey(0);
    // test parents
    EXPECT_EQ(node2->getParent(), node1);
    EXPECT_EQ(node1->getParent(), nullptr);
    EXPECT_EQ(node0->getParent(), node1);
    // test heights
    EXPECT_EQ(node2->getHeight(), 0);
    EXPECT_EQ(node1->getHeight(), 1);
    EXPECT_EQ(node0->getHeight(), 0);
}

TEST(insertNodeWithKeyTest, RightRightHeavyCase2) {
    avl_tree<int> avlt;
    avlt.insertNodeWithKey(1);
    avlt.insertNodeWithKey(0);
    avlt.insertNodeWithKey(3);
    avlt.insertNodeWithKey(2);
    avlt.insertNodeWithKey(4);
    avlt.insertNodeWithKey(5);
    stringstream ss;
    avlt.printTree(ss);
    string expectedOutput =
        string("\t\t5\n") +
        string("\t4\n") +
        string("3\n") +
        string("\t\t2\n") +
        string("\t1\n") +
        string("\t\t0\n");
    EXPECT_EQ(ss.str(), expectedOutput);
    auto node5 = avlt.getNodeWithKey(5);
    auto node4 = avlt.getNodeWithKey(4);
    auto node3 = avlt.getNodeWithKey(3);
    auto node2 = avlt.getNodeWithKey(2);
    auto node1 = avlt.getNodeWithKey(1);
    auto node0 = avlt.getNodeWithKey(0);
    // test parents
    EXPECT_EQ(node5->getParent(), node4);
    EXPECT_EQ(node4->getParent(), node3);
    EXPECT_EQ(node3->getParent(), nullptr);
    EXPECT_EQ(node2->getParent(), node1);
    EXPECT_EQ(node1->getParent(), node3);
    EXPECT_EQ(node0->getParent(), node1);
    // test heights
    EXPECT_EQ(node5->getHeight(), 0);
    EXPECT_EQ(node4->getHeight(), 1);
    EXPECT_EQ(node3->getHeight(), 2);
    EXPECT_EQ(node2->getHeight(), 0);
    EXPECT_EQ(node1->getHeight(), 1);
    EXPECT_EQ(node0->getHeight(), 0);
}

TEST(insertNodeWithKeyTest, RightLeftHeavyCase1) {
    avl_tree<int> avlt;
    avlt.insertNodeWithKey(0);
    avlt.insertNodeWithKey(2);
    avlt.insertNodeWithKey(1);
    stringstream ss;
    avlt.printTree(ss);
    string expectedOutput =
        string("\t2\n") +
        string("1\n") +
        string("\t0\n");
    EXPECT_EQ(ss.str(), expectedOutput);
    auto node2 = avlt.getNodeWithKey(2);
    auto node1 = avlt.getNodeWithKey(1);
    auto node0 = avlt.getNodeWithKey(0);
    // test parents
    EXPECT_EQ(node2->getParent(), node1);
    EXPECT_EQ(node1->getParent(), nullptr);
    EXPECT_EQ(node0->getParent(), node1);
    // test heights
    EXPECT_EQ(node2->getHeight(), 0);
    EXPECT_EQ(node1->getHeight(), 1);
    EXPECT_EQ(node0->getHeight(), 0);
}

TEST(insertNodeWithKeyTest, RightLeftHeavyCase2) {
    avl_tree<int> avlt;
    avlt.insertNodeWithKey(1);
    avlt.insertNodeWithKey(0);
    avlt.insertNodeWithKey(4);
    avlt.insertNodeWithKey(3);
    avlt.insertNodeWithKey(5);
    avlt.insertNodeWithKey(2);
    stringstream ss;
    avlt.printTree(ss);
    string expectedOutput =
        string("\t\t5\n") +
        string("\t4\n") +
        string("3\n") +
        string("\t\t2\n") +
        string("\t1\n") +
        string("\t\t0\n");
    EXPECT_EQ(ss.str(), expectedOutput);
    auto node5 = avlt.getNodeWithKey(5);
    auto node4 = avlt.getNodeWithKey(4);
    auto node3 = avlt.getNodeWithKey(3);
    auto node2 = avlt.getNodeWithKey(2);
    auto node1 = avlt.getNodeWithKey(1);
    auto node0 = avlt.getNodeWithKey(0);
    // test parents
    EXPECT_EQ(node5->getParent(), node4);
    EXPECT_EQ(node4->getParent(), node3);
    EXPECT_EQ(node3->getParent(), nullptr);
    EXPECT_EQ(node2->getParent(), node1);
    EXPECT_EQ(node1->getParent(), node3);
    EXPECT_EQ(node0->getParent(), node1);
    // test heights
    EXPECT_EQ(node5->getHeight(), 0);
    EXPECT_EQ(node4->getHeight(), 1);
    EXPECT_EQ(node3->getHeight(), 2);
    EXPECT_EQ(node2->getHeight(), 0);
    EXPECT_EQ(node1->getHeight(), 1);
    EXPECT_EQ(node0->getHeight(), 0);
}

TEST(deleteNodeWithKeyTest, RightChildWithOnlyRightChild) {
    avl_tree<int> avlt;
    avlt.insertNodeWithKey(4);
    avlt.insertNodeWithKey(2);
    avlt.insertNodeWithKey(5);
    avlt.insertNodeWithKey(1);
    avlt.insertNodeWithKey(3);
    avlt.insertNodeWithKey(6);
    avlt.insertNodeWithKey(0);
    avlt.deleteNodeWithKey(5);
    stringstream ss;
    avlt.printTree(ss);
    string expectedOutput =
        string("\t\t6\n") +
        string("\t4\n") +
        string("\t\t3\n") +
        string("2\n") +
        string("\t1\n") +
        string("\t\t0\n");
    EXPECT_EQ(ss.str(), expectedOutput);
    auto node6 = avlt.getNodeWithKey(6);
    auto node4 = avlt.getNodeWithKey(4);
    auto node3 = avlt.getNodeWithKey(3);
    auto node2 = avlt.getNodeWithKey(2);
    auto node1 = avlt.getNodeWithKey(1);
    auto node0 = avlt.getNodeWithKey(0);
    // test parents
    EXPECT_EQ(node6->getParent(), node4);
    EXPECT_EQ(node4->getParent(), node2);
    EXPECT_EQ(node3->getParent(), node4);
    EXPECT_EQ(node2->getParent(), nullptr);
    EXPECT_EQ(node1->getParent(), node2);
    EXPECT_EQ(node0->getParent(), node1);
    // test heights
    EXPECT_EQ(node6->getHeight(), 0);
    EXPECT_EQ(node4->getHeight(), 1);
    EXPECT_EQ(node3->getHeight(), 0);
    EXPECT_EQ(node2->getHeight(), 2);
    EXPECT_EQ(node1->getHeight(), 1);
    EXPECT_EQ(node0->getHeight(), 0);
}

TEST(deleteNodeWithKeyTest, LeftChildWithOnlyLeftChild) {
    avl_tree<int> avlt;
    avlt.insertNodeWithKey(2);
    avlt.insertNodeWithKey(1);
    avlt.insertNodeWithKey(4);
    avlt.insertNodeWithKey(0);
    avlt.insertNodeWithKey(3);
    avlt.insertNodeWithKey(5);
    avlt.insertNodeWithKey(6);
    avlt.deleteNodeWithKey(1);
    stringstream ss;
    avlt.printTree(ss);
    string expectedOutput =
        string("\t\t6\n") +
        string("\t5\n") +
        string("4\n") +
        string("\t\t3\n") +
        string("\t2\n") +
        string("\t\t0\n");
    EXPECT_EQ(ss.str(), expectedOutput);
    auto node6 = avlt.getNodeWithKey(6);
    auto node5 = avlt.getNodeWithKey(5);
    auto node4 = avlt.getNodeWithKey(4);
    auto node3 = avlt.getNodeWithKey(3);
    auto node2 = avlt.getNodeWithKey(2);
    auto node0 = avlt.getNodeWithKey(0);
    // test parents
    EXPECT_EQ(node6->getParent(), node5);
    EXPECT_EQ(node5->getParent(), node4);
    EXPECT_EQ(node4->getParent(), nullptr);
    EXPECT_EQ(node3->getParent(), node2);
    EXPECT_EQ(node2->getParent(), node4);
    EXPECT_EQ(node0->getParent(), node2);
    // test heights
    EXPECT_EQ(node6->getHeight(), 0);
    EXPECT_EQ(node5->getHeight(), 1);
    EXPECT_EQ(node4->getHeight(), 2);
    EXPECT_EQ(node3->getHeight(), 0);
    EXPECT_EQ(node2->getHeight(), 1);
    EXPECT_EQ(node0->getHeight(), 0);
}

TEST(deleteNodeWithKeyTest, RightChildWithNoChildren) {
    avl_tree<int> avlt;
    avlt.insertNodeWithKey(3);
    avlt.insertNodeWithKey(1);
    avlt.insertNodeWithKey(4);
    avlt.insertNodeWithKey(0);
    avlt.insertNodeWithKey(2);
    avlt.deleteNodeWithKey(4);
    stringstream ss;
    avlt.printTree(ss);
    string expectedOutput =
        string("\t3\n") +
        string("\t\t2\n") +
        string("1\n") +
        string("\t0\n");
    EXPECT_EQ(ss.str(), expectedOutput);
    auto node3 = avlt.getNodeWithKey(3);
    auto node2 = avlt.getNodeWithKey(2);
    auto node1 = avlt.getNodeWithKey(1);
    auto node0 = avlt.getNodeWithKey(0);
    // test parents
    EXPECT_EQ(node3->getParent(), node1);
    EXPECT_EQ(node2->getParent(), node3);
    EXPECT_EQ(node1->getParent(), nullptr);
    EXPECT_EQ(node0->getParent(), node1);
    // test heights
    EXPECT_EQ(node3->getHeight(), 1);
    EXPECT_EQ(node2->getHeight(), 0);
    EXPECT_EQ(node1->getHeight(), 2);
    EXPECT_EQ(node0->getHeight(), 0);
}

TEST(deleteNodeWithKeyTest, LeftChildWithNoChildren) {
    avl_tree<int> avlt;
    avlt.insertNodeWithKey(1);
    avlt.insertNodeWithKey(0);
    avlt.insertNodeWithKey(3);
    avlt.insertNodeWithKey(2);
    avlt.insertNodeWithKey(4);
    avlt.deleteNodeWithKey(0);
    stringstream ss;
    avlt.printTree(ss);
    string expectedOutput =
        string("\t4\n") +
        string("3\n") +
        string("\t\t2\n") +
        string("\t1\n");
    EXPECT_EQ(ss.str(), expectedOutput);
    auto node4 = avlt.getNodeWithKey(4);
    auto node3 = avlt.getNodeWithKey(3);
    auto node2 = avlt.getNodeWithKey(2);
    auto node1 = avlt.getNodeWithKey(1);
    // test parents
    EXPECT_EQ(node4->getParent(), node3);
    EXPECT_EQ(node3->getParent(), nullptr);
    EXPECT_EQ(node2->getParent(), node1);
    EXPECT_EQ(node1->getParent(), node3);
    // test heights
    EXPECT_EQ(node4->getHeight(), 0);
    EXPECT_EQ(node3->getHeight(), 2);
    EXPECT_EQ(node2->getHeight(), 0);
    EXPECT_EQ(node1->getHeight(), 1);
}

TEST(deleteNodeWithKeyTest, WithBothChildrenWhereSuccessorIsRightChild) {
    avl_tree<int> avlt;
    avlt.insertNodeWithKey(5);
    avlt.insertNodeWithKey(2);
    avlt.insertNodeWithKey(6);
    avlt.insertNodeWithKey(1);
    avlt.insertNodeWithKey(3);
    avlt.insertNodeWithKey(7);
    avlt.insertNodeWithKey(0);
    avlt.insertNodeWithKey(4);
    avlt.deleteNodeWithKey(5);
    stringstream ss;
    avlt.printTree(ss);
    string expectedOutput =
        string("\t\t7\n") +
        string("\t6\n") +
        string("\t\t\t4\n") +
        string("\t\t3\n") +
        string("2\n") +
        string("\t1\n") +
        string("\t\t0\n");
    EXPECT_EQ(ss.str(), expectedOutput);
    auto node7 = avlt.getNodeWithKey(7);
    auto node6 = avlt.getNodeWithKey(6);
    auto node4 = avlt.getNodeWithKey(4);
    auto node3 = avlt.getNodeWithKey(3);
    auto node2 = avlt.getNodeWithKey(2);
    auto node1 = avlt.getNodeWithKey(1);
    auto node0 = avlt.getNodeWithKey(0);
    // test parents
    EXPECT_EQ(node7->getParent(), node6);
    EXPECT_EQ(node6->getParent(), node2);
    EXPECT_EQ(node4->getParent(), node3);
    EXPECT_EQ(node3->getParent(), node6);
    EXPECT_EQ(node2->getParent(), nullptr);
    EXPECT_EQ(node1->getParent(), node2);
    EXPECT_EQ(node0->getParent(), node1);
    // test heights
    EXPECT_EQ(node7->getHeight(), 0);
    EXPECT_EQ(node6->getHeight(), 2);
    EXPECT_EQ(node4->getHeight(), 0);
    EXPECT_EQ(node3->getHeight(), 1);
    EXPECT_EQ(node2->getHeight(), 3);
    EXPECT_EQ(node1->getHeight(), 1);
    EXPECT_EQ(node0->getHeight(), 0);
}<|endoftext|>


<commit_before>/********** tell emacs we use -*- c++ -*- style comments *******************
 * $Revision: 1.2 $  $Author: trey $  $Date: 2005-01-26 04:08:42 $
 *
 * @file    Interleave.cc
 * @brief   No brief
 ***************************************************************************/

/***************************************************************************
 * INCLUDES
 ***************************************************************************/

#include <assert.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>

#include <iostream>
#include <fstream>

#include "commonTime.h"
#include "Interleave.h"
#include "commonDefs.h"
#include "MatrixUtils.h"

using namespace std;
using namespace MatrixUtils;

void Interleave::interleave(PomdpP pomdp, Solver& solver, int numSteps,
			    double minPrecision,
			    double initialPlanTimeSeconds,
			    double perStepPlanTimeSeconds)
{
  if (initialPlanTimeSeconds == -1) {
    // batchTest passes in initialPlanTimeSeconds as -1 to instruct us to reuse
    // existing solution in the solver
    sim->restart();
    initialPlanTimeSeconds = 0;
  } else {
    sim = new PomdpSim(pomdp);
    solver.planInit(pomdp);
  }
  timeval startRun = getTime();
  FOR (i, numSteps) {
    double elapsed = timevalToSeconds(getTime() - startRun);
    double maxTime = (i == 0) ? initialPlanTimeSeconds : perStepPlanTimeSeconds;
    if (maxTime == 0.0) {
      cout << "(" << (i+1) << ") ";
      cout.flush();
    } else {
      cout << endl
	   << "interleave: " << (i+1) << " / " << numSteps
	   << "----------------" << endl;
      cout << "interleave: elapsed time total=" << elapsed
	   << ", per step=" << (elapsed / (i+1)) << endl;
      cout << "interleave: b=";
      cout << sparseRep(sim->currentBelief) << endl;
    }
    int action = solver.planFixedTime(sim->currentBelief, maxTime, minPrecision);
    sim->performAction(action);
  }
  cout << "interleave: run complete, total reward was " << getReward() << endl;
}

void Interleave::batchTestIncremental(int numIterations,
				      PomdpP pomdp, Solver& solver, int numSteps,
				      double minPrecision,
				      double minOrder, double maxOrder, double ticksPerOrder,
				      const string& outFileName,
				      const string& boundsFileName,
				      const string& simFileName)
{
  // make the initial solution
  sim = new PomdpSim(pomdp);
  solver.planInit(pomdp);

  ofstream out( outFileName.c_str() );
  if (! out) {
    cerr << "ERROR: couldn't open " << outFileName << " for writing: "
	 << strerror(errno) << endl;
    exit(EXIT_FAILURE);
  }

  ofstream boundsFile( boundsFileName.c_str() );
  if (! boundsFile) {
    cerr << "ERROR: couldn't open " << boundsFileName << " for writing: "
	 << strerror(errno) << endl;
    exit(EXIT_FAILURE);
  }
  solver.setBoundsFile(&boundsFile);

  ofstream simOutFile( simFileName.c_str() );
  if (! simOutFile) {
    cerr << "ERROR: couldn't open " << simFileName << " for writing: "
	 << strerror(errno) << endl;
    exit(EXIT_FAILURE);
  }
  sim->simOutFile = &simOutFile;

  double timeSoFar = 1e-20;
  double logLastSimTime = -99;
  bool achieved_precision = false;
  while (!achieved_precision && timeSoFar < pow(10,maxOrder)) {
    timeval plan_start = getTime();
    achieved_precision =
      solver.planFixedTime(pomdp->initialBelief, /* maxTime = */ -1, minPrecision);
    double deltaTime = timevalToSeconds(getTime() - plan_start);
    timeSoFar += deltaTime;

    if ((timeSoFar > pow(10,minOrder)
	 && log(timeSoFar) - logLastSimTime > ::log(10) / ticksPerOrder)
	// ensure we do a simulation after the last iteration
	|| timeSoFar >= pow(10,maxOrder)) {
      logLastSimTime = ::log(timeSoFar);

      // repeatedly simulate, reusing the initial solution
      simOutFile << "----- time " << timeSoFar << endl;
      rewardRecord.clear();
      cout << endl;
      int num_successes = 0;
      FOR (i, numIterations) {
	cout << "#-#-#-#-#-#-# batchTest " << (i+1) << " / " << numIterations;
	cout.flush();
	sim->restart();
	FOR (j, numSteps) {
	  int action = solver.chooseAction(sim->currentBelief);
	  sim->performAction(action);
#if 0
	  cout << "(" << (j+1) << ") ";
	  cout.flush();
#endif
	  if (sim->terminated) {
	    num_successes++;
	    break;
	  }
	}
	cout << " (reward " << sim->rewardSoFar << ")" << endl;
	rewardRecord.push_back(sim->rewardSoFar);
      }

      // collect statistics and write a line to the output file
      double avg, stdev;
      calc_avg_stdev_collection(rewardRecord.begin(), rewardRecord.end(), avg, stdev);

      double success_rate = ((double) num_successes) / numIterations;

      ValueInterval val = solver.getValueAt(pomdp->initialBelief);
      // for some reason, if i use sqrt() instead of ::sqrt(), it's ambiguous
      out << timeSoFar << " " << avg << " " << (stdev/::sqrt(numIterations)*1.96) << " "
	  << val.l << " " << val.u << " " << success_rate << endl;
      out.flush();
    }
  }
  out.close();
  boundsFile.close();
  simOutFile.close();
}

void Interleave::printRewards(void) {
  cout << "rewards: ";
  FOR_EACH( reward, rewardRecord ) {
    cout << (*reward) << " ";
  }
  cout << endl;
  double avg, stdev;
  calc_avg_stdev_collection(rewardRecord.begin(), rewardRecord.end(), avg, stdev);
  cout << "reward avg stdev: " << avg << " " << stdev << endl;
}

#if 0

void testInterleave(void) {
  string prob_name = "network-e";

  PomdpP p = new PomdpM;
  string probfile = "examples/" + prob_name + ".pomdp";
  cout << "reading problem from " << probfile << endl;
  p->readFromFile(probfile);

  FocusedPomdp solver;

  Interleave x;
  x.interleave(p, solver,
	       /* numSteps = */ 20,
	       /* minPrecision = */ 1e-10,
	       /* initial time = */ 5.0,
	       /* per step time = */ 5.0);
}

void testBatch(void) {
  //string prob_name = "hallway2";
  string prob_name = "network-u";

  PomdpP p = new PomdpM;
  string probfile = "examples/" + prob_name + ".pomdp";
  cout << "reading problem from " << probfile << endl;
  p->readFromFile(probfile);

  FocusedPomdp solver;

  Interleave x;
  x.batchTestReuse(/* numIterations = */ 100,
		   p, solver,
		   /* numSteps = */ 20,
		   /* minPrecision = */ 1e-10,
		   /* initialPlanTime = */ 60);
  x.printRewards();
}

void Interleave::batchTestReuse(int numIterations,
				PomdpP pomdp, Solver& solver, int numSteps,
				double minPrecision,
				double initialPlanTimeSeconds)
{
  // make the initial solution
  sim = new PomdpSim(pomdp);
  solver.planInit(pomdp);
  solver.planFixedTime(pomdp->initialBelief, initialPlanTimeSeconds, minPrecision);

  // repeatedly simulate, reusing the initial solution
  FOR (i, numIterations) {
    cout << "#-#-#-#-#-#-# batchTest " << (i+1) << " / " << numIterations << endl;
    sim->restart();
    FOR (j, numSteps) {
      int action = solver.planFixedTime(sim->currentBelief, /* maxTime = */ 0,
					minPrecision);
      sim->performAction(action);
      //cout << "(" << (j+1) << ") ";
      cout.flush();
    }
    cout << "(reward " << sim->rewardSoFar << ")" << endl;
    rewardRecord.push_back(sim->rewardSoFar);
  }
}

void Interleave::batchTest(int numIterations,
			   PomdpP pomdp, Solver& solver, int numSteps,
			   double minPrecision,
			   double initialPlanTimeSeconds,
			   double perStepPlanTimeSeconds)
{
  FOR (i, numIterations) {
    cout << "#-#-#-#-#-#-# batchTest" << (i+1) << " / " << numIterations << endl;
    interleave(pomdp, solver, numSteps, minPrecision, initialPlanTimeSeconds,
	       perStepPlanTimeSeconds);
    rewardRecord.push_back(sim->rewardSoFar);
  }
}

#endif

/***************************************************************************
 * REVISION HISTORY:
 * $Log: not supported by cvs2svn $
 * Revision 1.1  2004/11/13 23:29:44  trey
 * moved many files from hsvi to common
 *
 * Revision 1.2  2004/11/09 21:31:59  trey
 * got pomdp source tree into a building state again
 *
 * Revision 1.1.1.1  2004/11/09 16:18:56  trey
 * imported hsvi into new repository
 *
 * Revision 1.12  2003/09/22 16:57:57  trey
 * added tracking of success rate, and ensured we test simulation performance at the end of the run
 *
 * Revision 1.11  2003/09/20 02:26:09  trey
 * found a major problem in F_a_o_transpose, now fixed; added command-line options for experiments
 *
 * Revision 1.10  2003/09/18 21:00:29  trey
 * upper bound self-update seems to be working
 *
 * Revision 1.9  2003/09/17 20:54:24  trey
 * seeing good performance on tagAvoid (but some mods since run started...)
 *
 * Revision 1.8  2003/09/17 18:30:16  trey
 * seems to show best performance so far
 *
 * Revision 1.7  2003/09/16 00:57:02  trey
 * lots of performance tuning, mostly fixed rising upper bound problem
 *
 * Revision 1.6  2003/09/11 01:46:42  trey
 * completed conversion to compressed matrices
 *
 * Revision 1.5  2003/09/06 21:51:53  trey
 * many changes
 *
 * Revision 1.4  2003/07/24 15:33:43  trey
 * working test configuration for self-update
 *
 * Revision 1.3  2003/07/22 19:59:37  trey
 * several minor fixes; still observing discrepancy between sim and solver lower bound
 *
 * Revision 1.2  2003/07/17 22:19:53  trey
 * fixed problems with timing early in the solution run, added upperBoundQ
 *
 * Revision 1.1  2003/07/16 16:09:36  trey
 * initial check-in
 *
 *
 ***************************************************************************/
<commit_msg>added debug statement during simulation<commit_after>/********** tell emacs we use -*- c++ -*- style comments *******************
 * $Revision: 1.3 $  $Author: trey $  $Date: 2005-03-28 18:10:50 $
 *
 * @file    Interleave.cc
 * @brief   No brief
 ***************************************************************************/

/***************************************************************************
 * INCLUDES
 ***************************************************************************/

#include <assert.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>

#include <iostream>
#include <fstream>

#include "commonTime.h"
#include "Interleave.h"
#include "commonDefs.h"
#include "MatrixUtils.h"

using namespace std;
using namespace MatrixUtils;

void Interleave::interleave(PomdpP pomdp, Solver& solver, int numSteps,
			    double minPrecision,
			    double initialPlanTimeSeconds,
			    double perStepPlanTimeSeconds)
{
  if (initialPlanTimeSeconds == -1) {
    // batchTest passes in initialPlanTimeSeconds as -1 to instruct us to reuse
    // existing solution in the solver
    sim->restart();
    initialPlanTimeSeconds = 0;
  } else {
    sim = new PomdpSim(pomdp);
    solver.planInit(pomdp);
  }
  timeval startRun = getTime();
  FOR (i, numSteps) {
    double elapsed = timevalToSeconds(getTime() - startRun);
    double maxTime = (i == 0) ? initialPlanTimeSeconds : perStepPlanTimeSeconds;
    if (maxTime == 0.0) {
      cout << "(" << (i+1) << ") ";
      cout.flush();
    } else {
      cout << endl
	   << "interleave: " << (i+1) << " / " << numSteps
	   << "----------------" << endl;
      cout << "interleave: elapsed time total=" << elapsed
	   << ", per step=" << (elapsed / (i+1)) << endl;
      cout << "interleave: b=";
      cout << sparseRep(sim->currentBelief) << endl;
    }
    int action = solver.planFixedTime(sim->currentBelief, maxTime, minPrecision);
    sim->performAction(action);
  }
  cout << "interleave: run complete, total reward was " << getReward() << endl;
}

void Interleave::batchTestIncremental(int numIterations,
				      PomdpP pomdp, Solver& solver, int numSteps,
				      double minPrecision,
				      double minOrder, double maxOrder, double ticksPerOrder,
				      const string& outFileName,
				      const string& boundsFileName,
				      const string& simFileName)
{
  // make the initial solution
  sim = new PomdpSim(pomdp);
  solver.planInit(pomdp);

  ofstream out( outFileName.c_str() );
  if (! out) {
    cerr << "ERROR: couldn't open " << outFileName << " for writing: "
	 << strerror(errno) << endl;
    exit(EXIT_FAILURE);
  }

  ofstream boundsFile( boundsFileName.c_str() );
  if (! boundsFile) {
    cerr << "ERROR: couldn't open " << boundsFileName << " for writing: "
	 << strerror(errno) << endl;
    exit(EXIT_FAILURE);
  }
  solver.setBoundsFile(&boundsFile);

  ofstream simOutFile( simFileName.c_str() );
  if (! simOutFile) {
    cerr << "ERROR: couldn't open " << simFileName << " for writing: "
	 << strerror(errno) << endl;
    exit(EXIT_FAILURE);
  }
  sim->simOutFile = &simOutFile;

  double timeSoFar = 1e-20;
  double logLastSimTime = -99;
  bool achieved_precision = false;
  bool achieved_terminal_state;
  while (!achieved_precision && timeSoFar < pow(10,maxOrder)) {
    timeval plan_start = getTime();
    achieved_precision =
      solver.planFixedTime(pomdp->initialBelief, /* maxTime = */ -1, minPrecision);
    double deltaTime = timevalToSeconds(getTime() - plan_start);
    timeSoFar += deltaTime;

    if ((timeSoFar > pow(10,minOrder)
	 && log(timeSoFar) - logLastSimTime > ::log(10) / ticksPerOrder)
	// ensure we do a simulation after the last iteration
	|| timeSoFar >= pow(10,maxOrder)) {
      logLastSimTime = ::log(timeSoFar);

      // repeatedly simulate, reusing the initial solution
      simOutFile << "----- time " << timeSoFar << endl;
      rewardRecord.clear();
      cout << endl;
      int num_successes = 0;
      FOR (i, numIterations) {
	cout << "#-#-#-#-#-#-# batchTest " << (i+1) << " / " << numIterations;
	cout.flush();
	sim->restart();
	achieved_terminal_state = false;
	FOR (j, numSteps) {
	  int action = solver.chooseAction(sim->currentBelief);
	  sim->performAction(action);
#if 0
	  cout << "(" << (j+1) << ") ";
	  cout.flush();
#endif
	  if (sim->terminated) {
	    num_successes++;
	    achieved_terminal_state = true;
	    break;
	  }
	}
	cout << " (reward " << sim->rewardSoFar << ")" << endl;
	rewardRecord.push_back(sim->rewardSoFar);
	if (!achieved_terminal_state) {
	  cout << "(time ran out in simulation)" << endl;
	}
      }

      // collect statistics and write a line to the output file
      double avg, stdev;
      calc_avg_stdev_collection(rewardRecord.begin(), rewardRecord.end(), avg, stdev);

      double success_rate = ((double) num_successes) / numIterations;

      ValueInterval val = solver.getValueAt(pomdp->initialBelief);
      // for some reason, if i use sqrt() instead of ::sqrt(), it's ambiguous
      out << timeSoFar << " " << avg << " " << (stdev/::sqrt(numIterations)*1.96) << " "
	  << val.l << " " << val.u << " " << success_rate << endl;
      out.flush();
    }
  }
  out.close();
  boundsFile.close();
  simOutFile.close();
}

void Interleave::printRewards(void) {
  cout << "rewards: ";
  FOR_EACH( reward, rewardRecord ) {
    cout << (*reward) << " ";
  }
  cout << endl;
  double avg, stdev;
  calc_avg_stdev_collection(rewardRecord.begin(), rewardRecord.end(), avg, stdev);
  cout << "reward avg stdev: " << avg << " " << stdev << endl;
}

#if 0

void testInterleave(void) {
  string prob_name = "network-e";

  PomdpP p = new PomdpM;
  string probfile = "examples/" + prob_name + ".pomdp";
  cout << "reading problem from " << probfile << endl;
  p->readFromFile(probfile);

  FocusedPomdp solver;

  Interleave x;
  x.interleave(p, solver,
	       /* numSteps = */ 20,
	       /* minPrecision = */ 1e-10,
	       /* initial time = */ 5.0,
	       /* per step time = */ 5.0);
}

void testBatch(void) {
  //string prob_name = "hallway2";
  string prob_name = "network-u";

  PomdpP p = new PomdpM;
  string probfile = "examples/" + prob_name + ".pomdp";
  cout << "reading problem from " << probfile << endl;
  p->readFromFile(probfile);

  FocusedPomdp solver;

  Interleave x;
  x.batchTestReuse(/* numIterations = */ 100,
		   p, solver,
		   /* numSteps = */ 20,
		   /* minPrecision = */ 1e-10,
		   /* initialPlanTime = */ 60);
  x.printRewards();
}

void Interleave::batchTestReuse(int numIterations,
				PomdpP pomdp, Solver& solver, int numSteps,
				double minPrecision,
				double initialPlanTimeSeconds)
{
  // make the initial solution
  sim = new PomdpSim(pomdp);
  solver.planInit(pomdp);
  solver.planFixedTime(pomdp->initialBelief, initialPlanTimeSeconds, minPrecision);

  // repeatedly simulate, reusing the initial solution
  FOR (i, numIterations) {
    cout << "#-#-#-#-#-#-# batchTest " << (i+1) << " / " << numIterations << endl;
    sim->restart();
    FOR (j, numSteps) {
      int action = solver.planFixedTime(sim->currentBelief, /* maxTime = */ 0,
					minPrecision);
      sim->performAction(action);
      //cout << "(" << (j+1) << ") ";
      cout.flush();
    }
    cout << "(reward " << sim->rewardSoFar << ")" << endl;
    rewardRecord.push_back(sim->rewardSoFar);
  }
}

void Interleave::batchTest(int numIterations,
			   PomdpP pomdp, Solver& solver, int numSteps,
			   double minPrecision,
			   double initialPlanTimeSeconds,
			   double perStepPlanTimeSeconds)
{
  FOR (i, numIterations) {
    cout << "#-#-#-#-#-#-# batchTest" << (i+1) << " / " << numIterations << endl;
    interleave(pomdp, solver, numSteps, minPrecision, initialPlanTimeSeconds,
	       perStepPlanTimeSeconds);
    rewardRecord.push_back(sim->rewardSoFar);
  }
}

#endif

/***************************************************************************
 * REVISION HISTORY:
 * $Log: not supported by cvs2svn $
 * Revision 1.2  2005/01/26 04:08:42  trey
 * switched to use sparseRep in debug print
 *
 * Revision 1.1  2004/11/13 23:29:44  trey
 * moved many files from hsvi to common
 *
 * Revision 1.2  2004/11/09 21:31:59  trey
 * got pomdp source tree into a building state again
 *
 * Revision 1.1.1.1  2004/11/09 16:18:56  trey
 * imported hsvi into new repository
 *
 * Revision 1.12  2003/09/22 16:57:57  trey
 * added tracking of success rate, and ensured we test simulation performance at the end of the run
 *
 * Revision 1.11  2003/09/20 02:26:09  trey
 * found a major problem in F_a_o_transpose, now fixed; added command-line options for experiments
 *
 * Revision 1.10  2003/09/18 21:00:29  trey
 * upper bound self-update seems to be working
 *
 * Revision 1.9  2003/09/17 20:54:24  trey
 * seeing good performance on tagAvoid (but some mods since run started...)
 *
 * Revision 1.8  2003/09/17 18:30:16  trey
 * seems to show best performance so far
 *
 * Revision 1.7  2003/09/16 00:57:02  trey
 * lots of performance tuning, mostly fixed rising upper bound problem
 *
 * Revision 1.6  2003/09/11 01:46:42  trey
 * completed conversion to compressed matrices
 *
 * Revision 1.5  2003/09/06 21:51:53  trey
 * many changes
 *
 * Revision 1.4  2003/07/24 15:33:43  trey
 * working test configuration for self-update
 *
 * Revision 1.3  2003/07/22 19:59:37  trey
 * several minor fixes; still observing discrepancy between sim and solver lower bound
 *
 * Revision 1.2  2003/07/17 22:19:53  trey
 * fixed problems with timing early in the solution run, added upperBoundQ
 *
 * Revision 1.1  2003/07/16 16:09:36  trey
 * initial check-in
 *
 *
 ***************************************************************************/
<|endoftext|>