<commit_before>/*
    Copyright © 2010, 2011, 2012 Vladimír Vondruš <mosra@centrum.cz>

    This file is part of Magnum.

    Magnum is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License version 3
    only, as published by the Free Software Foundation.

    Magnum is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    GNU Lesser General Public License version 3 for more details.
*/

#include "AbstractShapeRenderer.h"

#include "AbstractShaderProgram.h"
#include "Buffer.h"
#include "Mesh.h"
#include "DebugTools/ResourceManager.h"
#include "MeshTools/CompressIndices.h"
#include "Shaders/FlatShader.h"
#include "Trade/MeshData2D.h"
#include "Trade/MeshData3D.h"

namespace Magnum { namespace DebugTools { namespace Implementation {

namespace {

template<std::uint8_t dimensions> ResourceKey shaderKey();
template<> inline ResourceKey shaderKey<2>() { return ResourceKey("FlatShader2D"); }
template<> inline ResourceKey shaderKey<3>() { return ResourceKey("FlatShader3D"); }

template<std::uint8_t dimensions> void create(typename MeshData<dimensions>::Type&, Resource<Mesh>&, Resource<Buffer>&, Resource<Buffer>&);

template<> void create<2>(Trade::MeshData2D& data, Resource<Mesh>& meshResource, Resource<Buffer>& vertexBufferResource, Resource<Buffer>& indexBufferResource) {
    /* Vertex buffer */
    Buffer* buffer = new Buffer(Buffer::Target::Array);
    buffer->setData(*data.positions(0), Buffer::Usage::StaticDraw);
    ResourceManager::instance()->set(vertexBufferResource.key(), buffer, ResourceDataState::Final, ResourcePolicy::Manual);

    /* Mesh configuration */
    Mesh* mesh = new Mesh;
    mesh->setPrimitive(data.primitive())
        ->setVertexCount(data.positions(0)->size())
        ->addVertexBuffer(buffer, 0, Shaders::FlatShader2D::Position());
    ResourceManager::instance()->set(meshResource.key(), mesh, ResourceDataState::Final, ResourcePolicy::Manual);

    /* Index buffer, if present */
    if(data.indices()) {
        Buffer* indexBuffer = new Buffer(Buffer::Target::ElementArray);
        MeshTools::compressIndices(mesh, indexBuffer, Buffer::Usage::StaticDraw, *data.indices());
        ResourceManager::instance()->set(indexBufferResource.key(), indexBuffer, ResourceDataState::Final, ResourcePolicy::Manual);
    }
}

template<> void create<3>(Trade::MeshData3D& data, Resource<Mesh>& meshResource, Resource<Buffer>& vertexBufferResource, Resource<Buffer>& indexBufferResource) {
    /* Vertex buffer */
    Buffer* vertexBuffer = new Buffer(Buffer::Target::Array);
    vertexBuffer->setData(*data.positions(0), Buffer::Usage::StaticDraw);
    ResourceManager::instance()->set(vertexBufferResource.key(), vertexBuffer, ResourceDataState::Final, ResourcePolicy::Manual);

    /* Mesh configuration */
    Mesh* mesh = new Mesh;
    mesh->setPrimitive(data.primitive())
        ->setVertexCount(data.positions(0)->size())
        ->addVertexBuffer(vertexBuffer, 0, Shaders::FlatShader3D::Position());
    ResourceManager::instance()->set(meshResource.key(), mesh, ResourceDataState::Final, ResourcePolicy::Manual);

    /* Index buffer, if needed */
    if(data.indices()) {
        Buffer* indexBuffer = new Buffer(Buffer::Target::ElementArray);
        MeshTools::compressIndices(mesh, indexBuffer, Buffer::Usage::StaticDraw, *data.indices());
        ResourceManager::instance()->set(indexBufferResource.key(), indexBuffer, ResourceDataState::Final, ResourcePolicy::Manual);
    }
}

}

template<std::uint8_t dimensions> AbstractShapeRenderer<dimensions>::AbstractShapeRenderer(ResourceKey meshKey, ResourceKey vertexBufferKey, ResourceKey indexBufferKey) {
    shader = ResourceManager::instance()->get<AbstractShaderProgram, Shaders::FlatShader<dimensions>>(shaderKey<dimensions>());
    mesh = ResourceManager::instance()->get<Mesh>(meshKey);
    vertexBuffer = ResourceManager::instance()->get<Buffer>(vertexBufferKey);
    indexBuffer = ResourceManager::instance()->get<Buffer>(indexBufferKey);

    if(!shader) ResourceManager::instance()->set<AbstractShaderProgram>(shaderKey<dimensions>(),
        new Shaders::FlatShader<dimensions>, ResourceDataState::Final, ResourcePolicy::Resident);
}

template<std::uint8_t dimensions> AbstractShapeRenderer<dimensions>::~AbstractShapeRenderer() {}

template<std::uint8_t dimensions> void AbstractShapeRenderer<dimensions>::createResources(typename MeshData<dimensions>::Type data) {
    create<dimensions>(data, this->mesh, this->vertexBuffer, this->indexBuffer);
}

template class AbstractShapeRenderer<2>;
template class AbstractShapeRenderer<3>;

}}}
<commit_msg>DebugTools: assertions for non-empty resource key when it is needed.<commit_after>/*
    Copyright © 2010, 2011, 2012 Vladimír Vondruš <mosra@centrum.cz>

    This file is part of Magnum.

    Magnum is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License version 3
    only, as published by the Free Software Foundation.

    Magnum is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    GNU Lesser General Public License version 3 for more details.
*/

#include "AbstractShapeRenderer.h"

#include "AbstractShaderProgram.h"
#include "Buffer.h"
#include "Mesh.h"
#include "DebugTools/ResourceManager.h"
#include "MeshTools/CompressIndices.h"
#include "Shaders/FlatShader.h"
#include "Trade/MeshData2D.h"
#include "Trade/MeshData3D.h"

namespace Magnum { namespace DebugTools { namespace Implementation {

namespace {

template<std::uint8_t dimensions> ResourceKey shaderKey();
template<> inline ResourceKey shaderKey<2>() { return ResourceKey("FlatShader2D"); }
template<> inline ResourceKey shaderKey<3>() { return ResourceKey("FlatShader3D"); }

template<std::uint8_t dimensions> void create(typename MeshData<dimensions>::Type&, Resource<Mesh>&, Resource<Buffer>&, Resource<Buffer>&);

template<> void create<2>(Trade::MeshData2D& data, Resource<Mesh>& meshResource, Resource<Buffer>& vertexBufferResource, Resource<Buffer>& indexBufferResource) {
    /* Vertex buffer */
    Buffer* buffer = new Buffer(Buffer::Target::Array);
    buffer->setData(*data.positions(0), Buffer::Usage::StaticDraw);
    ResourceManager::instance()->set(vertexBufferResource.key(), buffer, ResourceDataState::Final, ResourcePolicy::Manual);

    /* Mesh configuration */
    Mesh* mesh = new Mesh;
    mesh->setPrimitive(data.primitive())
        ->setVertexCount(data.positions(0)->size())
        ->addVertexBuffer(buffer, 0, Shaders::FlatShader2D::Position());
    ResourceManager::instance()->set(meshResource.key(), mesh, ResourceDataState::Final, ResourcePolicy::Manual);

    /* Index buffer, if needed, if not, resource key doesn't have to be set */
    if(data.indices()) {
        CORRADE_INTERNAL_ASSERT(indexBufferResource.key() != ResourceKey());
        Buffer* indexBuffer = new Buffer(Buffer::Target::ElementArray);
        MeshTools::compressIndices(mesh, indexBuffer, Buffer::Usage::StaticDraw, *data.indices());
        ResourceManager::instance()->set(indexBufferResource.key(), indexBuffer, ResourceDataState::Final, ResourcePolicy::Manual);
    }
}

template<> void create<3>(Trade::MeshData3D& data, Resource<Mesh>& meshResource, Resource<Buffer>& vertexBufferResource, Resource<Buffer>& indexBufferResource) {
    /* Vertex buffer */
    Buffer* vertexBuffer = new Buffer(Buffer::Target::Array);
    vertexBuffer->setData(*data.positions(0), Buffer::Usage::StaticDraw);
    ResourceManager::instance()->set(vertexBufferResource.key(), vertexBuffer, ResourceDataState::Final, ResourcePolicy::Manual);

    /* Mesh configuration */
    Mesh* mesh = new Mesh;
    mesh->setPrimitive(data.primitive())
        ->setVertexCount(data.positions(0)->size())
        ->addVertexBuffer(vertexBuffer, 0, Shaders::FlatShader3D::Position());
    ResourceManager::instance()->set(meshResource.key(), mesh, ResourceDataState::Final, ResourcePolicy::Manual);

    /* Index buffer, if needed, if not, resource key doesn't have to be set */
    if(data.indices()) {
        CORRADE_INTERNAL_ASSERT(indexBufferResource.key() != ResourceKey());
        Buffer* indexBuffer = new Buffer(Buffer::Target::ElementArray);
        MeshTools::compressIndices(mesh, indexBuffer, Buffer::Usage::StaticDraw, *data.indices());
        ResourceManager::instance()->set(indexBufferResource.key(), indexBuffer, ResourceDataState::Final, ResourcePolicy::Manual);
    }
}

}

template<std::uint8_t dimensions> AbstractShapeRenderer<dimensions>::AbstractShapeRenderer(ResourceKey meshKey, ResourceKey vertexBufferKey, ResourceKey indexBufferKey) {
    shader = ResourceManager::instance()->get<AbstractShaderProgram, Shaders::FlatShader<dimensions>>(shaderKey<dimensions>());
    mesh = ResourceManager::instance()->get<Mesh>(meshKey);
    vertexBuffer = ResourceManager::instance()->get<Buffer>(vertexBufferKey);
    indexBuffer = ResourceManager::instance()->get<Buffer>(indexBufferKey);

    if(!shader) ResourceManager::instance()->set<AbstractShaderProgram>(shaderKey<dimensions>(),
        new Shaders::FlatShader<dimensions>, ResourceDataState::Final, ResourcePolicy::Resident);
}

template<std::uint8_t dimensions> AbstractShapeRenderer<dimensions>::~AbstractShapeRenderer() {}

template<std::uint8_t dimensions> void AbstractShapeRenderer<dimensions>::createResources(typename MeshData<dimensions>::Type data) {
    create<dimensions>(data, this->mesh, this->vertexBuffer, this->indexBuffer);
}

template class AbstractShapeRenderer<2>;
template class AbstractShapeRenderer<3>;

}}}
<|endoftext|>


<commit_before>#include "initializer3d.h"

//####################################################################
//
// To avoid a float overflow and speed up the calculations.
//
// Convert
//
// 10^10 (m) = 10000000000 (m) = 1 (length here)
// 10^30 (kg) = 1 (mass here)
//
// G constant (m^3 kg^-1 s^-2) : -10-10-10+30 = 0 (not change)
//
// You should choose the right scale for your calculations.
// The "Correct" class help this Conversions.
//
//####################################################################

template class Initializer3D<float>;
template class Initializer3D<double>;

template <typename T>
void Initializer3D<T>::initRandomCube()
{
    Correct correct(m_sim.scale);
    m_engine->changeModelScale(correct.m);

    quint64 num = m_engine->numberOfParticle();
    T* masses = m_engine->masses();
    T* coordinates = m_engine->coordinates();
    T* velocities = m_engine->velocities();

    if (m_sim.massRandom)
    {
        for (quint64 i = 0; i < num; ++i)
        {
            masses[i] = T(bhs::rand0to1() * m_sim.massAvg * 2.0 * correct.kg);
        }
    } else {
        for (quint64 i = 0; i < num; ++i)
        {
            masses[i] = m_sim.massAvg;
        }
    }
    for (quint64 i = 0; i < num * 3; ++i)
    {
        coordinates[i] = T(bhs::rand0center1max() * m_sim.scale * correct.m);
    }
    for (quint64 i = 0; i < num * 3; ++i)
    {
        velocities[i] = T(bhs::rand0center1max() * m_sim.speed * correct.m);
    }
    setRotation();
}

template <typename T>
void Initializer3D<T>::initRandomSphere(const double rate)
{
    Correct correct(m_sim.scale);
    m_engine->changeModelScale(correct.m);

    quint64 num = m_engine->numberOfParticle();
    T* masses = m_engine->masses();
    T* coordinates = m_engine->coordinates();
    T* velocities = m_engine->velocities();

    if (m_sim.massRandom)
    {
        for (quint64 i = 0; i < num; ++i)
        {
            masses[i] = T(bhs::rand0to1() * m_sim.massAvg * 2.0 * correct.kg);
        }
    } else {
        for (quint64 i = 0; i < num; ++i)
        {
            masses[i] = m_sim.massAvg * correct.kg;
        }
    }

    quint64 i3;
    Vector3 coord;
    for (quint64 i = 0; i < num; ++i)
    {
        i3 = i * 3;
        do
        {
            coord.set(
                bhs::rand0center1max(),
                bhs::rand0center1max(),
                bhs::rand0center1max());
        }
        while (coord.norm() > (T)1.0 || coord.norm() < (T)rate);

        coordinates[i3    ] = T(coord.x());
        coordinates[i3 + 1] = T(coord.y());
        coordinates[i3 + 2] = T(coord.z());
    }

    for (quint64 i = 0; i < num * 3; ++i)
    {
        velocities[i] = T(bhs::rand0center1max() * m_sim.speed * correct.m);
    }
    setRotation();
}

template <typename T>
void Initializer3D<T>::initCustom()
{
    Correct correct(m_sim.custom.scale);
    m_engine->changeModelScale(correct.m);

    T* masses = m_engine->masses();
    T* coordinates = m_engine->coordinates();
    T* velocities = m_engine->velocities();

    int i = 0;
    for (const bhs::Particle& e : m_sim.custom.particles)
    {
        masses[i] = T(e.mass * correct.kg);
        int i3 = i * 3;
        coordinates[i3    ] = T(e.coordinate.x() * correct.m);
        coordinates[i3 + 1] = T(e.coordinate.y() * correct.m);
        coordinates[i3 + 2] = T(e.coordinate.z() * correct.m);
        velocities[i3    ] = T(e.velocity.x() * correct.m);
        velocities[i3 + 1] = T(e.velocity.y() * correct.m);
        velocities[i3 + 2] = T(e.velocity.z() * correct.m);
        ++i;
    }
}

template <typename T>
void Initializer3D<T>::setRotation()
{
    quint64 num = m_engine->numberOfParticle();
    T* coordinates = m_engine->coordinates();
    T* velocities = m_engine->velocities();
    T time = m_engine->timePerFrame();
    double radian = degreeToRadian(m_sim.rotation);
    radian *= double(time);
    T sn = T(sin(radian));
    T cn = T(cos(radian));

    for (quint64 i = 0; i < num; ++i)
    {
        quint64 i3 = i * 3;
        T x1 = coordinates[i3    ];
        T z1 = coordinates[i3 + 2];
        T x2 = cn * x1 + sn * z1;
        T z2 = -sn * x1 + cn * z1;
        velocities[i3    ] += (x2 - x1) / time;
        velocities[i3 + 2] += (z2 - z1) / time;
    }
}
<commit_msg>fix bug cube - not random masses<commit_after>#include "initializer3d.h"

//####################################################################
//
// To avoid a float overflow and speed up the calculations.
//
// Convert
//
// 10^10 (m) = 10000000000 (m) = 1 (length here)
// 10^30 (kg) = 1 (mass here)
//
// G constant (m^3 kg^-1 s^-2) : -10-10-10+30 = 0 (not change)
//
// You should choose the right scale for your calculations.
// The "Correct" class help this Conversions.
//
//####################################################################

template class Initializer3D<float>;
template class Initializer3D<double>;

template <typename T>
void Initializer3D<T>::initRandomCube()
{
    Correct correct(m_sim.scale);
    m_engine->changeModelScale(correct.m);

    quint64 num = m_engine->numberOfParticle();
    T* masses = m_engine->masses();
    T* coordinates = m_engine->coordinates();
    T* velocities = m_engine->velocities();

    if (m_sim.massRandom)
    {
        for (quint64 i = 0; i < num; ++i)
        {
            masses[i] = T(bhs::rand0to1() * m_sim.massAvg * 2.0 * correct.kg);
        }
    } else {
        for (quint64 i = 0; i < num; ++i)
        {
            masses[i] = m_sim.massAvg * correct.kg;
        }
    }
    for (quint64 i = 0; i < num * 3; ++i)
    {
        coordinates[i] = T(bhs::rand0center1max() * m_sim.scale * correct.m);
    }
    for (quint64 i = 0; i < num * 3; ++i)
    {
        velocities[i] = T(bhs::rand0center1max() * m_sim.speed * correct.m);
    }
    setRotation();
}

template <typename T>
void Initializer3D<T>::initRandomSphere(const double rate)
{
    Correct correct(m_sim.scale);
    m_engine->changeModelScale(correct.m);

    quint64 num = m_engine->numberOfParticle();
    T* masses = m_engine->masses();
    T* coordinates = m_engine->coordinates();
    T* velocities = m_engine->velocities();

    if (m_sim.massRandom)
    {
        for (quint64 i = 0; i < num; ++i)
        {
            masses[i] = T(bhs::rand0to1() * m_sim.massAvg * 2.0 * correct.kg);
        }
    } else {
        for (quint64 i = 0; i < num; ++i)
        {
            masses[i] = m_sim.massAvg * correct.kg;
        }
    }

    quint64 i3;
    Vector3 coord;
    for (quint64 i = 0; i < num; ++i)
    {
        i3 = i * 3;
        do
        {
            coord.set(
                bhs::rand0center1max(),
                bhs::rand0center1max(),
                bhs::rand0center1max());
        }
        while (coord.norm() > (T)1.0 || coord.norm() < (T)rate);

        coordinates[i3    ] = T(coord.x());
        coordinates[i3 + 1] = T(coord.y());
        coordinates[i3 + 2] = T(coord.z());
    }

    for (quint64 i = 0; i < num * 3; ++i)
    {
        velocities[i] = T(bhs::rand0center1max() * m_sim.speed * correct.m);
    }
    setRotation();
}

template <typename T>
void Initializer3D<T>::initCustom()
{
    Correct correct(m_sim.custom.scale);
    m_engine->changeModelScale(correct.m);

    T* masses = m_engine->masses();
    T* coordinates = m_engine->coordinates();
    T* velocities = m_engine->velocities();

    int i = 0;
    for (const bhs::Particle& e : m_sim.custom.particles)
    {
        masses[i] = T(e.mass * correct.kg);
        int i3 = i * 3;
        coordinates[i3    ] = T(e.coordinate.x() * correct.m);
        coordinates[i3 + 1] = T(e.coordinate.y() * correct.m);
        coordinates[i3 + 2] = T(e.coordinate.z() * correct.m);
        velocities[i3    ] = T(e.velocity.x() * correct.m);
        velocities[i3 + 1] = T(e.velocity.y() * correct.m);
        velocities[i3 + 2] = T(e.velocity.z() * correct.m);
        ++i;
    }
}

template <typename T>
void Initializer3D<T>::setRotation()
{
    quint64 num = m_engine->numberOfParticle();
    T* coordinates = m_engine->coordinates();
    T* velocities = m_engine->velocities();
    T time = m_engine->timePerFrame();
    double radian = degreeToRadian(m_sim.rotation);
    radian *= double(time);
    T sn = T(sin(radian));
    T cn = T(cos(radian));

    for (quint64 i = 0; i < num; ++i)
    {
        quint64 i3 = i * 3;
        T x1 = coordinates[i3    ];
        T z1 = coordinates[i3 + 2];
        T x2 = cn * x1 + sn * z1;
        T z2 = -sn * x1 + cn * z1;
        velocities[i3    ] += (x2 - x1) / time;
        velocities[i3 + 2] += (z2 - z1) / time;
    }
}
<|endoftext|>


<commit_before>#include <babylon/cameras/arc_rotate_camera.h>
#include <babylon/cameras/free_camera.h>
#include <babylon/engines/scene.h>
#include <babylon/interfaces/irenderable_scene.h>
#include <babylon/lights/point_light.h>
#include <babylon/meshes/mesh.h>
#include <babylon/samples/babylon_register_sample.h>

namespace BABYLON {
namespace Samples {

/**
 * @brief Cameras scene demonstrating the types of cameras in babylonjs.
 * @see https://www.babylonjs-playground.com/#1A3M5C#0
 * @see https://doc.babylonjs.com/babylon101/cameras
 */
struct CamerasTypesScene : public IRenderableScene {

  CamerasTypesScene(ICanvas* iCanvas) : IRenderableScene(iCanvas)
  {
  }

  ~CamerasTypesScene() override = default;

  const char* getName() override
  {
    return "Cameras Scene";
  }

  void initializeScene(ICanvas* canvas, Scene* scene) override
  {
    // Setup a simple environment
    auto light0 = PointLight::New("Omni", Vector3(0.f, 2.f, 8.f), scene);
    light0->position().x += 0.f;
    auto box1 = Mesh::CreateBox("b1", 1.f, scene);
    box1->position().x += 0.f;
    auto box2          = Mesh::CreateBox("b2", 1.f, scene);
    box2->position().x = -3.f;
    auto box3          = Mesh::CreateBox("b3", 1.f, scene);
    box3->position().x = 3.f;

    // ArcRotateCamera >> Camera rotating around a 3D point (here Vector zero)
    // Parameters : name, alpha, beta, radius, target, scene
    auto arcCamera
      = ArcRotateCamera::New("ArcRotateCamera", 1.f, 0.8f, 10.f, Vector3(0.f, 0.f, 0.f), scene);
    arcCamera->setPosition(Vector3(0.f, 0.f, 50.f));
    arcCamera->target = Vector3(3.f, 0.f, 0.f);

    // FreeCamera >> You can move around the world with mouse and keyboard
    // (LEFT/RIGHT/UP/DOWN) Parameters : name, position, scene
    auto freeCamera      = FreeCamera::New("FreeCamera", Vector3(0.f, 0.f, 5.f), scene);
    freeCamera->rotation = Vector3(0.f, Math::PI, 0.f);

    // Attach a camera to the scene and the canvas
    scene->activeCamera = freeCamera;
    freeCamera->attachControl(canvas, true);
  }

}; // end of struct CamerasTypesScene

BABYLON_REGISTER_SAMPLE("Cameras", CamerasTypesScene)

} // end of namespace Samples
} // end of namespace BABYLON
<commit_msg>Formatting<commit_after>#include <babylon/cameras/arc_rotate_camera.h>
#include <babylon/cameras/free_camera.h>
#include <babylon/engines/scene.h>
#include <babylon/interfaces/irenderable_scene.h>
#include <babylon/lights/point_light.h>
#include <babylon/meshes/mesh.h>
#include <babylon/samples/babylon_register_sample.h>

namespace BABYLON {
namespace Samples {

/**
 * @brief Cameras scene demonstrating the types of cameras in babylonjs.
 * @see https://www.babylonjs-playground.com/#1A3M5C#0
 * @see https://doc.babylonjs.com/babylon101/cameras
 */
struct CamerasTypesScene : public IRenderableScene {

  CamerasTypesScene(ICanvas* iCanvas) : IRenderableScene(iCanvas)
  {
  }

  ~CamerasTypesScene() override = default;

  const char* getName() override
  {
    return "Cameras Scene";
  }

  void initializeScene(ICanvas* canvas, Scene* scene) override
  {
    // Setup a simple environment
    auto light0 = PointLight::New("Omni", Vector3(0.f, 2.f, 8.f), scene);
    light0->position().x += 0.f;
    auto box1 = Mesh::CreateBox("b1", 1.f, scene);
    box1->position().x += 0.f;
    auto box2          = Mesh::CreateBox("b2", 1.f, scene);
    box2->position().x = -3.f;
    auto box3          = Mesh::CreateBox("b3", 1.f, scene);
    box3->position().x = 3.f;

    // ArcRotateCamera >> Camera rotating around a 3D point (here Vector zero)
    // Parameters : name, alpha, beta, radius, target, scene
    auto arcCamera
      = ArcRotateCamera::New("ArcRotateCamera", 1.f, 0.8f, 10.f, Vector3(0.f, 0.f, 0.f), scene);
    arcCamera->setPosition(Vector3(0.f, 0.f, 50.f));
    arcCamera->target = Vector3(3.f, 0.f, 0.f);

    // FreeCamera >> You can move around the world with mouse and keyboard (LEFT/RIGHT/UP/DOWN)
    // Parameters : name, position, scene
    auto freeCamera      = FreeCamera::New("FreeCamera", Vector3(0.f, 0.f, 5.f), scene);
    freeCamera->rotation = Vector3(0.f, Math::PI, 0.f);

    // Attach a camera to the scene and the canvas
    scene->activeCamera = freeCamera;
    freeCamera->attachControl(canvas, true);
  }

}; // end of struct CamerasTypesScene

BABYLON_REGISTER_SAMPLE("Cameras", CamerasTypesScene)

} // end of namespace Samples
} // end of namespace BABYLON
<|endoftext|>


<commit_before>///////////////////////////////////////////////////////////////////////////////
//
// File MultiRegionsDemoTests.cpp
//
// For more information, please see: http://www.nektar.info
//
// The MIT License
//
// Copyright (c) 2006 Division of Applied Mathematics, Brown University (USA),
// Department of Aeronautics, Imperial College London (UK), and Scientific
// Computing and Imaging Institute, University of Utah (USA).
//
// License for the specific language governing rights and limitations under
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
// Description: Run a series of tests on the Incompressible Navier Stokes Solver
//
///////////////////////////////////////////////////////////////////////////////
#include "../../Auxiliary/RegressBase.h"
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <sys/stat.h>
#include <boost/filesystem.hpp>

void RunL2RegressionTest(std::string demo, std::string input, std::string info);
void MakeOkFile(std::string demo, std::string input, std::string info);

#ifdef MAKE_OK_FILE
#define Execute($1,$2,$3)  MakeOkFile($1,$2,$3)
#else
#define Execute($1,$2,$3)  RunL2RegressionTest($1,$2,$3)
#endif

#ifdef _WINDOWS
#define COPY_COMMAND "copy "
#else
#define COPY_COMMAND "cp "
#endif

static int tests_total = 0;
static int tests_passed = 0;
static int tests_failed = 0;
static bool verbose = false;
static bool quiet = false;

int main(int argc, char* argv[])
{
    if (argc > 2)
    {
        std::cout << "Usage: " << argv[0] << " [-v|-q]" << std::endl;
        return -1;
    }
    if (argc == 2 && std::string(argv[1]) == "-v")
    {
        verbose = true;
    }
    if (argc == 2 && std::string(argv[1]) == "-q")
    {
        quiet = true;
    }

    //Test Channel Flow
    Execute("IncNavierStokesSolver","Test_ChanFlow_m3.xml","Channel Flow P=3");
    Execute("IncNavierStokesSolver","Test_ChanFlow_m8.xml","Channel Flow P=8");
    Execute("IncNavierStokesSolver","Test_ChanFlow_m8_BodyForce.xml","Channel Flow P=8 BodyForce");
    Execute("IncNavierStokesSolver","Test_ChanFlow_m8_singular.xml","Channel Flow P=8 Singularity Check");
    Execute("IncNavierStokesSolver","Test_ChanFlow2D_bcsfromfiles.xml","Channel Flow P=5 Boundary Conditions from files");

    //Test Kovasznay Flow
    Execute("IncNavierStokesSolver","Test_KovaFlow_m3.xml","Kovasznay Flow P=3");
    Execute("IncNavierStokesSolver","Test_KovaFlow_m8.xml","Kovasznay Flow P=8");

    //Test Decaying Vortex
    Execute("IncNavierStokesSolver","Test_TaylorVor_dt1.xml","Convergence: Taylor Vortex IMEXOrder2 dt=0.01");
    Execute("IncNavierStokesSolver","Test_TaylorVor_dt2.xml","Convergence: Taylor Vortex IMEXOrder2 dt=0.001");

    //Test Coupled LinearNS Kovasznay Flow
    Execute("IncNavierStokesSolver","Test_KovaFlow_m8.xml","Steady Oseen Kovasznay flow P=6");
    Execute("IncNavierStokesSolver","Test_Kovas_Quad6_Tri4_mixedbcs.xml","Steady Oseen Kovasznay flow, mixed elements and bcs P=7");

    //Test Coupled LinearNS unsteady Channel Flow
    Execute("IncNavierStokesSolver","Test_ChanFlow_LinNS_m8.xml","Unsteady channel flow with coupled solver , P=8");

    //Test Modified Arnoldi direct stability (VelCorrectionScheme)
    Execute("IncNavierStokesSolver","ChanStability.xml","Linear stability (Mod. Arnoldi): Channel");

	//Test Modified Arnoldi adjoint stability (VelCorrectionScheme)
    Execute("IncNavierStokesSolver","ChanStability_adj.xml","Adjoint stability (Mod. Arnoldi): Channel");

	//Test Modified Arnoldi Transient growth  (VelCorrectionScheme)
	Execute("IncNavierStokesSolver","bfs_tg.xml","Transient Growth (Modified Arnoldi): Backward-facing step");

    #ifdef NEKTAR_USING_ARPACK
    //same stability tests with Arpack
	Execute("IncNavierStokesSolver","ChanStability_Ar.xml","Linear stability (Arpack): Channel");
	Execute("IncNavierStokesSolver","ChanStability_adj_Ar.xml","Adjoint stability (Arpack): Channel");
	Execute("IncNavierStokesSolver","bfs_tg-AR.xml","Transient Growth (Arpack): Backward-facing step");

	//Test Modified Arnoldi direct stability  (CoupledSolver)
	Execute("IncNavierStokesSolver","ChanStability_Coupled.xml","Linear stability with coupled solver (Arpack): Channel");
	#endif
    if (tests_failed && !quiet)
    {
        std::cout << "WARNING: " << tests_failed << " test(s) failed." << std::endl;
    }
    else if (verbose)
    {
        std::cout << "All tests passed successfully!" << std::endl;
    }
    return tests_failed;
}

void RunL2RegressionTest(std::string Demo, std::string input, std::string info)
{
    tests_total++;
    if (!quiet)
    {
        std::cout << "TESTING: " << Demo << std::flush;
    }
	std::string NektarSolverDir =std::string("") +  NEKTAR_SOLVER_DIR + "/dist/bin/";
    RegressBase Test(NektarSolverDir.c_str(),Demo,input,"Solvers/IncNavierStokesSolver/OkFiles/");
    int fail;

	std::string basename = input;
	basename.erase(basename.end()-4,basename.end());
	boost::filesystem::path filePath(std::string(REG_PATH) + "Solvers/IncNavierStokesSolver/InputFiles/" + basename);
	std::vector<std::string> extensions;
	extensions.push_back(".xml");
	extensions.push_back(".rst");
	extensions.push_back(".bse");
	extensions.push_back("_u_1.bc");
	extensions.push_back("_u_3.bc");
	extensions.push_back("_v_3.bc");

	for (unsigned int i = 0; i < extensions.size(); ++i)
	{
	    struct stat vFileInfo;
	    std::string source  = filePath.file_string() + extensions[i];
	    std::string command = std::string(COPY_COMMAND) + filePath.file_string() + extensions[i] + " .";
	    int vNotPresent = stat(source.c_str(), &vFileInfo);
	    if (!vNotPresent)
	    {
	        int status = system(command.c_str());
	        if(status)
	        {
	            std::cerr << "Unable to copy file:" << source << " to current location" << std::endl;
	            exit(2);
	        }
	    }
	}

    if(fail = Test.TestL2()) // test failed
    {
        if (!quiet)
        {
            std::cout << "\rFAILED: " << Demo << " " << input << " (" << info << ")" << std::endl;
            std::cout << "===========================================================\n";
            // Explain cause of error if available
            Test.PrintTestError(fail);
            std::cout << "===========================================================\n";
        }
        tests_failed++;
    }
    else
    {
        if (verbose)
        {
            std::cout << "\rPASSED: " << Demo << " " << input << " (" << info << ")" << std::endl;
        }
        else if (quiet)
        {
            // print nothing
        }
        else {
            std::cout << "\rPASSED: " << Demo << " (" << info << ")" << std::endl;
        }
        tests_passed++;
    }

#ifdef _WINDOWS
	std::string cleanup = "del /Q *.xml *.fld *.chk *.rst *.bc";
#else
    std::string cleanup = "rm -f *.xml *.fld *.chk *.rst *.bc";
#endif

    system(cleanup.c_str());
};

void MakeOkFile(std::string Demo, std::string input,				std::string info)
{
    tests_total++;
	std::string NektarSolverDir =std::string("") +  NEKTAR_SOLVER_DIR + "/dist/bin/";
    RegressBase Test(NektarSolverDir.c_str(),Demo,input,"Solvers/IncNavierStokesSolver/OkFiles/");
    int fail;

    std::string basename = input;
    basename.erase(basename.end()-4,basename.end());
    boost::filesystem::path filePath(std::string(REG_PATH) + "Solvers/IncNavierStokesSolver/InputFiles/" + basename);
    std::vector<std::string> extensions;
    extensions.push_back(".xml");
    extensions.push_back(".rst");
    extensions.push_back(".bse");
    extensions.push_back("_u_1.bc");
    extensions.push_back("_u_3.bc");
    extensions.push_back("_v_3.bc");

    for (unsigned int i = 0; i < extensions.size(); ++i)
    {
        struct stat vFileInfo;
        std::string source  = filePath.file_string() + extensions[i];
        std::string command = std::string(COPY_COMMAND) + filePath.file_string() + extensions[i] + " .";
        int vNotPresent = stat(source.c_str(), &vFileInfo);
        if (!vNotPresent)
        {
            int status = system(command.c_str());
            if(status)
            {
                std::cerr << "Unable to copy file:" << source << " to current location" << std::endl;
                exit(2);
            }
        }
    }

    if(fail = Test.MakeOkFile())
    {
        std::cout << "Failed to make OK file\n";
        // Explain cause of error if available
        std::cout << "===========================================================\n";
        Test.PrintTestError(fail);
        std::cout << "===========================================================\n";
        tests_failed++;
	}
#ifdef _WINDOWS
	std::string cleanup = "del /Q *.xml *.fld *.chk *.rst *.bc";
#else
    std::string cleanup = "rm -f *.xml *.fld *.chk *.rst *.bc";
#endif

    system(cleanup.c_str());
}

<commit_msg>Disabled Direct and adjoint arpack regression tests due to failure on some architectures.<commit_after>///////////////////////////////////////////////////////////////////////////////
//
// File MultiRegionsDemoTests.cpp
//
// For more information, please see: http://www.nektar.info
//
// The MIT License
//
// Copyright (c) 2006 Division of Applied Mathematics, Brown University (USA),
// Department of Aeronautics, Imperial College London (UK), and Scientific
// Computing and Imaging Institute, University of Utah (USA).
//
// License for the specific language governing rights and limitations under
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
// Description: Run a series of tests on the Incompressible Navier Stokes Solver
//
///////////////////////////////////////////////////////////////////////////////
#include "../../Auxiliary/RegressBase.h"
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <sys/stat.h>
#include <boost/filesystem.hpp>

void RunL2RegressionTest(std::string demo, std::string input, std::string info);
void MakeOkFile(std::string demo, std::string input, std::string info);

#ifdef MAKE_OK_FILE
#define Execute($1,$2,$3)  MakeOkFile($1,$2,$3)
#else
#define Execute($1,$2,$3)  RunL2RegressionTest($1,$2,$3)
#endif

#ifdef _WINDOWS
#define COPY_COMMAND "copy "
#else
#define COPY_COMMAND "cp "
#endif

static int tests_total = 0;
static int tests_passed = 0;
static int tests_failed = 0;
static bool verbose = false;
static bool quiet = false;

int main(int argc, char* argv[])
{
    if (argc > 2)
    {
        std::cout << "Usage: " << argv[0] << " [-v|-q]" << std::endl;
        return -1;
    }
    if (argc == 2 && std::string(argv[1]) == "-v")
    {
        verbose = true;
    }
    if (argc == 2 && std::string(argv[1]) == "-q")
    {
        quiet = true;
    }

    //Test Channel Flow
    Execute("IncNavierStokesSolver","Test_ChanFlow_m3.xml","Channel Flow P=3");
    Execute("IncNavierStokesSolver","Test_ChanFlow_m8.xml","Channel Flow P=8");
    Execute("IncNavierStokesSolver","Test_ChanFlow_m8_BodyForce.xml","Channel Flow P=8 BodyForce");
    Execute("IncNavierStokesSolver","Test_ChanFlow_m8_singular.xml","Channel Flow P=8 Singularity Check");
    Execute("IncNavierStokesSolver","Test_ChanFlow2D_bcsfromfiles.xml","Channel Flow P=5 Boundary Conditions from files");

    //Test Kovasznay Flow
    Execute("IncNavierStokesSolver","Test_KovaFlow_m3.xml","Kovasznay Flow P=3");
    Execute("IncNavierStokesSolver","Test_KovaFlow_m8.xml","Kovasznay Flow P=8");

    //Test Decaying Vortex
    Execute("IncNavierStokesSolver","Test_TaylorVor_dt1.xml","Convergence: Taylor Vortex IMEXOrder2 dt=0.01");
    Execute("IncNavierStokesSolver","Test_TaylorVor_dt2.xml","Convergence: Taylor Vortex IMEXOrder2 dt=0.001");

    //Test Coupled LinearNS Kovasznay Flow
    Execute("IncNavierStokesSolver","Test_KovaFlow_m8.xml","Steady Oseen Kovasznay flow P=6");
    Execute("IncNavierStokesSolver","Test_Kovas_Quad6_Tri4_mixedbcs.xml","Steady Oseen Kovasznay flow, mixed elements and bcs P=7");

    //Test Coupled LinearNS unsteady Channel Flow
    Execute("IncNavierStokesSolver","Test_ChanFlow_LinNS_m8.xml","Unsteady channel flow with coupled solver , P=8");

    //Test Modified Arnoldi direct stability (VelCorrectionScheme)
    Execute("IncNavierStokesSolver","ChanStability.xml","Linear stability (Mod. Arnoldi): Channel");

	//Test Modified Arnoldi adjoint stability (VelCorrectionScheme)
    Execute("IncNavierStokesSolver","ChanStability_adj.xml","Adjoint stability (Mod. Arnoldi): Channel");

	//Test Modified Arnoldi Transient growth  (VelCorrectionScheme)
	Execute("IncNavierStokesSolver","bfs_tg.xml","Transient Growth (Modified Arnoldi): Backward-facing step");

    #ifdef NEKTAR_USING_ARPACK
    //same stability tests with Arpack
	/// @todo Fix ChanStability_Ar regression test to work on all architectures
//	Execute("IncNavierStokesSolver","ChanStability_Ar.xml","Linear stability (Arpack): Channel");
//	Execute("IncNavierStokesSolver","ChanStability_adj_Ar.xml","Adjoint stability (Arpack): Channel");
	Execute("IncNavierStokesSolver","bfs_tg-AR.xml","Transient Growth (Arpack): Backward-facing step");

	//Test Modified Arnoldi direct stability  (CoupledSolver)
	Execute("IncNavierStokesSolver","ChanStability_Coupled.xml","Linear stability with coupled solver (Arpack): Channel");
	#endif
    if (tests_failed && !quiet)
    {
        std::cout << "WARNING: " << tests_failed << " test(s) failed." << std::endl;
    }
    else if (verbose)
    {
        std::cout << "All tests passed successfully!" << std::endl;
    }
    return tests_failed;
}

void RunL2RegressionTest(std::string Demo, std::string input, std::string info)
{
    tests_total++;
    if (!quiet)
    {
        std::cout << "TESTING: " << Demo << std::flush;
    }
	std::string NektarSolverDir =std::string("") +  NEKTAR_SOLVER_DIR + "/dist/bin/";
    RegressBase Test(NektarSolverDir.c_str(),Demo,input,"Solvers/IncNavierStokesSolver/OkFiles/");
    int fail;

	std::string basename = input;
	basename.erase(basename.end()-4,basename.end());
	boost::filesystem::path filePath(std::string(REG_PATH) + "Solvers/IncNavierStokesSolver/InputFiles/" + basename);
	std::vector<std::string> extensions;
	extensions.push_back(".xml");
	extensions.push_back(".rst");
	extensions.push_back(".bse");
	extensions.push_back("_u_1.bc");
	extensions.push_back("_u_3.bc");
	extensions.push_back("_v_3.bc");

	for (unsigned int i = 0; i < extensions.size(); ++i)
	{
	    struct stat vFileInfo;
	    std::string source  = filePath.file_string() + extensions[i];
	    std::string command = std::string(COPY_COMMAND) + filePath.file_string() + extensions[i] + " .";
	    int vNotPresent = stat(source.c_str(), &vFileInfo);
	    if (!vNotPresent)
	    {
	        int status = system(command.c_str());
	        if(status)
	        {
	            std::cerr << "Unable to copy file:" << source << " to current location" << std::endl;
	            exit(2);
	        }
	    }
	}

    if(fail = Test.TestL2()) // test failed
    {
        if (!quiet)
        {
            std::cout << "\rFAILED: " << Demo << " " << input << " (" << info << ")" << std::endl;
            std::cout << "===========================================================\n";
            // Explain cause of error if available
            Test.PrintTestError(fail);
            std::cout << "===========================================================\n";
        }
        tests_failed++;
    }
    else
    {
        if (verbose)
        {
            std::cout << "\rPASSED: " << Demo << " " << input << " (" << info << ")" << std::endl;
        }
        else if (quiet)
        {
            // print nothing
        }
        else {
            std::cout << "\rPASSED: " << Demo << " (" << info << ")" << std::endl;
        }
        tests_passed++;
    }

#ifdef _WINDOWS
	std::string cleanup = "del /Q *.xml *.fld *.chk *.rst *.bc";
#else
    std::string cleanup = "rm -f *.xml *.fld *.chk *.rst *.bc";
#endif

    system(cleanup.c_str());
};

void MakeOkFile(std::string Demo, std::string input,				std::string info)
{
    tests_total++;
	std::string NektarSolverDir =std::string("") +  NEKTAR_SOLVER_DIR + "/dist/bin/";
    RegressBase Test(NektarSolverDir.c_str(),Demo,input,"Solvers/IncNavierStokesSolver/OkFiles/");
    int fail;

    std::string basename = input;
    basename.erase(basename.end()-4,basename.end());
    boost::filesystem::path filePath(std::string(REG_PATH) + "Solvers/IncNavierStokesSolver/InputFiles/" + basename);
    std::vector<std::string> extensions;
    extensions.push_back(".xml");
    extensions.push_back(".rst");
    extensions.push_back(".bse");
    extensions.push_back("_u_1.bc");
    extensions.push_back("_u_3.bc");
    extensions.push_back("_v_3.bc");

    for (unsigned int i = 0; i < extensions.size(); ++i)
    {
        struct stat vFileInfo;
        std::string source  = filePath.file_string() + extensions[i];
        std::string command = std::string(COPY_COMMAND) + filePath.file_string() + extensions[i] + " .";
        int vNotPresent = stat(source.c_str(), &vFileInfo);
        if (!vNotPresent)
        {
            int status = system(command.c_str());
            if(status)
            {
                std::cerr << "Unable to copy file:" << source << " to current location" << std::endl;
                exit(2);
            }
        }
    }

    if(fail = Test.MakeOkFile())
    {
        std::cout << "Failed to make OK file\n";
        // Explain cause of error if available
        std::cout << "===========================================================\n";
        Test.PrintTestError(fail);
        std::cout << "===========================================================\n";
        tests_failed++;
	}
#ifdef _WINDOWS
	std::string cleanup = "del /Q *.xml *.fld *.chk *.rst *.bc";
#else
    std::string cleanup = "rm -f *.xml *.fld *.chk *.rst *.bc";
#endif

    system(cleanup.c_str());
}

<|endoftext|>


<commit_before>#ifndef BTREE_LOOF_NODE_HPP_
#define BTREE_LOOF_NODE_HPP_

// Eventually we'll rename loof to leaf, but right now I want the old code to look at.

namespace loof {

// These codes can appear as the first byte of a leaf node entry
// (values 250 or smaller are just key sizes for key/value pairs).

// Means we have a deletion entry.
const int DELETE_ENTRY_CODE = 255;

// Means we have a skipped entry exactly one byte long.
const int SKIP_ENTRY_CODE_ONE = 254;

// Means we have a skipped entry exactly two bytes long.
const int SKIP_ENTRY_CODE_TWO = 253;

// Means we have a skipped entry exactly N bytes long, of form { uint8_t 252; uint16_t N; char garbage[]; }
const int SKIP_ENTRY_CODE_MANY = 252;

// A reserved meaningless value.
const int SKIP_ENTRY_RESERVED = 251;

// We must maintain timestamps and deletion entries as best we can,
// with the following limitations.  The timestamps stored need not be
// more than the most `MANDATORY_TIMESTAMPS` recent timestamps.  The
// deletions stored need not be any more than what is necessary to
// fill `(block_size - offsetof(loof_t, pair_offsets)) /
// DELETION_RESERVE_FRACTION` bytes.  For example, with a 4084 block
// size, if the five most recent operations were deletions of 250-byte
// keys, we would only be required to store the 2 most recent
// deletions and the 2 most recent timestamps.

const int MANDATORY_TIMESTAMPS = 5;
const int DELETION_RESERVE_FRACTION = 10;

// The maximum fraction of leaf node memory that must be devoted to
// deletion entries, if necessary.  So deletion entries are limited by
// MANDATORY_TIMESTAMPS (only the deletion entries of that many most
// recent entries must be preserved) and by this fraction of the total
// buffer size (if the last five operations were deletions of 250-byte
// keys (in a 4096-block-size node), we'd only have to store 2
// deletions because that's how many it takes to overflow 410 (or a
// smaller number, since we subtract fixed costs).

struct entry_t;
struct value_t;

inline
bool entry_is_deletion(const entry_t *p) {
    uint8_t x = *reinterpret_cast<const uint8_t *>(p);
    rassert(x != 251);
    return x == DELETE_PAIR_CODE;
}

inline
bool entry_is_live(const entry_t *p) {
    uint8_t x = *reinterpret_cast<const uint8_t *>(p);
    rassert(x != 251);
    rassert(MAX_KEY_SIZE == 250);
    return x <= MAX_KEY_SIZE;
}

inline
bool entry_is_skip(const entry_t *p) {
    return !entry_is_deletion(p) && !entry_is_live(p);
}

template <class V>
bool entry_fits(value_sizer_t<V> *sizer, const entry_t *p, int size) {
    if (size < 1) {
        return false;
    }

    uint8_t code = *reinterpret_cast<const uint8_t *>(p);
    switch (code) {
    case DELETE_ENTRY_CODE:
        return entry_key(p)->fits(size - 1);
    case SKIP_ENTRY_CODE_ONE:
        return true;
    case SKIP_ENTRY_CODE_TWO:
        return size >= 2;
    case SKIP_ENTRY_CODE_MANY:
        return size >= 3 && size >= 3 + *reinterpret_cast<const uint16_t *>(1 + reinterpret_cast<const char *>(p));
    default:
        rassert(code <= MAX_KEY_SIZE);
        return entry_key(p)->fits(size) && sizer->fits(entry_value<V>(p), size - entry_key(p)->full_size());
    }
}

inline
const btree_key_t *entry_key(const entry_t *p) {
    if (entry_is_deletion(p)) {
        return reinterpret_cast<const btree_key_t *>(1 + reinterpret_cast<const char *>(p));
    } else {
        return reinterpret_cast<const btree_key_t *>(p);
    }
}

template <class V>
const V *entry_value(const entry_t *p) {
    if (entry_is_deletion(p)) {
        return NULL;
    } else {
        return reinterpret_cast<const V *>(reinterpret_cast<const char *>(p) + entry_key(p)->full_size());
    }
}

template <class V>
int entry_size(value_sizer_t<V> *sizer, const entry_t *p) {
    uint8_t code = *reinterpret_cast<const uint8_t *>(p);
    switch (code) {
    case DELETE_ENTRY_CODE:
        return 1 + entry_key(p)->full_size();
    case SKIP_ENTRY_CODE_ONE:
        return 1;
    case SKIP_ENTRY_CODE_TWO:
        return 2;
    case SKIP_ENTRY_CODE_MANY:
        return 3 + *reinterpret_cast<const uint16_t *>(1 + reinterpret_cast<const char *>(p));
    default:
        rassert(code <= MAX_KEY_SIZE);
        return entry_key(p)->full_size() + sizer->size(entry_value<V>(p));
    }
}

struct loof_t {
    // The value-type-specific magic value.
    block_magic_t magic;

    // The size of pair_offsets.
    uint16_t num_pairs;

    // The number of timestamps we have (stored after the pair_offsets).
    uint16_t num_tstamps;

    // The total size (in bytes) of the live entries and their 2-byte
    // pair offsets in pair_offsets.
    uint16_t live_size;

    // The frontmost offset.
    uint16_t frontmost;

    // The pair offsets.
    uint16_t pair_offsets[];

    // The timestamps are stored after the pair offsets.
    repli_timestamp_t *tstamps() const {
        return reinterpret_cast<repli_timestamp_t *>(pair_offsets + num_pairs);
    }
};

const entry_t *get_entry(const loof_t *node, int offset) {
    return reinterpret_cast<const entry_t *>(reinterpret_cast<const char *>(node) + offset);
}

entry_t *get_entry(loof_t *node, int offset) {
    return reinterpret_cast<entry_t *>(reinterpret_cast<char *>(node) + offset);
}

struct entry_iter_t {
    int offset;
    int tstamp_index;

    template <class V>
    void step(value_sizer_t<V> *sizer, const loof_t *node) {
	rassert(!done(sizer));

	offset += entry_size(get_entry(node, offset));

	rassert(tstamp_index <= node->num_tstamps);
	tstamp_index += tstamp_index < node->num_tstamps;
    }

    bool done(value_sizer_t<V> *sizer) const {
	rassert(offset <= sizer->block_size().value());
	return offset >= sizer->block_size().value();
    }

    static entry_iter_t make(const loof_t *node) {
	entry_iter_t ret;
	ret.offset = node->frontmost;
	ret.tstamp_index = 0;
	return ret;
    }
};

template <class V>
void init(value_sizer_t<V> *sizer, loof_t *node) {
    node->magic = sizer->btree_leaf_magic();
    node->num_pairs = 0;
    node->num_tstamps = 0;
    node->live_size = 0;
    node->frontmost = sizer->block_size().value();
}

template <class V>
int free_space(value_sizer_t<V> *sizer) {
    return sizer->block_size().value() - offsetof(loof_t, pair_offsets);
}

// Returns the mandatory storage cost of the node, returning a value
// in the closed interval [0, free_space(sizer)].  Outputs the offset
// of the first entry for which storing a timestamp is not mandatory.
template <class V>
int mandatory_cost(value_sizer_t<V> *sizer, const loof_t *node, int required_timestamps, int *tstamp_back_offset_out) {
    int size = node->live_size;

    // node->live_size does not include deletion entries, deletion
    // entries' timestamps, and live entries' timestamps.  We add that
    // to size.

    entry_iter_t iter = entry_iter_t::make(node);
    int count = 0;
    int deletions_cost = 0;
    int max_deletions_cost = free_space(sizer) / DELETION_RESERVE_FRACTION;
    while (!(count == required_timestamps || iter.done(sizer) || iter.tstamp_index == node->num_tstamps)) {

	entry_t *ent = get_entry(node, iter.offset);
	if (entry_is_deletion(ent)) {
            if (deletions_cost >= max_deletions_cost) {
                break;
            }

            int this_entry_cost = sizeof(uint16_t) + sizeof(repli_timestamp_t) + entry_size(ent);
            deletions_cost += this_entry_cost;
	    size += this_entry_cost;
	    ++count;
	} else if (entry_is_live(ent)) {
	    ++count;
	    size += sizeof(repli_timestamp_t);
	}

	iter.step(sizer, node);
    }

    *tstamp_back_offset_out = iter.offset;

    return size;
}

template <class V>
int mandatory_cost(value_sizer_t<V> *sizer, const loof_t *node, int required_timestamps) {
    int ignored;
    return mandatory_cost(sizer, node, required_timestamps, &ignored);
}

template <class V>
int loof_epsilon(value_sizer_t<V> *sizer) {
    // Returns the maximum possible entry size, i.e. the key cost plus
    // the value cost plus pair_offsets plus timestamp cost.

    int key_cost = sizeof(uint8_t) + MAX_KEY_SIZE;

    // If the value is always empty, the DELETE_ENTRY_CODE byte needs to be considered.
    int n = std::max(sizer->max_possible_size(), 1);
    int pair_offsets_cost = sizeof(uint16_t);
    int timestamp_cost = sizeof(repli_timestamp_t);

    return key_cost + n + pair_offsets_cost + timestamp_cost;
}

template <class V>
bool is_full(value_sizer_t<V> *sizer, const loof_t *node, const btree_key_t *key, const V *value) {

    // Upon an insertion, we preserve `MANDATORY_TIMESTAMPS - 1`
    // timestamps and add our own (accounted for below)
    int size = mandatory_cost(sizer, node, MANDATORY_TIMESTAMPS - 1);

    // Add the space we'll need for the new key/value pair we would
    // insert.  We conservatively assume the key is not already
    // contained in the node.

    size += sizeof(uint16_t) + sizeof(repli_timestamp_t) + key->full_size() + sizer->size(value);

    // The node is full if we can't fit all that data within the free space.
    return size > free_space(sizer);
}

template <class V>
bool is_underfull(value_sizer_t<V> *sizer, const loof_t *node) {

    // An underfull node is one whose mandatory fields' cost
    // constitutes significantly less than half the free space, where
    // "significantly" is enough to prevent a split-then-merge.

    // (Note that x / y is indeed taken to mean floor(x / y) below.)

    // A split node's size S is always within loof_epsilon of
    // free_space and then is split as evenly as possible.  This means
    // the two resultant nodes' sizes are both no less than S / 2 -
    // loof_epsilon / 2, which is no less than (free_space -
    // loof_epsilon) / 2 - loof_epsilon / 2.  Which is no less than is
    // free_space / 2 - loof_epsilon.  We don't want an immediately
    // split node to be underfull, hence the threshold used below.

    return mandatory_cost(sizer, node, MANDATORY_TIMESTAMPS) < free_space(sizer) / 2 - loof_epsilon(sizer);
}

template <class V>
void split(value_sizer_t<V> *sizer, loof_t *node, loof_t *rnode, btree_key_t *median_out) {
    int tstamp_back_offset;
    int mandatory = mandatory_cost(sizer, node, MANDATORY_TIMESTAMPS, &tstamp_back_offset);

    rassert(mandatory >= free_space(sizer) - loof_epsilon(sizer));

    // We shall split the mandatory cost of this node as evenly as possible.

    int i = 0;
    int prev_lcost = 0;
    int lcost = 0;
    while (i < node->num_pairs && 2 * lcost < mandatory) {
        int offset = node->pair_offsets[i];
        entry_t *ent = get_entry(node, offset);

        // We only take mandatory entries' costs into consideration,
        // which guarantees correct behavior (in that neither node nor
        // can become underfull after a split).  If we didn't do this,
        // it would be possible to bias one node with a bunch of
        // deletions that makes its mandatory_cost artificially small.

        if (entry_is_live(ent)) {
            prev_lcost = lcost;
            lcost += entry_size(entry) + sizeof(uint16_t) + (offset < tstamp_back_offset ? sizeof(repli_timestamp_t) : 0);
        } else {
            rassert(entry_is_deletion(ent));

            if (offset < tstamp_back_offset) {
                prev_lcost = lcost;
                lcost += entry_size(entry) + sizeof(uint16_t) + sizeof(repli_timestamp_t);
            }
        }

        lcost += sz + (node->pair_offsets[i] < tstamp_back_offset ? sizeof(repli_timestamp_t) : 0);

        ++i;
    }

    // Since the mandatory_cost is at least free_space - loof_epsilon there's no way i can equal num_pairs or zero.
    rassert(i < node->num_pairs);
    rassert(i > 0);

    // Now prev_lcost and lcost envelope mandatory / 2.
    rassert(prev_lcost <= mandatory / 2);
    rassert(lcost > mandatory / 2);

    int s;
#ifndef NDEBUG
    int end_lcost;
#endif
    if ((mandatory - prev_lcost) - prev_lcost < lcost - (mandatory - lcost)) {
#ifndef NDEBUG
        end_lcost = prev_lcost;
#endif
        s = i - 1;
    } else {
#ifndef NDEBUG
        end_lcost = lcost;
#endif
        s = i;
    }

    // If our math was right, neither node can be underfull just
    // considering the split of the mandatory costs.
    rassert(end_lcost >= free_space(sizer) / 2 - loof_epsilon(sizer));
    rassert(mandatory - end_lcost >= free_space(sizer) / 2 - loof_epsilon(sizer));

    // Now we wish to move the elements at indices [s, num_pairs) to rnode.

    init(sizer, rnode);

    move_elements(sizer, node, s, node->num_pairs, rnode);

    node->num_pairs = s;
}

}  // namespace loof

#endif  BTREE_LOOF_NODE_HPP_
<commit_msg>Got rid of num_tstamps and instead use tstamp_cutpoint.<commit_after>#ifndef BTREE_LOOF_NODE_HPP_
#define BTREE_LOOF_NODE_HPP_

// Eventually we'll rename loof to leaf, but right now I want the old code to look at.

namespace loof {

// These codes can appear as the first byte of a leaf node entry
// (values 250 or smaller are just key sizes for key/value pairs).

// Means we have a deletion entry.
const int DELETE_ENTRY_CODE = 255;

// Means we have a skipped entry exactly one byte long.
const int SKIP_ENTRY_CODE_ONE = 254;

// Means we have a skipped entry exactly two bytes long.
const int SKIP_ENTRY_CODE_TWO = 253;

// Means we have a skipped entry exactly N bytes long, of form { uint8_t 252; uint16_t N; char garbage[]; }
const int SKIP_ENTRY_CODE_MANY = 252;

// A reserved meaningless value.
const int SKIP_ENTRY_RESERVED = 251;

// We must maintain timestamps and deletion entries as best we can,
// with the following limitations.  The timestamps stored need not be
// more than the most `MANDATORY_TIMESTAMPS` recent timestamps.  The
// deletions stored need not be any more than what is necessary to
// fill `(block_size - offsetof(loof_t, pair_offsets)) /
// DELETION_RESERVE_FRACTION` bytes.  For example, with a 4084 block
// size, if the five most recent operations were deletions of 250-byte
// keys, we would only be required to store the 2 most recent
// deletions and the 2 most recent timestamps.

const int MANDATORY_TIMESTAMPS = 5;
const int DELETION_RESERVE_FRACTION = 10;

// The maximum fraction of leaf node memory that must be devoted to
// deletion entries, if necessary.  So deletion entries are limited by
// MANDATORY_TIMESTAMPS (only the deletion entries of that many most
// recent entries must be preserved) and by this fraction of the total
// buffer size (if the last five operations were deletions of 250-byte
// keys (in a 4096-block-size node), we'd only have to store 2
// deletions because that's how many it takes to overflow 410 (or a
// smaller number, since we subtract fixed costs).

struct entry_t;
struct value_t;

inline
bool entry_is_deletion(const entry_t *p) {
    uint8_t x = *reinterpret_cast<const uint8_t *>(p);
    rassert(x != 251);
    return x == DELETE_PAIR_CODE;
}

inline
bool entry_is_live(const entry_t *p) {
    uint8_t x = *reinterpret_cast<const uint8_t *>(p);
    rassert(x != 251);
    rassert(MAX_KEY_SIZE == 250);
    return x <= MAX_KEY_SIZE;
}

inline
bool entry_is_skip(const entry_t *p) {
    return !entry_is_deletion(p) && !entry_is_live(p);
}

template <class V>
bool entry_fits(value_sizer_t<V> *sizer, const entry_t *p, int size) {
    if (size < 1) {
        return false;
    }

    uint8_t code = *reinterpret_cast<const uint8_t *>(p);
    switch (code) {
    case DELETE_ENTRY_CODE:
        return entry_key(p)->fits(size - 1);
    case SKIP_ENTRY_CODE_ONE:
        return true;
    case SKIP_ENTRY_CODE_TWO:
        return size >= 2;
    case SKIP_ENTRY_CODE_MANY:
        return size >= 3 && size >= 3 + *reinterpret_cast<const uint16_t *>(1 + reinterpret_cast<const char *>(p));
    default:
        rassert(code <= MAX_KEY_SIZE);
        return entry_key(p)->fits(size) && sizer->fits(entry_value<V>(p), size - entry_key(p)->full_size());
    }
}

inline
const btree_key_t *entry_key(const entry_t *p) {
    if (entry_is_deletion(p)) {
        return reinterpret_cast<const btree_key_t *>(1 + reinterpret_cast<const char *>(p));
    } else {
        return reinterpret_cast<const btree_key_t *>(p);
    }
}

template <class V>
const V *entry_value(const entry_t *p) {
    if (entry_is_deletion(p)) {
        return NULL;
    } else {
        return reinterpret_cast<const V *>(reinterpret_cast<const char *>(p) + entry_key(p)->full_size());
    }
}

template <class V>
int entry_size(value_sizer_t<V> *sizer, const entry_t *p) {
    uint8_t code = *reinterpret_cast<const uint8_t *>(p);
    switch (code) {
    case DELETE_ENTRY_CODE:
        return 1 + entry_key(p)->full_size();
    case SKIP_ENTRY_CODE_ONE:
        return 1;
    case SKIP_ENTRY_CODE_TWO:
        return 2;
    case SKIP_ENTRY_CODE_MANY:
        return 3 + *reinterpret_cast<const uint16_t *>(1 + reinterpret_cast<const char *>(p));
    default:
        rassert(code <= MAX_KEY_SIZE);
        return entry_key(p)->full_size() + sizer->size(entry_value<V>(p));
    }
}

struct loof_t {
    // The value-type-specific magic value.
    block_magic_t magic;

    // The size of pair_offsets.
    uint16_t num_pairs;

    // The total size (in bytes) of the live entries and their 2-byte
    // pair offsets in pair_offsets.
    uint16_t live_size;

    // The frontmost offset.
    uint16_t frontmost;

    // The first offset whose entry is not accompanied by a timestamp.
    uint16_t tstamp_cutpoint;

    // The pair offsets.
    uint16_t pair_offsets[];
};

const entry_t *get_entry(const loof_t *node, int offset) {
    return reinterpret_cast<const entry_t *>(reinterpret_cast<const char *>(node) + offset + (offset < node->tstamp_cutpoint ? sizeof(repli_timestamp_t) : 0));
}

entry_t *get_entry(loof_t *node, int offset) {
    return reinterpret_cast<entry_t *>(reinterpret_cast<char *>(node) + offset + (offset < node->tstamp_cutpoint ? sizeof(repli_timestamp_t) : 0));
}

struct entry_iter_t {
    int offset;

    template <class V>
    void step(value_sizer_t<V> *sizer, const loof_t *node) {
	rassert(!done(sizer));

	offset += entry_size(get_entry(node, offset));
    }

    bool done(value_sizer_t<V> *sizer) const {
	rassert(offset <= sizer->block_size().value());
	return offset >= sizer->block_size().value();
    }

    static entry_iter_t make(const loof_t *node) {
	entry_iter_t ret;
	ret.offset = node->frontmost;
	return ret;
    }
};

template <class V>
void init(value_sizer_t<V> *sizer, loof_t *node) {
    node->magic = sizer->btree_leaf_magic();
    node->num_pairs = 0;
    node->live_size = 0;
    node->frontmost = sizer->block_size().value();
    node->tstamp_cutpoint = node->frontmost;
}

template <class V>
int free_space(value_sizer_t<V> *sizer) {
    return sizer->block_size().value() - offsetof(loof_t, pair_offsets);
}

// Returns the mandatory storage cost of the node, returning a value
// in the closed interval [0, free_space(sizer)].  Outputs the offset
// of the first entry for which storing a timestamp is not mandatory.
template <class V>
int mandatory_cost(value_sizer_t<V> *sizer, const loof_t *node, int required_timestamps, int *tstamp_back_offset_out) {
    int size = node->live_size;

    // node->live_size does not include deletion entries, deletion
    // entries' timestamps, and live entries' timestamps.  We add that
    // to size.

    entry_iter_t iter = entry_iter_t::make(node);
    int count = 0;
    int deletions_cost = 0;
    int max_deletions_cost = free_space(sizer) / DELETION_RESERVE_FRACTION;
    while (!(count == required_timestamps || iter.done(sizer) || iter.offset >= node->tstamp_cutpoint)) {

	entry_t *ent = get_entry(node, iter.offset);
	if (entry_is_deletion(ent)) {
            if (deletions_cost >= max_deletions_cost) {
                break;
            }

            int this_entry_cost = sizeof(uint16_t) + sizeof(repli_timestamp_t) + entry_size(ent);
            deletions_cost += this_entry_cost;
	    size += this_entry_cost;
	    ++count;
	} else if (entry_is_live(ent)) {
	    ++count;
	    size += sizeof(repli_timestamp_t);
	}

	iter.step(sizer, node);
    }

    *tstamp_back_offset_out = iter.offset;

    return size;
}

template <class V>
int mandatory_cost(value_sizer_t<V> *sizer, const loof_t *node, int required_timestamps) {
    int ignored;
    return mandatory_cost(sizer, node, required_timestamps, &ignored);
}

template <class V>
int loof_epsilon(value_sizer_t<V> *sizer) {
    // Returns the maximum possible entry size, i.e. the key cost plus
    // the value cost plus pair_offsets plus timestamp cost.

    int key_cost = sizeof(uint8_t) + MAX_KEY_SIZE;

    // If the value is always empty, the DELETE_ENTRY_CODE byte needs to be considered.
    int n = std::max(sizer->max_possible_size(), 1);
    int pair_offsets_cost = sizeof(uint16_t);
    int timestamp_cost = sizeof(repli_timestamp_t);

    return key_cost + n + pair_offsets_cost + timestamp_cost;
}

template <class V>
bool is_full(value_sizer_t<V> *sizer, const loof_t *node, const btree_key_t *key, const V *value) {

    // Upon an insertion, we preserve `MANDATORY_TIMESTAMPS - 1`
    // timestamps and add our own (accounted for below)
    int size = mandatory_cost(sizer, node, MANDATORY_TIMESTAMPS - 1);

    // Add the space we'll need for the new key/value pair we would
    // insert.  We conservatively assume the key is not already
    // contained in the node.

    size += sizeof(uint16_t) + sizeof(repli_timestamp_t) + key->full_size() + sizer->size(value);

    // The node is full if we can't fit all that data within the free space.
    return size > free_space(sizer);
}

template <class V>
bool is_underfull(value_sizer_t<V> *sizer, const loof_t *node) {

    // An underfull node is one whose mandatory fields' cost
    // constitutes significantly less than half the free space, where
    // "significantly" is enough to prevent a split-then-merge.

    // (Note that x / y is indeed taken to mean floor(x / y) below.)

    // A split node's size S is always within loof_epsilon of
    // free_space and then is split as evenly as possible.  This means
    // the two resultant nodes' sizes are both no less than S / 2 -
    // loof_epsilon / 2, which is no less than (free_space -
    // loof_epsilon) / 2 - loof_epsilon / 2.  Which is no less than is
    // free_space / 2 - loof_epsilon.  We don't want an immediately
    // split node to be underfull, hence the threshold used below.

    return mandatory_cost(sizer, node, MANDATORY_TIMESTAMPS) < free_space(sizer) / 2 - loof_epsilon(sizer);
}

template <class V>
void split(value_sizer_t<V> *sizer, loof_t *node, loof_t *rnode, btree_key_t *median_out) {
    int tstamp_back_offset;
    int mandatory = mandatory_cost(sizer, node, MANDATORY_TIMESTAMPS, &tstamp_back_offset);

    rassert(mandatory >= free_space(sizer) - loof_epsilon(sizer));

    // We shall split the mandatory cost of this node as evenly as possible.

    int i = 0;
    int prev_lcost = 0;
    int lcost = 0;
    while (i < node->num_pairs && 2 * lcost < mandatory) {
        int offset = node->pair_offsets[i];
        entry_t *ent = get_entry(node, offset);

        // We only take mandatory entries' costs into consideration,
        // which guarantees correct behavior (in that neither node nor
        // can become underfull after a split).  If we didn't do this,
        // it would be possible to bias one node with a bunch of
        // deletions that makes its mandatory_cost artificially small.

        if (entry_is_live(ent)) {
            prev_lcost = lcost;
            lcost += entry_size(entry) + sizeof(uint16_t) + (offset < tstamp_back_offset ? sizeof(repli_timestamp_t) : 0);
        } else {
            rassert(entry_is_deletion(ent));

            if (offset < tstamp_back_offset) {
                prev_lcost = lcost;
                lcost += entry_size(entry) + sizeof(uint16_t) + sizeof(repli_timestamp_t);
            }
        }

        lcost += sz + (node->pair_offsets[i] < tstamp_back_offset ? sizeof(repli_timestamp_t) : 0);

        ++i;
    }

    // Since the mandatory_cost is at least free_space - loof_epsilon there's no way i can equal num_pairs or zero.
    rassert(i < node->num_pairs);
    rassert(i > 0);

    // Now prev_lcost and lcost envelope mandatory / 2.
    rassert(prev_lcost <= mandatory / 2);
    rassert(lcost > mandatory / 2);

    int s;
#ifndef NDEBUG
    int end_lcost;
#endif
    if ((mandatory - prev_lcost) - prev_lcost < lcost - (mandatory - lcost)) {
#ifndef NDEBUG
        end_lcost = prev_lcost;
#endif
        s = i - 1;
    } else {
#ifndef NDEBUG
        end_lcost = lcost;
#endif
        s = i;
    }

    // If our math was right, neither node can be underfull just
    // considering the split of the mandatory costs.
    rassert(end_lcost >= free_space(sizer) / 2 - loof_epsilon(sizer));
    rassert(mandatory - end_lcost >= free_space(sizer) / 2 - loof_epsilon(sizer));

    // Now we wish to move the elements at indices [s, num_pairs) to rnode.

    init(sizer, rnode);

    move_elements(sizer, node, s, node->num_pairs, rnode);

    node->num_pairs = s;
}

}  // namespace loof

#endif  BTREE_LOOF_NODE_HPP_
<|endoftext|>


<commit_before>#include <iostream>
#include <typeinfo>

#include <map>
#include <boost/concept_check.hpp>

using std::cout;
using std::endl;

#include "viennagrid/forwards.hpp"

#include "viennagrid/storage/view.hpp"
#include "viennagrid/storage/container_collection.hpp"
#include "viennagrid/storage/inserter.hpp"
#include "viennagrid/storage/id_generator.hpp"
#include "viennagrid/storage/hidden_key_map.hpp"
#include "viennagrid/storage/range.hpp"

#include "viennagrid/topology/point.hpp"
#include "viennagrid/topology/line.hpp"
#include "viennagrid/topology/simplex.hpp"
#include "viennagrid/topology/plc.hpp"

#include "viennagrid/element/element_config.hpp"
#include "viennagrid/element/element_key.hpp"
#include "viennagrid/element/element_orientation.hpp"
#include "viennagrid/element/element_view.hpp"

#include "viennagrid/point.hpp"

#include "viennagrid/config/generic_config.hpp"

#include "viennagrid/domain/topologic_domain.hpp"
#include "viennagrid/domain/metainfo.hpp"
#include "viennagrid/domain/geometric_domain.hpp"
#include "viennagrid/domain/config.hpp"

int main()
{

    //
    // First define the type of hook to use:
    //

//     typedef viennagrid::storage::pointer_hook_tag hook_tag;
    //typedef viennagrid::storage::iterator_hook_tag hook_tag;
    typedef viennagrid::storage::id_hook_tag hook_tag;

    //
    // typedefing and setting up the topological domain
    //

    typedef viennagrid::result_of::geometric_domain_config<viennagrid::plc_tag, viennagrid::config::point_type_2d, viennagrid::storage::pointer_hook_tag>::type domain_config;

    //typedef viennagrid::config::polygonal_2d_domain domain_type;
    typedef viennagrid::result_of::geometric_domain< domain_config >::type domain_type;
    domain_type domain;

    //
    // typedefs for the element types
    //

    typedef viennagrid::result_of::point_type<domain_type>::type point_type;

    typedef viennagrid::result_of::element<domain_type, viennagrid::vertex_tag>::type vertex_type;
    typedef viennagrid::result_of::element_hook<domain_type, viennagrid::vertex_tag>::type vertex_hook_type;

    typedef viennagrid::result_of::element<domain_type, viennagrid::line_tag>::type line_type;
    typedef viennagrid::result_of::element_hook<domain_type, viennagrid::line_tag>::type line_hook_type;

    typedef viennagrid::result_of::element<domain_type, viennagrid::polygon_tag>::type polygon_type;
    typedef viennagrid::result_of::element_hook<domain_type, viennagrid::polygon_tag>::type polygon_hook_type;

    std::vector<vertex_hook_type> v;

    v.push_back( viennagrid::create_element<vertex_type>( domain, point_type(0, 0) ) );
    v.push_back( viennagrid::create_element<vertex_type>( domain, point_type(10, 0) ) );
    v.push_back( viennagrid::create_element<vertex_type>( domain, point_type(20, 10) ) );
    v.push_back( viennagrid::create_element<vertex_type>( domain, point_type(20, 20) ) );
    v.push_back( viennagrid::create_element<vertex_type>( domain, point_type(10, 20) ) );
    v.push_back( viennagrid::create_element<vertex_type>( domain, point_type(0, 10) ) );
    v.push_back( viennagrid::create_element<vertex_type>( domain, point_type(5, 5) ) );

    v.push_back( viennagrid::create_element<vertex_type>( domain, point_type(10, 10) ) );
    v.push_back( viennagrid::create_element<vertex_type>( domain, point_type(12, 10) ) );
    v.push_back( viennagrid::create_element<vertex_type>( domain, point_type(10, 12) ) );

    v.push_back( viennagrid::create_element<vertex_type>( domain, point_type(8, 10) ) );

    v.push_back( viennagrid::create_element<vertex_type>( domain, point_type(15, 15) ) );

    polygon_hook_type bounding_poly = viennagrid::create_element<polygon_type>( domain, v.begin(), v.begin() + 7 );

    polygon_hook_type hole_poly = viennagrid::create_element<polygon_type>( domain, v.begin() + 7, v.begin() + 10 );

    line_hook_type line = viennagrid::create_element<line_type>( domain, v.begin() + 9, v.begin() + 11 );

    vertex_hook_type point = v[11];

    std::cout << bounding_poly << std::endl;
    std::cout << viennagrid::dereference_hook(domain, bounding_poly) << std::endl;
    std::cout << hole_poly << std::endl;
    std::cout << viennagrid::dereference_hook(domain, hole_poly) << std::endl;

    typedef viennagrid::result_of::element<domain_type, viennagrid::plc_tag>::type plc_type;
    typedef viennagrid::result_of::element_hook<domain_type, viennagrid::plc_tag>::type plc_hook_type;

    plc_hook_type plc_hook = viennagrid::create_element<plc_type>(  domain,
                                                                    &bounding_poly, &bounding_poly + 1,
                                                                    &hole_poly, &hole_poly + 1,
                                                                    &line, &line + 1,
                                                                    &point, &point + 1 );

    plc_type & plc = viennagrid::dereference_hook(domain, plc_hook);

    //std::cout << plc.get_bounding_polygon() << std::endl;

    typedef viennagrid::result_of::element_range<plc_type, vertex_type>::type vertex_on_plc_range;
    typedef viennagrid::result_of::iterator<vertex_on_plc_range>::type vertex_on_plc_iterator;

    std::cout << "All vertices of the PLC" << std::endl;
    vertex_on_plc_range vertex_range = viennagrid::elements<vertex_type>( plc );
    for (vertex_on_plc_iterator it = vertex_range.begin(); it != vertex_range.end(); ++it)
        std::cout << *it << " " << viennagrid::point(domain, *it) << " is loose: " << viennagrid::is_tagged<viennagrid::loose_tag>(*it, plc) << std::endl;
    std::cout << std::endl;

    typedef viennagrid::result_of::element_range<plc_type, line_type>::type line_on_plc_range;
    typedef viennagrid::result_of::iterator<line_on_plc_range>::type line_on_plc_iterator;

    std::cout << "All lines of the PLC" << std::endl;
    line_on_plc_range line_range = viennagrid::elements<line_type>( plc );
    for (line_on_plc_iterator it = line_range.begin(); it != line_range.end(); ++it)
        std::cout << *it << " is loose: " << viennagrid::is_tagged<viennagrid::loose_tag>(*it, plc) << std::endl;
    std::cout << std::endl;

    std::cout << "All PLCs of the domain" << std::endl;
    typedef viennagrid::result_of::element_range< domain_type, plc_type >::type plc_range_type;
    plc_range_type plc_range = viennagrid::elements< plc_type >(domain);
    for ( plc_range_type::iterator it = plc_range.begin(); it != plc_range.end(); ++it)
        std::cout << *it << std::endl;
    std::cout << std::endl;

    //std::copy( plc_range.begin(), plc_range.end(), std::ostream_iteratr<plc_type>( std::cout, "\n" ) );

    typedef viennagrid::result_of::const_element_view<plc_type, vertex_type>::type vertex_view_type;
    typedef viennagrid::result_of::iterator<vertex_view_type>::type vertex_view_iterator;

    std::cout << "All loose points of the plc" << std::endl;
    vertex_view_type vertex_view = viennagrid::loose_elements<vertex_type>(plc); // viennagrid::element_view<vertex_type>( plc, viennagrid::loose_predicate<plc_type>(plc) );
    for (vertex_view_iterator it = vertex_view.begin(); it != vertex_view.end(); ++it)
        std::cout << *it << std::endl;
    std::cout << std::endl;

    typedef viennagrid::result_of::element_view<plc_type, polygon_type>::type polygon_view_type;

    std::cout << "All hole polygons of the plc" << std::endl;
    polygon_view_type hole_polygons = viennagrid::hole_elements<polygon_type>(plc);
    std::copy( hole_polygons.begin(), hole_polygons.end(), std::ostream_iterator<polygon_type>(std::cout, "\n") );

    std::cout << "All bounding polygons of the plc" << std::endl;
    polygon_view_type bounding_polygons = viennagrid::bounding_elements<polygon_type>(plc);
    std::copy( bounding_polygons.begin(), bounding_polygons.end(), std::ostream_iterator<polygon_type>(std::cout, "\n") );

    typedef viennagrid::result_of::element_view<plc_type, line_type>::type line_view_type;

    std::cout << "All inner lines of the plc" << std::endl;
    line_view_type inner_lines = viennagrid::untagged_elements<line_type, viennagrid::bounding_tag>(plc);
    std::copy( inner_lines.begin(), inner_lines.end(), std::ostream_iterator<line_type>(std::cout, "\n") );

//     std::cout << std::endl << std::endl;
//     std::copy( viennagrid::elements<viennagrid::polygon_tag>(domain).begin(), viennagrid::elements<viennagrid::polygon_tag>(domain).end(), std::ostream_iterator<polygon_type>(std::cout, "\n") );
//
//     std::cout << std::endl << std::endl;
//     std::copy( viennagrid::elements<viennagrid::hole_polygon_tag>(domain).begin(), viennagrid::elements<viennagrid::hole_polygon_tag>(domain).end(), std::ostream_iterator<hole_polygon_type>(std::cout, "\n") );
//
//     std::cout << std::endl << std::endl;
//     std::copy( viennagrid::elements<viennagrid::hole_polygon_tag>(plc).begin(), viennagrid::elements<viennagrid::hole_polygon_tag>(plc).end(), std::ostream_iterator<hole_polygon_type>(std::cout, "\n") );

    return 0;
}
<commit_msg>added element_creation header adapted to new tagging system<commit_after>#include <iostream>
#include <typeinfo>

#include <map>
#include <boost/concept_check.hpp>

using std::cout;
using std::endl;

#include "viennagrid/forwards.hpp"

#include "viennagrid/storage/view.hpp"
#include "viennagrid/storage/container_collection.hpp"
#include "viennagrid/storage/inserter.hpp"
#include "viennagrid/storage/id_generator.hpp"
#include "viennagrid/storage/hidden_key_map.hpp"
#include "viennagrid/storage/range.hpp"

#include "viennagrid/topology/point.hpp"
#include "viennagrid/topology/line.hpp"
#include "viennagrid/topology/simplex.hpp"
#include "viennagrid/topology/plc.hpp"

#include "viennagrid/element/element_config.hpp"
#include "viennagrid/element/element_key.hpp"
#include "viennagrid/element/element_orientation.hpp"
#include "viennagrid/element/element_view.hpp"

#include "viennagrid/point.hpp"

#include "viennagrid/config/generic_config.hpp"

#include "viennagrid/domain/topologic_domain.hpp"
#include "viennagrid/domain/metainfo.hpp"
#include "viennagrid/domain/geometric_domain.hpp"
#include "viennagrid/domain/config.hpp"
#include "viennagrid/domain/element_creation.hpp"

int main()
{

    //
    // First define the type of hook to use:
    //

//     typedef viennagrid::storage::pointer_hook_tag hook_tag;
    //typedef viennagrid::storage::iterator_hook_tag hook_tag;
    typedef viennagrid::storage::id_hook_tag hook_tag;

    //
    // typedefing and setting up the topological domain
    //

    typedef viennagrid::result_of::geometric_domain_config<viennagrid::plc_tag, viennagrid::config::point_type_2d, viennagrid::storage::pointer_hook_tag>::type domain_config;

    //typedef viennagrid::config::polygonal_2d_domain domain_type;
    typedef viennagrid::result_of::geometric_domain< domain_config >::type domain_type;
    domain_type domain;

    //
    // typedefs for the element types
    //

    typedef viennagrid::result_of::point_type<domain_type>::type point_type;

    typedef viennagrid::result_of::element<domain_type, viennagrid::vertex_tag>::type vertex_type;
    typedef viennagrid::result_of::element_hook<domain_type, viennagrid::vertex_tag>::type vertex_hook_type;

    typedef viennagrid::result_of::element<domain_type, viennagrid::line_tag>::type line_type;
    typedef viennagrid::result_of::element_hook<domain_type, viennagrid::line_tag>::type line_hook_type;

    typedef viennagrid::result_of::element<domain_type, viennagrid::polygon_tag>::type polygon_type;
    typedef viennagrid::result_of::element_hook<domain_type, viennagrid::polygon_tag>::type polygon_hook_type;

    std::vector<vertex_hook_type> v;

    v.push_back( viennagrid::create_element<vertex_type>( domain, point_type(0, 0) ) );
    v.push_back( viennagrid::create_element<vertex_type>( domain, point_type(10, 0) ) );
    v.push_back( viennagrid::create_element<vertex_type>( domain, point_type(20, 10) ) );
    v.push_back( viennagrid::create_element<vertex_type>( domain, point_type(20, 20) ) );
    v.push_back( viennagrid::create_element<vertex_type>( domain, point_type(10, 20) ) );
    v.push_back( viennagrid::create_element<vertex_type>( domain, point_type(0, 10) ) );
    v.push_back( viennagrid::create_element<vertex_type>( domain, point_type(5, 5) ) );

    v.push_back( viennagrid::create_element<vertex_type>( domain, point_type(10, 10) ) );
    v.push_back( viennagrid::create_element<vertex_type>( domain, point_type(12, 10) ) );
    v.push_back( viennagrid::create_element<vertex_type>( domain, point_type(10, 12) ) );

    v.push_back( viennagrid::create_element<vertex_type>( domain, point_type(8, 10) ) );

    v.push_back( viennagrid::create_element<vertex_type>( domain, point_type(15, 15) ) );

    polygon_hook_type bounding_poly = viennagrid::create_element<polygon_type>( domain, v.begin(), v.begin() + 7 );

    polygon_hook_type hole_poly = viennagrid::create_element<polygon_type>( domain, v.begin() + 7, v.begin() + 10 );

    line_hook_type line = viennagrid::create_element<line_type>( domain, v.begin() + 9, v.begin() + 11 );

    vertex_hook_type point = v[11];

    std::cout << bounding_poly << std::endl;
    std::cout << viennagrid::dereference_hook(domain, bounding_poly) << std::endl;
    std::cout << hole_poly << std::endl;
    std::cout << viennagrid::dereference_hook(domain, hole_poly) << std::endl;

    typedef viennagrid::result_of::element<domain_type, viennagrid::plc_tag>::type plc_type;
    typedef viennagrid::result_of::element_hook<domain_type, viennagrid::plc_tag>::type plc_hook_type;

    plc_hook_type plc_hook = viennagrid::create_element<plc_type>(  domain,
                                                                    &bounding_poly, &bounding_poly + 1,
                                                                    &hole_poly, &hole_poly + 1,
                                                                    &line, &line + 1,
                                                                    &point, &point + 1 );

    plc_type & plc = viennagrid::dereference_hook(domain, plc_hook);

    //std::cout << plc.get_bounding_polygon() << std::endl;

    typedef viennagrid::result_of::element_range<plc_type, vertex_type>::type vertex_on_plc_range;
    typedef viennagrid::result_of::iterator<vertex_on_plc_range>::type vertex_on_plc_iterator;

    viennagrid::tagging::result_of::element_tag<plc_type, viennagrid::loose_tag>::type loose_tag = viennagrid::tagging::create_element_tag<viennagrid::loose_tag>(plc);

    std::cout << "All vertices of the PLC" << std::endl;
    vertex_on_plc_range vertex_range = viennagrid::elements<vertex_type>( plc );
    for (vertex_on_plc_iterator it = vertex_range.begin(); it != vertex_range.end(); ++it)
        std::cout << *it << " " << viennagrid::point(domain, *it) << " is loose: " << viennagrid::tagging::is_tagged(*it, loose_tag) << std::endl;
    std::cout << std::endl;

    typedef viennagrid::result_of::element_range<plc_type, line_type>::type line_on_plc_range;
    typedef viennagrid::result_of::iterator<line_on_plc_range>::type line_on_plc_iterator;

    std::cout << "All lines of the PLC" << std::endl;
    line_on_plc_range line_range = viennagrid::elements<line_type>( plc );
    for (line_on_plc_iterator it = line_range.begin(); it != line_range.end(); ++it)
        std::cout << *it << " is loose: " << viennagrid::tagging::is_tagged(*it, loose_tag) << std::endl;
    std::cout << std::endl;

    std::cout << "All PLCs of the domain" << std::endl;
    typedef viennagrid::result_of::element_range< domain_type, plc_type >::type plc_range_type;
    plc_range_type plc_range = viennagrid::elements< plc_type >(domain);
    for ( plc_range_type::iterator it = plc_range.begin(); it != plc_range.end(); ++it)
        std::cout << *it << std::endl;
    std::cout << std::endl;

    //std::copy( plc_range.begin(), plc_range.end(), std::ostream_iteratr<plc_type>( std::cout, "\n" ) );

    typedef viennagrid::result_of::const_element_view<plc_type, vertex_type>::type vertex_view_type;
    typedef viennagrid::result_of::iterator<vertex_view_type>::type vertex_view_iterator;

    std::cout << "All loose points of the plc" << std::endl;
    vertex_view_type vertex_view = viennagrid::loose_elements<vertex_type>(plc); // viennagrid::element_view<vertex_type>( plc, viennagrid::loose_predicate<plc_type>(plc) );
    for (vertex_view_iterator it = vertex_view.begin(); it != vertex_view.end(); ++it)
        std::cout << *it << std::endl;
    std::cout << std::endl;

    typedef viennagrid::result_of::element_view<plc_type, polygon_type>::type polygon_view_type;

    std::cout << "All hole polygons of the plc" << std::endl;
    polygon_view_type hole_polygons = viennagrid::hole_elements<polygon_type>(plc);
    std::copy( hole_polygons.begin(), hole_polygons.end(), std::ostream_iterator<polygon_type>(std::cout, "\n") );

    std::cout << "All bounding polygons of the plc" << std::endl;
    polygon_view_type bounding_polygons = viennagrid::bounding_elements<polygon_type>(plc);
    std::copy( bounding_polygons.begin(), bounding_polygons.end(), std::ostream_iterator<polygon_type>(std::cout, "\n") );

    typedef viennagrid::result_of::element_view<plc_type, line_type>::type line_view_type;

    std::cout << "All inner lines of the plc" << std::endl;
    viennagrid::tagging::result_of::element_tag<plc_type, viennagrid::bounding_tag>::type bounding_tag = viennagrid::tagging::create_element_tag<viennagrid::bounding_tag>(plc);
    line_view_type inner_lines = viennagrid::untagged_elements<line_type>(plc, bounding_tag);
    std::copy( inner_lines.begin(), inner_lines.end(), std::ostream_iterator<line_type>(std::cout, "\n") );

//     std::cout << std::endl << std::endl;
//     std::copy( viennagrid::elements<viennagrid::polygon_tag>(domain).begin(), viennagrid::elements<viennagrid::polygon_tag>(domain).end(), std::ostream_iterator<polygon_type>(std::cout, "\n") );
//
//     std::cout << std::endl << std::endl;
//     std::copy( viennagrid::elements<viennagrid::hole_polygon_tag>(domain).begin(), viennagrid::elements<viennagrid::hole_polygon_tag>(domain).end(), std::ostream_iterator<hole_polygon_type>(std::cout, "\n") );
//
//     std::cout << std::endl << std::endl;
//     std::copy( viennagrid::elements<viennagrid::hole_polygon_tag>(plc).begin(), viennagrid::elements<viennagrid::hole_polygon_tag>(plc).end(), std::ostream_iterator<hole_polygon_type>(std::cout, "\n") );

    return 0;
}
<|endoftext|>


<commit_before>// Thanks to James Remillard
//
#include <kdtree++/kdtree.hpp>
#include <vector>
#include <map>
#include <set>

using namespace std;

struct kdtreeNode
{
 typedef double value_type;

 double xyz[3];
 size_t index;

 value_type operator[](size_t n) const
 {
   return xyz[n];
 }

 double distance( const kdtreeNode &node)
 {
   double x = xyz[0] - node.xyz[0];
   double y = xyz[1] - node.xyz[1];
   double z = xyz[2] - node.xyz[2];

// this is not correct   return sqrt( x*x+y*y+z*z);

// this is what kdtree checks with find_within_range()
// the "manhattan distance" from the search point.
// effectively, distance is the maximum distance in any one dimension.
   return max(fabs(x),max(fabs(y),fabs(z)));

 }
};

int main(int argc,char *argv[])
{
 vector<kdtreeNode> pts;

 typedef KDTree::KDTree<3,kdtreeNode> treeType;

 treeType tree;

 // make random 3d points
 for ( size_t n = 0; n < 10000; ++n)
 {
   kdtreeNode node;
   node.xyz[0] = double(rand())/RAND_MAX;
   node.xyz[1] = double(rand())/RAND_MAX;
   node.xyz[2] = double(rand())/RAND_MAX;
   node.index = n;

   tree.insert( node);
   pts.push_back( node);
 }

 for (size_t r = 0; r < 1000; ++r)
 {
   kdtreeNode refNode;
   refNode.xyz[0] = double(rand())/RAND_MAX;
   refNode.xyz[1] = double(rand())/RAND_MAX;
   refNode.xyz[2] = double(rand())/RAND_MAX;

   double limit = double(rand())/RAND_MAX;

   // find the correct return list by checking every single point
   set<size_t> correctCloseList;

   for ( size_t i= 0; i < pts.size(); ++i)
   {
     double dist = refNode.distance( pts[i]);
     if ( dist < limit)
       correctCloseList.insert( i );
   }

   // now do the same with the kdtree.
   vector<kdtreeNode> howClose;
   tree.find_within_range(refNode,limit,back_insert_iterator<vector<kdtreeNode> >(howClose));

   // make sure no extra points are returned, and the return has no missing points.
   for ( size_t i = 0; i < howClose.size(); ++i)
   {
     set<size_t>::iterator hit = correctCloseList.find( howClose[i].index);

     if ( hit != correctCloseList.end())
     {
       correctCloseList.erase(hit);
     }
     else
     {
       // point that is too far away - fail!
       assert(false);
       printf("fail, extra points.\n");
     }
   }

   // fail, not all of the close enough points returned.
   assert( correctCloseList.size() == 0);
   if ( correctCloseList.size() > 0)
   {
     printf("fail, missing points.\n");
   }
 }
}

<commit_msg>Added #include<cstdio> to test_find_winthin_range.cpp so that it compiles with g++-4.5<commit_after>// Thanks to James Remillard
//
#include <cstdio>
#include <kdtree++/kdtree.hpp>
#include <vector>
#include <map>
#include <set>

using namespace std;

struct kdtreeNode
{
 typedef double value_type;

 double xyz[3];
 size_t index;

 value_type operator[](size_t n) const
 {
   return xyz[n];
 }

 double distance( const kdtreeNode &node)
 {
   double x = xyz[0] - node.xyz[0];
   double y = xyz[1] - node.xyz[1];
   double z = xyz[2] - node.xyz[2];

// this is not correct   return sqrt( x*x+y*y+z*z);

// this is what kdtree checks with find_within_range()
// the "manhattan distance" from the search point.
// effectively, distance is the maximum distance in any one dimension.
   return max(fabs(x),max(fabs(y),fabs(z)));

 }
};

int main(int argc,char *argv[])
{
 vector<kdtreeNode> pts;

 typedef KDTree::KDTree<3,kdtreeNode> treeType;

 treeType tree;

 // make random 3d points
 for ( size_t n = 0; n < 10000; ++n)
 {
   kdtreeNode node;
   node.xyz[0] = double(rand())/RAND_MAX;
   node.xyz[1] = double(rand())/RAND_MAX;
   node.xyz[2] = double(rand())/RAND_MAX;
   node.index = n;

   tree.insert( node);
   pts.push_back( node);
 }

 for (size_t r = 0; r < 1000; ++r)
 {
   kdtreeNode refNode;
   refNode.xyz[0] = double(rand())/RAND_MAX;
   refNode.xyz[1] = double(rand())/RAND_MAX;
   refNode.xyz[2] = double(rand())/RAND_MAX;

   double limit = double(rand())/RAND_MAX;

   // find the correct return list by checking every single point
   set<size_t> correctCloseList;

   for ( size_t i= 0; i < pts.size(); ++i)
   {
     double dist = refNode.distance( pts[i]);
     if ( dist < limit)
       correctCloseList.insert( i );
   }

   // now do the same with the kdtree.
   vector<kdtreeNode> howClose;
   tree.find_within_range(refNode,limit,back_insert_iterator<vector<kdtreeNode> >(howClose));

   // make sure no extra points are returned, and the return has no missing points.
   for ( size_t i = 0; i < howClose.size(); ++i)
   {
     set<size_t>::iterator hit = correctCloseList.find( howClose[i].index);

     if ( hit != correctCloseList.end())
     {
       correctCloseList.erase(hit);
     }
     else
     {
       // point that is too far away - fail!
       assert(false);
       printf("fail, extra points.\n");
     }
   }

   // fail, not all of the close enough points returned.
   assert( correctCloseList.size() == 0);
   if ( correctCloseList.size() > 0)
   {
     printf("fail, missing points.\n");
   }
 }
}

<|endoftext|>


<commit_before>#include <strex.hpp>

#include "context.hpp"

namespace postgres {
    std::string to_type(const db::column_value_type &c) {
        using namespace std;
        string type_name;

        switch (strex::hash(c.type_name)) {
        case strex::hash("int"):
            type_name = "INTEGER";
            break;
        case strex::hash("int32"):
            type_name = "INTEGER";
            break;
        case strex::hash("int64"):
            type_name = "BIGINT";
            break;
        case strex::hash("str"):
            type_name = "TEXT";
            break;
        case strex::hash("text"):
            type_name = "TEXT";
            break;
        case strex::hash("bool"):
            type_name = "BOOLEAN";
            break;
        case strex::hash("buffer"):
            type_name = "bytea";
            break;
        case strex::hash("timestamp"):
            type_name = "timestamp";
            break;
        case strex::hash("serial"):
            type_name = "SERIAL";
            break;
        case strex::hash("decimal"):
            type_name = "DECIMAL(12, 2)";
            break;
        }

        if (c.unique_key)
            type_name += " UNIQUE";
        if (c.not_null)
            type_name += " NOT NULL";
        if (!c.default_value.empty())
            type_name += " DEFAULT " + c.default_value;

        return type_name;
    }

    db::column_value_type from_type(const std::string &t, const std::string def, const bool _primary_key, const bool _unique_key, const bool _not_null) {
        const auto def_value = _primary_key ? std::string{} : def;

        if (t == "integer")
            return db::column_value_type{"int", def_value, _primary_key, _unique_key, _not_null};

        if (t == "text")
            return db::column_value_type{"text", def_value, _primary_key, _unique_key, _not_null};

        if (t == "bytea")
            return db::column_value_type{"buffer", def_value, _primary_key, _unique_key, _not_null};

        if (t == "numeric")
            return db::column_value_type{"decimal", def_value, _primary_key, _unique_key, _not_null};

        if (t == "boolean")
            return db::column_value_type{"bool", def_value, _primary_key, _unique_key, _not_null};

        return db::column_value_type{t, def_value, _primary_key, _unique_key, _not_null};
    }
}
<commit_msg>Fix postgres unknown type<commit_after>#include <strex.hpp>

#include "context.hpp"

namespace postgres {
    std::string to_type(const db::column_value_type &c) {
        using namespace std;
        string type_name = c.type_name;

        switch (strex::hash(type_name)) {
        case strex::hash("int"):
            type_name = "INTEGER";
            break;
        case strex::hash("int32"):
            type_name = "INTEGER";
            break;
        case strex::hash("int64"):
            type_name = "BIGINT";
            break;
        case strex::hash("str"):
            type_name = "TEXT";
            break;
        case strex::hash("text"):
            type_name = "TEXT";
            break;
        case strex::hash("bool"):
            type_name = "BOOLEAN";
            break;
        case strex::hash("buffer"):
            type_name = "bytea";
            break;
        case strex::hash("timestamp"):
            type_name = "timestamp";
            break;
        case strex::hash("serial"):
            type_name = "SERIAL";
            break;
        case strex::hash("decimal"):
            type_name = "DECIMAL(12, 2)";
            break;
        }

        if (c.unique_key)
            type_name += " UNIQUE";
        if (c.not_null)
            type_name += " NOT NULL";
        if (!c.default_value.empty())
            type_name += " DEFAULT " + c.default_value;

        return type_name;
    }

    db::column_value_type from_type(const std::string &t, const std::string def, const bool _primary_key, const bool _unique_key, const bool _not_null) {
        const auto def_value = _primary_key ? std::string{} : def;

        if (t == "integer")
            return db::column_value_type{"int", def_value, _primary_key, _unique_key, _not_null};

        if (t == "text")
            return db::column_value_type{"text", def_value, _primary_key, _unique_key, _not_null};

        if (t == "bytea")
            return db::column_value_type{"buffer", def_value, _primary_key, _unique_key, _not_null};

        if (t == "numeric")
            return db::column_value_type{"decimal", def_value, _primary_key, _unique_key, _not_null};

        if (t == "boolean")
            return db::column_value_type{"bool", def_value, _primary_key, _unique_key, _not_null};

        return db::column_value_type{t, def_value, _primary_key, _unique_key, _not_null};
    }
}
<|endoftext|>