text:
//
// Copyright © 2017 Arm Ltd. All rights reserved.
// See LICENSE file in the project root for full license information.
//

#include "LayerSupportCommon.hpp"
#include "RefLayerSupport.hpp"
#include <armnn/Descriptors.hpp>
#include <armnn/Types.hpp>
#include <armnn/Tensor.hpp>

#include <boost/core/ignore_unused.hpp>
#include "InternalTypes.hpp"

using namespace boost;

namespace armnn
{

template<typename Float32Func, typename Uint8Func, typename ... Params>
bool IsSupportedForDataTypeRef(std::string* reasonIfUnsupported,
                               DataType dataType,
                               Float32Func floatFuncPtr,
                               Uint8Func uint8FuncPtr,
                               Params&&... params)
{
    return IsSupportedForDataTypeGeneric(reasonIfUnsupported,
                                         dataType,
                                         &FalseFunc<Params...>,
                                         floatFuncPtr,
                                         uint8FuncPtr,
                                         std::forward<Params>(params)...);
}

bool IsActivationSupportedRef(const TensorInfo& input,
                              const TensorInfo& output,
                              const ActivationDescriptor& descriptor,
                              std::string* reasonIfUnsupported)
{
    ignore_unused(output);
    ignore_unused(descriptor);
    return IsSupportedForDataTypeRef(reasonIfUnsupported,
                                     input.GetDataType(),
                                     &TrueFunc<>,
                                     &TrueFunc<>);
}

bool IsAdditionSupportedRef(const TensorInfo& input0,
                            const TensorInfo& input1,
                            const TensorInfo& output,
                            std::string* reasonIfUnsupported)
{
    ignore_unused(input1);
    ignore_unused(output);
    return IsSupportedForDataTypeRef(reasonIfUnsupported,
                                     input0.GetDataType(),
                                     &TrueFunc<>,
                                     &TrueFunc<>);
}

bool IsBatchNormalizationSupportedRef(const TensorInfo& input,
                                      const TensorInfo& output,
                                      const TensorInfo& mean,
                                      const TensorInfo& var,
                                      const TensorInfo& beta,
                                      const TensorInfo& gamma,
                                      const BatchNormalizationDescriptor& descriptor,
                                      std::string* reasonIfUnsupported)
{
    ignore_unused(descriptor);
    return IsSupportedForDataTypeRef(reasonIfUnsupported,
                                     input.GetDataType(),
                                     &TrueFunc<>,
                                     &TrueFunc<>);
}

bool IsConstantSupportedRef(const TensorInfo& output,
                            std::string* reasonIfUnsupported)
{
    return IsSupportedForDataTypeRef(reasonIfUnsupported,
                                     output.GetDataType(),
                                     &TrueFunc<>,
                                     &TrueFunc<>);
}

bool IsConvolution2dSupportedRef(const TensorInfo& input,
                                 const TensorInfo& output,
                                 const Convolution2dDescriptor& descriptor,
                                 const TensorInfo& weights,
                                 const TensorInfo& biases,
                                 std::string* reasonIfUnsupported)
{
    ignore_unused(descriptor);
    ignore_unused(output);
    ignore_unused(weights);
    ignore_unused(biases);
    return IsSupportedForDataTypeRef(reasonIfUnsupported,
                                     input.GetDataType(),
                                     &TrueFunc<>,
                                     &TrueFunc<>);
}

bool IsDepthwiseConvolutionSupportedRef(const TensorInfo& input,
                                        const TensorInfo& output,
                                        const DepthwiseConvolution2dDescriptor& descriptor,
                                        const TensorInfo& weights,
                                        const TensorInfo& biases,
                                        std::string* reasonIfUnsupported)
{
    ignore_unused(output);
    ignore_unused(descriptor);
    ignore_unused(weights);
    ignore_unused(biases);
    return IsSupportedForDataTypeRef(reasonIfUnsupported,
                                     input.GetDataType(),
                                     &TrueFunc<>,
                                     &TrueFunc<>);
}

bool IsFullyConnectedSupportedRef(const TensorInfo& input,
                                  const TensorInfo& output,
                                  const TensorInfo& weights,
                                  const TensorInfo& biases,
                                  const FullyConnectedDescriptor& descriptor,
                                  std::string* reasonIfUnsupported)
{
    ignore_unused(output);
    ignore_unused(descriptor);
    ignore_unused(weights);
    ignore_unused(biases);
    return IsSupportedForDataTypeRef(reasonIfUnsupported,
                                     input.GetDataType(),
                                     &TrueFunc<>,
                                     &TrueFunc<>);
}

bool IsInputSupportedRef(const TensorInfo& input,
                         std::string* reasonIfUnsupported)
{
    return IsSupportedForDataTypeRef(reasonIfUnsupported,
                                     input.GetDataType(),
                                     &TrueFunc<>,
                                     &TrueFunc<>);
}

bool IsL2NormalizationSupportedRef(const TensorInfo& input,
                                   const TensorInfo& output,
                                   std::string* reasonIfUnsupported)
{
    ignore_unused(output);
    return IsSupportedForDataTypeRef(reasonIfUnsupported,
                                     input.GetDataType(),
                                     &TrueFunc<>,
                                     &FalseFuncU8<>);
}

bool IsMergerSupportedRef(const std::vector<const TensorInfo*> inputs,
                          const OriginsDescriptor& descriptor,
                          std::string* reasonIfUnsupported)
{
    ignore_unused(descriptor);
    return IsSupportedForDataTypeRef(reasonIfUnsupported,
                                     inputs[0]->GetDataType(),
                                     &TrueFunc<>,
                                     &TrueFunc<>);
}

bool IsMultiplicationSupportedRef(const TensorInfo& input0,
                                  const TensorInfo& input1,
                                  const TensorInfo& output,
                                  std::string* reasonIfUnsupported)
{
    ignore_unused(input1);
    ignore_unused(output);
    return IsSupportedForDataTypeRef(reasonIfUnsupported,
                                     input0.GetDataType(),
                                     &TrueFunc<>,
                                     &TrueFunc<>);
}

bool IsNormalizationSupportedRef(const TensorInfo& input,
                                 const TensorInfo& output,
                                 const NormalizationDescriptor& descriptor,
                                 std::string* reasonIfUnsupported)
{
    ignore_unused(descriptor);
    return IsSupportedForDataTypeRef(reasonIfUnsupported,
                                     input.GetDataType(),
                                     &TrueFunc<>,
                                     &FalseFuncU8<>);
}

bool IsOutputSupportedRef(const TensorInfo& output,
                          std::string* reasonIfUnsupported)
{
    return IsSupportedForDataTypeRef(reasonIfUnsupported,
                                     output.GetDataType(),
                                     &TrueFunc<>,
                                     &TrueFunc<>);
}

bool IsPermuteSupportedRef(const TensorInfo& input,
                           const TensorInfo& output,
                           const PermuteDescriptor& descriptor,
                           std::string* reasonIfUnsupported)
{
    ignore_unused(descriptor);
    return IsSupportedForDataTypeRef(reasonIfUnsupported,
                                     input.GetDataType(),
                                     &TrueFunc<>,
                                     &TrueFunc<>);
}

bool IsPooling2dSupportedRef(const TensorInfo& input,
                             const TensorInfo& output,
                             const Pooling2dDescriptor& descriptor,
                             std::string* reasonIfUnsupported)
{
    ignore_unused(descriptor);
    return IsSupportedForDataTypeRef(reasonIfUnsupported,
                                     input.GetDataType(),
                                     &TrueFunc<>,
                                     &TrueFunc<>);
}

bool IsResizeBilinearSupportedRef(const TensorInfo& input,
                                  std::string* reasonIfUnsupported)
{
    return IsSupportedForDataTypeRef(reasonIfUnsupported,
                                     input.GetDataType(),
                                     &TrueFunc<>,
                                     &TrueFunc<>);
}

bool IsSoftmaxSupportedRef(const TensorInfo& input,
                           const TensorInfo& output,
                           const SoftmaxDescriptor& descriptor,
                           std::string* reasonIfUnsupported)
{
    ignore_unused(output);
    ignore_unused(descriptor);
    return IsSupportedForDataTypeRef(reasonIfUnsupported,
                                     input.GetDataType(),
                                     &TrueFunc<>,
                                     &TrueFunc<>);
}

bool IsSplitterSupportedRef(const TensorInfo& input,
                            const ViewsDescriptor& descriptor,
                            std::string* reasonIfUnsupported)
{
    ignore_unused(descriptor);
    return IsSupportedForDataTypeRef(reasonIfUnsupported,
                                     input.GetDataType(),
                                     &TrueFunc<>,
                                     &TrueFunc<>);
}

bool IsFakeQuantizationSupportedRef(const TensorInfo& input,
                                    const FakeQuantizationDescriptor& descriptor,
                                    std::string* reasonIfUnsupported)
{
    ignore_unused(descriptor);
    return IsSupportedForDataTypeRef(reasonIfUnsupported,
                                     input.GetDataType(),
                                     &TrueFunc<>,
                                     &FalseFuncU8<>);
}

bool IsReshapeSupportedRef(const TensorInfo& input,
                           std::string* reasonIfUnsupported)
{
    return IsSupportedForDataTypeRef(reasonIfUnsupported,
                                     input.GetDataType(),
                                     &TrueFunc<>,
                                     &TrueFunc<>);
}

bool IsFloorSupportedRef(const TensorInfo& input,
                         const TensorInfo& output,
                         std::string* reasonIfUnsupported)
{
    ignore_unused(output);
    return IsSupportedForDataTypeRef(reasonIfUnsupported,
                                     input.GetDataType(),
                                     &TrueFunc<>,
                                     &FalseFuncU8<>);
}

bool IsLstmSupportedRef(const TensorInfo& input, const TensorInfo& outputStateIn,
                        const TensorInfo& cellStateIn, const TensorInfo& scratchBuffer,
                        const TensorInfo& outputStateOut, const TensorInfo& cellStateOut,
                        const TensorInfo& output, const LstmDescriptor& descriptor,
                        const TensorInfo& inputToForgetWeights, const TensorInfo& inputToCellWeights,
                        const TensorInfo& inputToOutputWeights, const TensorInfo& recurrentToForgetWeights,
                        const TensorInfo& recurrentToCellWeights, const TensorInfo& recurrentToOutputWeights,
                        const TensorInfo& forgetGateBias, const TensorInfo& cellBias,
                        const TensorInfo& outputGateBias, const TensorInfo* inputToInputWeights,
                        const TensorInfo* recurrentToInputWeights, const TensorInfo* cellToInputWeights,
                        const TensorInfo* inputGateBias, const TensorInfo* projectionWeights,
                        const TensorInfo* projectionBias, const TensorInfo* cellToForgetWeights,
                        const TensorInfo* cellToOutputWeights, std::string* reasonIfUnsupported)
{
    ignore_unused(input);
    ignore_unused(outputStateIn);
    ignore_unused(cellStateIn);
    ignore_unused(scratchBuffer);
    ignore_unused(outputStateOut);
    ignore_unused(cellStateOut);
    ignore_unused(output);
    ignore_unused(descriptor);
    ignore_unused(inputToForgetWeights);
    ignore_unused(inputToCellWeights);
    ignore_unused(inputToOutputWeights);
    ignore_unused(recurrentToForgetWeights);
    ignore_unused(recurrentToCellWeights);
    ignore_unused(recurrentToOutputWeights);
    ignore_unused(forgetGateBias);
    ignore_unused(cellBias);
    ignore_unused(outputGateBias);
    ignore_unused(inputToInputWeights);
    ignore_unused(recurrentToInputWeights);
    ignore_unused(cellToInputWeights);
    ignore_unused(inputGateBias);
    ignore_unused(projectionWeights);
    ignore_unused(projectionBias);
    ignore_unused(cellToForgetWeights);
    ignore_unused(cellToOutputWeights);
    return false;
}

bool IsConvertFp16ToFp32SupportedRef(const TensorInfo& input,
                                     const TensorInfo& output,
                                     std::string* reasonIfUnsupported)
{
    return (IsSupportedForDataTypeGeneric(reasonIfUnsupported,
                                          input.GetDataType(),
                                          &TrueFunc<>,
                                          &FalseInputFuncF32<>,
                                          &FalseFuncU8<>) &&
            IsSupportedForDataTypeGeneric(reasonIfUnsupported,
                                          output.GetDataType(),
                                          &FalseOutputFuncF16<>,
                                          &TrueFunc<>,
                                          &FalseFuncU8<>));
}

bool IsConvertFp32ToFp16SupportedRef(const TensorInfo& input,
                                     const TensorInfo& output,
                                     std::string* reasonIfUnsupported)
{
    return (IsSupportedForDataTypeGeneric(reasonIfUnsupported,
                                          input.GetDataType(),
                                          &FalseInputFuncF16<>,
                                          &TrueFunc<>,
                                          &FalseFuncU8<>) &&
            IsSupportedForDataTypeGeneric(reasonIfUnsupported,
                                          output.GetDataType(),
                                          &TrueFunc<>,
                                          &FalseOutputFuncF32<>,
                                          &FalseFuncU8<>));
}

}


text:
#include <iostream>
//
#include <polyvec/api.hpp>
#include <polyvec/core/log.hpp>
#include <polyvec/misc.hpp>
#include <polyvec/io/vtk_curve_writer.hpp>
//
#include <dev/pdf.hpp>
//
#include <polyvec/mc/get_bounding_box.hpp>
#include <polyvec/mc/get_pixel_regions.hpp>
#include <polyvec/mc/junction.hpp>
#include <polyvec/mc/random_color.hpp>
#include <polyvec/mc/raster_image_connectivity.hpp>
//
#include <Eigen/Core>
#include <Eigen/Geometry>

NAMESPACE_BEGIN()
void draw_raster_closed(const Eigen::Matrix2Xd& raster,
                        const Eigen::Vector4d& color) {
  ::polyvec::vec<::polyvec::real2> points;
  for (int i = 0; i < raster.cols(); ++i) {
    points.emplace_back(raster.col(i));
  }

  ::polyvec::draw::polygon(points, ::polyvec::Style::fill(color.head<3>()));
}  // end of draw_raster_closed()
NAMESPACE_END()

NAMESPACE_BEGIN(polyvectest)
NAMESPACE_BEGIN(mc)

int junctions(int, char**) {
  std::vector<std::string> image_addrs;
  image_addrs.emplace_back(POLYVEC_TEST_PATH "/mc/abc.png");
  image_addrs.emplace_back(POLYVEC_TEST_PATH "/mc/holes001.png");
  // image_addrs.emplace_back(POLYVEC_TEST_PATH "/mc/chess.png");

  printf("==== Testing raster image connectivity \n");

  polyfit::Log::open("test_dump/log-export-multicolor-traces.txt");

  for (int i = 0; i < (int)image_addrs.size(); ++i) {
    std::vector<Eigen::Matrix2Xi> boundaries;
    std::vector<Eigen::Vector4d> colors;
    polyfit::mc::get_pixel_regions_from_bmp(image_addrs[i], boundaries, colors);

    // Get the bounding box of the whole picture
    Eigen::AlignedBox<int, 2> bbox = polyfit::mc::get_bounding_box(boundaries);

    // Can you build a connectivity
    polyfit::mc::RasterImageConnectivity raster_conn =
        polyfit::mc::RasterImageConnectivity::build(boundaries);
    const bool is_mesh_okay =
        raster_conn.connectivity().check_sanity_slowly(true);
    printf("Mesh okay status: %d \n", (int)is_mesh_okay);

    std::unique_ptr<::polyvec::DevicePDF> pdf;

    //
    // Draw the image by random colors
    //
    pdf.reset(new ::polyvec::DevicePDF(
        ::polyvec::misc::sfmt("test_dump/junctions%02d_%04d.pdf", i, 0).c_str(),
        1, 1));
    //
    std::vector<int> by_area = raster_conn.regions_sorted_by_area();
    //
    for (int j = 0; j < (int)raster_conn.n_regions(); ++j) {
      const int region_id = by_area[j];
      std::vector<int> holes;
      int outer_boundary;
      raster_conn.region_to_polygon(region_id, outer_boundary, holes);
      assert_break(outer_boundary == region_id);

      draw_raster_closed(
          raster_conn.get_polygon_points(outer_boundary).cast<double>(),
          j == 0 ? Eigen::Vector4d(1, 1, 1, 1) : ::polyfit::mc::random_color());

      for (int h : holes) {
        Eigen::Matrix2Xi bdry = raster_conn.get_polygon_points(h);
        bdry.rowwise().reverseInPlace();
        draw_raster_closed(bdry.cast<double>(), Eigen::Vector4d(1, 1, 1, 1));
      }
    }  // end of regions
    // pdf->draw(0, 0);

    //
    // Now get the junction types and draw them
    //

    std::vector<polyfit::mc::JunctionType> junction_types;
    polyfit::mc::find_junctions(raster_conn, junction_types);

    // Draw the junctions
    for (int vid = 0; vid < raster_conn.n_pixel_vertices(); ++vid) {
      if (junction_types[vid] == ::polyfit::mc::JUNCTION_INVALID) {
        continue;
      }

      // Now draw
      Eigen::Vector2i pos = raster_conn.pixel_vertex_index_to_pos(vid);
      auto __draw = [&](const std::string& ss) {
        ::polyvec::draw::text(pos.cast<double>(), ss.c_str(),
                              ::polyvec::draw::font_pdf,
                              ::polyvec::Style::fill(::polyvec::colors::black));
      };

      switch (junction_types[vid]) {
        case polyfit::mc::JUNCTION_3_SHARP:
          __draw("3");
          break;
        case polyfit::mc::JUNCTION_4_SHARP:
          __draw("4");
          break;
        case polyfit::mc::JUNCTION_KOPF:
          __draw("K");
          break;
        default:;
      }
    }  // end of vertices
    pdf->draw(0, 0);
  }  // end of images

  return EXIT_FAILURE;
}

NAMESPACE_END(mc)
NAMESPACE_END(polyvectest)

ext: cpp

max_stars_repo_name: ShnitzelKiller/polyfit

max_issues_repo_name: ShnitzelKiller/polyfit

max_forks_repo_name: ShnitzelKiller/polyfit


text:
// Copyright 2020-2022 The Defold Foundation
// Copyright 2014-2020 King
// Copyright 2009-2014 Ragnar Svensson, Christian Murray
// Licensed under the Defold License version 1.0 (the "License"); you may not use
// this file except in compliance with the License.
//
// You may obtain a copy of the License, together with FAQs at
// https://www.defold.com/license
//
// Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.

#include "script_timer.h"
#include "script_timer_private.h"

#include <string.h>
#include <dlib/index_pool.h>
#include <dlib/hashtable.h>
#include <dlib/profile.h>

#include "script.h"
#include "script_private.h"

namespace dmScript
{
    /*# Timer API documentation
     *
     * Timers allow you to set a delay and a callback to be called when the timer completes.
     *
     * The timers created with this API are updated with the collection timer where they
     * are created. If you pause or speed up the collection (using `set_time_step`) it will
     * also affect the new timer.
     *
     * @document
     * @name Timer
     * @namespace timer
     */

    /*
        The timers are stored in a flat array with no holes which we scan sequenctially on each update.

        When a timer is removed the last timer in the list may change location (EraseSwap).

        This is to keep the array sweep fast and handle cases where multiple short lived timers are
        created followed by one long-lived timer. If we did not re-shuffle and keep holes we would keep
        scanning the array to the end where the only live timer exists skipping all the holes.
        How much of an issue this is guesswork at this point.

        The timer identity is an index into an indirection layer combined with a generation counter,
        this makes it possible to reuse the index for the indirection layer without risk of using
        stale indexes - the caller to CancelTimer is allowed to call with an handle of a timer that already
        has expired.

        Each script instance needs to call KillTimers for its owner to clean up potential timers
        that has not yet been cancelled or completed (one-shot).
    */

    static const char TIMER_WORLD_VALUE_KEY[] = "__dm_timer_world__";
    static const uint32_t TIMER_WORLD_VALUE_KEY_HASH = dmHashBuffer32(TIMER_WORLD_VALUE_KEY, sizeof(TIMER_WORLD_VALUE_KEY) - 1);

    struct Timer
    {
        TimerCallback   m_Callback;
        uintptr_t       m_Owner;
        uintptr_t       m_UserData;

        // Store complete timer handle with generation here to identify stale timer handles
        HTimer          m_Handle;

        // How much time remaining until the timer fires
        float           m_Remaining;

        // The timer delay, we need to keep this for repeating timers
        float           m_Delay;

        // Flag if the timer should repeat
        uint32_t        m_Repeat : 1;
        // Flag if the timer is alive
        uint32_t        m_IsAlive : 1;
    };

    #define INVALID_TIMER_LOOKUP_INDEX  0xffffu
    #define INITIAL_TIMER_CAPACITY      8u
    #define MAX_TIMER_CAPACITY          65000u  // Needs to be less that 65535 since 65535 is reserved for invalid index
    #define TIMER_CAPACITY_GROWTH       16u

    struct TimerWorld
    {
        dmArray<Timer>                      m_Timers;
        dmArray<uint16_t>                   m_IndexLookup;
        dmIndexPool<uint16_t>               m_IndexPool;
        uint16_t                            m_Version;   // Incremented to avoid collisions each time we push timer indexes back to the m_IndexPool
        uint16_t                            m_InUpdate : 1;
    };

    static uint16_t GetLookupIndex(HTimer handle)
    {
        return (uint16_t)(handle & 0xffffu);
    }

    static HTimer MakeHandle(uint16_t generation, uint16_t lookup_index)
    {
        return (((uint32_t)generation) << 16) | (lookup_index);
    }

    static Timer* AllocateTimer(HTimerWorld timer_world, uintptr_t owner)
    {
        assert(timer_world != 0x0);
        uint32_t timer_count = timer_world->m_Timers.Size();
        if (timer_count == MAX_TIMER_CAPACITY)
        {
            dmLogError("Timer could not be stored since the timer buffer is full (%d).", MAX_TIMER_CAPACITY);
            return 0x0;
        }

        if (timer_world->m_IndexPool.Remaining() == 0)
        {
            uint32_t old_capacity = timer_world->m_IndexPool.Capacity();
            uint32_t capacity = dmMath::Min(old_capacity + TIMER_CAPACITY_GROWTH, MAX_TIMER_CAPACITY);
            timer_world->m_IndexPool.SetCapacity(capacity);
            timer_world->m_IndexLookup.SetCapacity(capacity);
            timer_world->m_IndexLookup.SetSize(capacity);
            memset(&timer_world->m_IndexLookup[old_capacity], 0u, (capacity - old_capacity) * sizeof(uint16_t));
        }

        HTimer handle = MakeHandle(timer_world->m_Version, timer_world->m_IndexPool.Pop());

        if (timer_world->m_Timers.Full())
        {
            uint32_t capacity = timer_world->m_Timers.Capacity();
            capacity = dmMath::Min(capacity + TIMER_CAPACITY_GROWTH, MAX_TIMER_CAPACITY);
            timer_world->m_Timers.SetCapacity(capacity);
        }

        timer_world->m_Timers.SetSize(timer_count + 1);
        Timer& timer = timer_world->m_Timers[timer_count];
        timer.m_Handle = handle;
        timer.m_Owner = owner;

        uint16_t lookup_index = GetLookupIndex(handle);

        timer_world->m_IndexLookup[lookup_index] = timer_count;
        return &timer;
    }

    static void EraseTimer(HTimerWorld timer_world, uint32_t timer_index)
    {
        assert(timer_world != 0x0);

        Timer& movedTimer = timer_world->m_Timers.EraseSwap(timer_index);

        if (timer_index < timer_world->m_Timers.Size())
        {
            uint16_t moved_lookup_index = GetLookupIndex(movedTimer.m_Handle);
            timer_world->m_IndexLookup[moved_lookup_index] = timer_index;
        }
    }

    static void FreeTimer(HTimerWorld timer_world, Timer& timer)
    {
        assert(timer_world != 0x0);
        assert(timer.m_IsAlive == 0);

        uint16_t lookup_index = GetLookupIndex(timer.m_Handle);
        uint16_t timer_index = timer_world->m_IndexLookup[lookup_index];
        timer_world->m_IndexPool.Push(lookup_index);

        EraseTimer(timer_world, timer_index);
    }

    HTimerWorld NewTimerWorld()
    {
        TimerWorld* timer_world = new TimerWorld();
        timer_world->m_Timers.SetCapacity(INITIAL_TIMER_CAPACITY);
        timer_world->m_IndexLookup.SetCapacity(INITIAL_TIMER_CAPACITY);
        timer_world->m_IndexLookup.SetSize(INITIAL_TIMER_CAPACITY);
        memset(&timer_world->m_IndexLookup[0], 0u, INITIAL_TIMER_CAPACITY * sizeof(uint16_t));
        timer_world->m_IndexPool.SetCapacity(INITIAL_TIMER_CAPACITY);
        timer_world->m_Version = 0;
        timer_world->m_InUpdate = 0;
        return timer_world;
    }

    void DeleteTimerWorld(HTimerWorld timer_world)
    {
        assert(timer_world->m_InUpdate == 0);
        delete timer_world;
    }

    void UpdateTimers(HTimerWorld timer_world, float dt)
    {
        assert(timer_world != 0x0);
        DM_PROFILE(TimerWorld, "Update");

        timer_world->m_InUpdate = 1;

        // We only scan timers for trigger if the timer *existed at entry to UpdateTimers*, any timers added
        // in a trigger callback will always be added at the end of m_Timers and not triggered in this scope.
        uint32_t size = timer_world->m_Timers.Size();
        DM_COUNTER("timerc", size);

        for (uint32_t i = 0; i < size; ++i)
        {
            Timer* timer = &timer_world->m_Timers[i];
            if (timer->m_IsAlive == 0)
            {
                continue;
            }

            timer->m_Remaining -= dt;
            if (timer->m_Remaining > 0.0f)
            {
                continue;
            }

            float elapsed_time = timer->m_Delay - timer->m_Remaining;

            TimerEventType eventType = timer->m_Repeat == 0 ? TIMER_EVENT_TRIGGER_WILL_DIE : TIMER_EVENT_TRIGGER_WILL_REPEAT;

            timer->m_Callback(timer_world, eventType, timer->m_Handle, elapsed_time, timer->m_Owner, timer->m_UserData);

            // The array might have been reallocated here! So grab the pointer again...
            timer = &timer_world->m_Timers[i];

            if (timer->m_IsAlive == 0)
            {
                continue;
            }

            if (timer->m_Repeat == 0)
            {
                timer->m_IsAlive = 0;
                continue;
            }

            if (timer->m_Delay == 0.0f)
            {
                timer->m_Remaining = 0.0f;
                continue;
            }

            float wrapped_count = ((-timer->m_Remaining) / timer->m_Delay) + 1.f;
            float offset_to_next_trigger  = floor(wrapped_count) * timer->m_Delay;
            timer->m_Remaining += offset_to_next_trigger;
            assert(timer->m_Remaining >= 0.f);
        }

        timer_world->m_InUpdate = 0;

        size = timer_world->m_Timers.Size();
        uint32_t original_size = size;
        uint32_t i = 0;
        while (i < size)
        {
            Timer& timer = timer_world->m_Timers[i];
            if (timer.m_IsAlive == 0)
            {
                FreeTimer(timer_world, timer);
                --size;
            }
            else
            {
                ++i;
            }
        }

        if (size != original_size)
        {
            ++timer_world->m_Version;
        }
    }

    HTimer AddTimer(HTimerWorld timer_world,
                    float delay,
                    bool repeat,
                    TimerCallback timer_callback,
                    uintptr_t owner,
                    uintptr_t userdata)
    {
        assert(timer_world != 0x0);
        assert(delay >= 0.f);
        assert(timer_callback != 0x0);
        Timer* timer = AllocateTimer(timer_world, owner);
        if (timer == 0x0)
        {
            return INVALID_TIMER_HANDLE;
        }

        timer->m_Delay = delay;
        timer->m_Remaining = delay;
        timer->m_UserData = userdata;
        timer->m_Callback = timer_callback;
        timer->m_Repeat = repeat;
        timer->m_IsAlive = 1;

        return timer->m_Handle;
    }

    bool CancelTimer(HTimerWorld timer_world, HTimer handle)
    {
        assert(timer_world != 0x0);
        uint16_t lookup_index = GetLookupIndex(handle);
        if (lookup_index >= timer_world->m_IndexLookup.Size())
        {
            return false;
        }

        uint16_t timer_index = timer_world->m_IndexLookup[lookup_index];
        if (timer_index >= timer_world->m_Timers.Size())
        {
            return false;
        }

        Timer& timer = timer_world->m_Timers[timer_index];
        if (timer.m_Handle != handle)
        {
            return false;
        }

        if (timer.m_IsAlive == 0)
        {
            return false;
        }

        timer.m_IsAlive = 0;
        timer.m_Callback(timer_world, TIMER_EVENT_CANCELLED, timer.m_Handle, 0.f, timer.m_Owner, timer.m_UserData);

        if (timer_world->m_InUpdate == 0)
        {
            FreeTimer(timer_world, timer);
            ++timer_world->m_Version;
        }
        return true;
    }

    uint32_t KillTimers(HTimerWorld timer_world, uintptr_t owner)
    {
        assert(timer_world != 0x0);

        uint32_t size = timer_world->m_Timers.Size();
        uint32_t cancelled_count = 0;
        uint32_t timer_index = 0;
        while (timer_index < size)
        {
            Timer& timer = timer_world->m_Timers[timer_index];
            if (timer.m_Owner != owner)
            {
                ++timer_index;
                continue;
            }

            if (timer.m_IsAlive == 1)
            {
                timer.m_IsAlive = 0;
                ++cancelled_count;
            }

            if (timer_world->m_InUpdate == 0)
            {
                FreeTimer(timer_world, timer);
                --size;
            }
            else
            {
                ++timer_index;
            }
        }

        if (cancelled_count > 0)
        {
            ++timer_world->m_Version;
        }

        return cancelled_count;
    }

    uint32_t GetAliveTimers(HTimerWorld timer_world)
    {
        assert(timer_world != 0x0);

        uint32_t alive_timers = 0u;
        uint32_t size = timer_world->m_Timers.Size();
        uint32_t i = 0;
        while (i < size)
        {
            Timer& timer = timer_world->m_Timers[i];
            if(timer.m_IsAlive == 1)
            {
                ++alive_timers;
            }
            ++i;
        }
        return alive_timers;
    }

    static void SetTimerWorld(HScriptWorld script_world, HTimerWorld timer_world)
    {
        HContext context = GetScriptWorldContext(script_world);
        lua_pushinteger(context->m_LuaState, (lua_Integer)TIMER_WORLD_VALUE_KEY_HASH);
        lua_pushlightuserdata(context->m_LuaState, timer_world);
        SetScriptWorldContextValue(script_world);
    }

    static HTimerWorld GetTimerWorld(HScriptWorld script_world)
    {
        assert(script_world != 0x0);
        HContext context = GetScriptWorldContext(script_world);
        assert(context != 0x0);
        lua_State* L = context->m_LuaState;
        assert(L != 0x0);
        DM_LUA_STACK_CHECK(L, 0);

        lua_pushinteger(L, (lua_Integer)TIMER_WORLD_VALUE_KEY_HASH);
        GetScriptWorldContextValue(script_world);
        HTimerWorld timer_world = (HTimerWorld)lua_touserdata(L, -1);
        lua_pop(L, 1);
        return timer_world;
    }

    void TimerNewScriptWorld(HScriptWorld script_world)
    {
        assert(script_world != 0x0);
        HContext context = GetScriptWorldContext(script_world);
        assert(context != 0x0);
        lua_State* L = context->m_LuaState;
        assert(L != 0x0);
        DM_LUA_STACK_CHECK(L, 0);

        HTimerWorld timer_world = NewTimerWorld();
        lua_pushinteger(L, (lua_Integer)TIMER_WORLD_VALUE_KEY_HASH);
        lua_pushlightuserdata(L, timer_world);
        SetScriptWorldContextValue(script_world);
    }

    void TimerDeleteScriptWorld(HScriptWorld script_world)
    {
        assert(script_world != 0x0);
        HTimerWorld timer_world = GetTimerWorld(script_world);
        if (timer_world != 0x0)
        {
            SetTimerWorld(script_world, 0x0);
            DeleteTimerWorld(timer_world);
        }
    }

    void TimerUpdateScriptWorld(HScriptWorld script_world, float dt)
    {
        assert(script_world != 0x0);
        HTimerWorld timer_world = GetTimerWorld(script_world);
        if (timer_world != 0x0)
        {
            UpdateTimers(timer_world, dt);
        }
    }

    void TimerInitializeInstance(HScriptWorld script_world)
    {
        HContext context = GetScriptWorldContext(script_world);
        lua_State* L = GetLuaState(context);
        DM_LUA_STACK_CHECK(L, 0);

        lua_pushinteger(L, (lua_Integer)TIMER_WORLD_VALUE_KEY_HASH);
        HTimerWorld timer_world = GetTimerWorld(script_world);
        lua_pushlightuserdata(L, timer_world);
        SetInstanceContextValue(L);
    }

    void TimerFinalizeInstance(HScriptWorld script_world)
    {
        HContext context = GetScriptWorldContext(script_world);
        lua_State* L = GetLuaState(context);
        DM_LUA_STACK_CHECK(L, 0);

        uintptr_t owner = dmScript::GetInstanceId(L);
        HTimerWorld timer_world = GetTimerWorld(script_world);
        KillTimers(timer_world, owner);

        lua_pushinteger(L, (lua_Integer)TIMER_WORLD_VALUE_KEY_HASH);
        lua_pushnil(L);
        SetInstanceContextValue(L);
    }

    struct LuaTimerCallbackArgs
    {
        dmScript::HTimer timer_handle;
        float time_elapsed;
    };

    static void LuaTimerCallbackArgsCB(lua_State* L, void* user_context)
    {
        LuaTimerCallbackArgs* args = (LuaTimerCallbackArgs*)user_context;
        lua_pushinteger(L, args->timer_handle);
        lua_pushnumber(L, args->time_elapsed);
    }

    static void LuaTimerCallback(HTimerWorld timer_world, TimerEventType event_type, dmScript::HTimer timer_handle, float time_elapsed, uintptr_t owner, uintptr_t userdata)
    {
        LuaCallbackInfo* callback = (LuaCallbackInfo*)userdata;
        if (!IsCallbackValid(callback))
        {
            return;
        }

        if (event_type != TIMER_EVENT_CANCELLED)
        {
            LuaTimerCallbackArgs args = { timer_handle, time_elapsed };

            InvokeCallback(callback, LuaTimerCallbackArgsCB, &args);
        }

        if ((event_type != TIMER_EVENT_TRIGGER_WILL_REPEAT) && IsCallbackValid(callback))
        {
            DestroyCallback(callback);
        }
    }

    static dmScript::HTimerWorld GetTimerWorld(lua_State* L)
    {
        lua_pushinteger(L, (lua_Integer)TIMER_WORLD_VALUE_KEY_HASH);
        dmScript::GetInstanceContextValue(L);

        if (lua_type(L, -1) != LUA_TLIGHTUSERDATA)
        {
            lua_pop(L, 1);
            return 0x0;
        }

        dmScript::HTimerWorld world = (dmScript::HTimerWorld)lua_touserdata(L, -1);
        lua_pop(L, 1);
        return world;
    }

    /*# create a timer
     * Adds a timer and returns a unique handle
     *
     * You may create more timers from inside a timer callback.
     *
     * Using a delay of 0 will result in a timer that triggers at the next frame just before
     * script update functions.
     *
     * If you want a timer that triggers on each frame, set delay to 0.0f and repeat to true.
     *
     * Timers created within a script will automatically die when the script is deleted.
     *
     * @name timer.delay
     * @param delay [type:number] time interval in seconds
     * @param repeat [type:boolean] true = repeat timer until cancel, false = one-shot timer
     * @param callback [type:function(self, handle, time_elapsed)] timer callback function
     *
     * `self`
     * : [type:object] The current object
     *
     * `handle`
     * : [type:number] The handle of the timer
     *
     * `time_elapsed`
     * : [type:number] The elapsed time - on first trigger it is time since timer.delay call, otherwise time since last trigger
     *
     * @return [type:hash] handle identifier for the create timer, returns timer.INVALID_TIMER_HANDLE if the timer can not be created
     */
    static int TimerDelay(lua_State* L) {
        int top = lua_gettop(L);
        luaL_checktype(L, 1, LUA_TNUMBER);
        luaL_checktype(L, 2, LUA_TBOOLEAN);
        luaL_checktype(L, 3, LUA_TFUNCTION);

        const double seconds = lua_tonumber(L, 1);
        if (seconds < 0.0)
        {
            return luaL_error(L, "timer.delay does not support negative delay times");
        }

        bool repeat = lua_toboolean(L, 2);

        dmScript::HTimerWorld timer_world = GetTimerWorld(L);
        if (timer_world == 0x0)
        {
            dmLogError("Unable to create a timer, the lua context does not have a timer world");
            lua_pushnumber(L, dmScript::INVALID_TIMER_HANDLE);
            return 1;
        }

        uintptr_t owner = dmScript::GetInstanceId(L);

        LuaCallbackInfo* user_data = dmScript::CreateCallback(L, 3);

        dmScript::HTimer handle = dmScript::AddTimer(timer_world, seconds, repeat, LuaTimerCallback, (uintptr_t)owner, (uintptr_t)user_data);

        lua_pushinteger(L, handle);
        assert(top + 1 == lua_gettop(L));
        return 1;
    }

    /*# cancel a timer
     *
     * You may cancel a timer from inside a timer callback.
     * Cancelling a timer that is already executed or cancelled is safe.
     *
     * @name timer.cancel
     * @param handle [type:hash] the timer handle returned by timer.delay()
     * @return true [type:boolean] if the timer was active, false if the timer is already cancelled / complete
     */
    static int TimerCancel(lua_State* L)
    {
        int top = lua_gettop(L);
        const int handle = luaL_checkint(L, 1);

        dmScript::HTimerWorld timer_world = GetTimerWorld(L);
        if (timer_world == 0x0)
        {
            lua_pushboolean(L, 0);
            return 1;
        }

        bool cancelled = dmScript::CancelTimer(timer_world, (dmScript::HTimer)handle);
        lua_pushboolean(L, cancelled ? 1 : 0);
        assert(top + 1 == lua_gettop(L));
        return 1;
    }

    /*# trigger a callback
     *
     * Manual triggering a callback for a timer.
     *
     * @name timer.trigger
     * @param handle [type:hash] the timer handle returned by timer.delay()
     * @return true [type:boolean] if the timer was active, false if the timer is already cancelled / complete
     */
    static int TimerTrigger(lua_State* L)
    {
        DM_LUA_STACK_CHECK(L, 1);

        const int timer_handle = luaL_checkint(L, 1);

        dmScript::HTimerWorld timer_world = GetTimerWorld(L);
        if (timer_world == 0x0)
        {
            dmLogError("Unable to trigger callback, the lua context does not have a timer world");
            lua_pushboolean(L, 0);
            return 1;
        }

        uint16_t lookup_index = GetLookupIndex(timer_handle);
        if (lookup_index >= timer_world->m_IndexLookup.Size())
        {
            lua_pushboolean(L, 0);
            return 1;
        }

        uint16_t timer_index = timer_world->m_IndexLookup[lookup_index];
        if (timer_index >= timer_world->m_Timers.Size())
        {
            lua_pushboolean(L, 0);
            return 1;
        }

        Timer& timer = timer_world->m_Timers[timer_index];

        LuaCallbackInfo* callback = (LuaCallbackInfo*)timer.m_UserData;
        if (!IsCallbackValid(callback))
        {
            lua_pushboolean(L, 0);
            return 1;
        }

        LuaTimerCallbackArgs args = { timer.m_Handle, timer.m_Delay - timer.m_Remaining };
        InvokeCallback(callback, LuaTimerCallbackArgsCB, &args);

        lua_pushboolean(L, 1);
        return 1;
    }

    static const luaL_reg TIMER_COMP_FUNCTIONS[] = {
        { "delay", TimerDelay },
        { "cancel", TimerCancel },
        { "trigger", TimerTrigger},
        { 0, 0 }
    };

    void TimerInitialize(HContext context)
    {
        lua_State* L = context->m_LuaState;
        DM_LUA_STACK_CHECK(L, 0);

        luaL_register(L, "timer", TIMER_COMP_FUNCTIONS);

        #define SETCONSTANT(name) \
            lua_pushnumber(L, (lua_Number) name); \
            lua_setfield(L, -2, #name);\

        /*# Indicates an invalid timer handle
         *
         * @name timer.INVALID_TIMER_HANDLE
         * @variable
         */
        SETCONSTANT(INVALID_TIMER_HANDLE);

        lua_pop(L, 1);
    }

    void InitializeTimer(HContext context)
    {
        static ScriptExtension sl;
        sl.Initialize = TimerInitialize;
        sl.NewScriptWorld = TimerNewScriptWorld;
        sl.DeleteScriptWorld = TimerDeleteScriptWorld;
        sl.UpdateScriptWorld = TimerUpdateScriptWorld;
        sl.FixedUpdateScriptWorld = 0;
        sl.InitializeScriptInstance = TimerInitializeInstance;
        sl.FinalizeScriptInstance = TimerFinalizeInstance;
        RegisterScriptExtension(context, &sl);
    }
}

max_stars_repo_name: cmarincia/defold

max_issues_repo_name: cmarincia/defold

max_forks_repo_name: cmarincia/defold


text:
/*
Copyright (c) 2017 Donald Munro

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.
 */

#include "PointCloudWin.h"

#include <iomanip>
#include <vector>
#include <regex>
#include <sstream>
#include <fstream>
#include <regex>
#include <algorithm>
#ifdef STD_FILESYSTEM
#include <filesystem>
namespace filesystem = std::filesystem;
#endif
#ifdef FILESYSTEM_EXPERIMENTAL
#include <experimental/filesystem>
namespace filesystem = std::experimental::filesystem;
#endif
#ifdef FILESYSTEM_BOOST
#include <boost/filesystem.hpp>
namespace filesystem = boost::filesystem;
#endif

#include <assert.h>

#include <glm/gtc/quaternion.hpp>
#include <glm/gtx/quaternion.hpp>

#include "tinyply.h"
#include "OGLUtils.h"

//#define BOUNDS_VERTICES 1

PointCloudWin::PointCloudWin(std::string title, int w, int h, const std::string& shader_dir,
                               const std::string& plyfilename, const float scale, bool yz_flip, bool is_mean_center,
                             int glsl_ver, int gl_major, int gl_minor, bool can_resize) :
      oglfiber::OGLFiberWindow(title, w, h, gl_major, gl_minor, can_resize, nullptr), glsl_ver(glsl_ver),
      scale(scale), yz_flip(yz_flip), mean_center(is_mean_center)
//--------------------------------------------------------------------------------------------------------------------
{
   filesystem::path dir(shader_dir);
   is_good = filesystem::is_directory(dir);
   if (! is_good)
   {
      std::cerr << "Invalid shader directory" << shader_dir << std::endl;
      return;
   }
   if (! filesystem::is_directory(dir / filesystem::path("axes")))
   {
      std::cerr << "Shader directory" << shader_dir << "/axes not found" << std::endl;
      is_good = false;
      return;
   }
   if (! filesystem::is_directory(dir / filesystem::path("cloud")))
   {
      std::cerr << "Shader directory" << shader_dir << "/cloud not found" << std::endl;
      is_good = false;
      return;
   }
   shader_directory = dir;
   filesystem::path p(plyfilename);
   if (! filesystem::is_regular_file(filesystem::canonical(p)))
   {
      std::cerr << "Ply file " << filesystem::canonical(p) << " not valid." << std::endl;
      is_good = false;
      return;
   }
   else
   {
      std::ifstream ifs(filesystem::canonical(p));
      is_good = ifs.good();
      if (! is_good)
      {
         std::cerr << "Ply file " << filesystem::canonical(p) << " not readable" << std::endl;
         return;
      }
   }
   plyfile = p;
}

void PointCloudWin::on_initialize(const GLFWwindow *win)
//------------------------------------------------------
{
   glClearColor(0.0, 0.0, 0.0, 0.0);
   glEnable(GL_DEPTH_TEST);
   GLenum err;
   std::stringstream errs;
   std::string vertex_glsl, fragment_glsl;
   filesystem::path dir = shader_directory / filesystem::path("axes");
   bool is_axes = true;
   if (oglutil::load_shaders(dir.string(), vertex_glsl, fragment_glsl))
   {
      axes_unit.program = oglutil::compile_link_shader(replace_ver(vertex_glsl.c_str(), glsl_ver),
                                                       replace_ver(fragment_glsl.c_str(), glsl_ver),
                                                       axes_unit.vertex_shader, axes_unit.fragment_shader,
                                                       err, &errs);
      if (axes_unit.program ==  GL_FALSE)
      {
         std::cerr << "Error linking Axis shader program:" << err << ": " << errs.str();
         is_axes = false;
      }
      else
      {
         if (axes_unit.uniform("MVP") == -1)
         {
            is_axes = false;
            std::cerr << "Error linking Axis shader program:" << err << ": " << errs.str();
         }
      }
   }
   else
   {
      std::cerr << "Axes shader directory " << dir.string() << " error. Axes will not be displayed." << std::endl;
      is_axes = false;
   }

   dir = shader_directory / filesystem::path("cloud");
   if (! oglutil::load_shaders(dir.string(), vertex_glsl, fragment_glsl))
   {
      std::cerr << "Error loading point cloud shaders from " << dir.string() << std::endl;
      is_good = false;
      return;
   }
   pointcloud_unit.program = oglutil::compile_link_shader(replace_ver(vertex_glsl.c_str(), glsl_ver),
                                                          replace_ver(fragment_glsl.c_str(), glsl_ver),
                                                          pointcloud_unit.vertex_shader,
                                                          pointcloud_unit.fragment_shader,
                                                          err, &errs);
   if (pointcloud_unit.program ==  GL_FALSE)
   {
      std::cerr << "Error linking shader program:" << err << ": " << errs.str();
      is_good = false;
      return;
   }
   if ( (pointcloud_unit.uniform("MV") == -1) || (pointcloud_unit.uniform("P") == -1) ||
        (pointcloud_unit.uniform("maxDistance") == -1) || (pointcloud_unit.uniform("pointSize") == -1))
   {
      std::cerr << "Error linking shader program:" << err << ": " << errs.str();
      is_good = false;
      return;
   }

   errs.str("OpenGL Initialization error: ");
   if (! oglutil::isGLOk(err, &errs))
   {
      std::cerr << errs.str().c_str() << std::endl;
      exit(1);
   }
   initialised_pc = init_pointcloud();
   if (! initialised_pc)
   {
      std::cerr << "Error initializing point cloud buffers from " << plyfile.string() << std::endl;
      is_good = false;
      return;
   }
   if (is_axes)
      initialised_axes = init_axes();
   else
      initialised_axes = false;

   glfwSetInputMode(GLFW_win(), GLFW_CURSOR, GLFW_CURSOR_NORMAL);
//   glfwSetInputMode(GLFW_win(), GLFW_STICKY_MOUSE_BUTTONS, 1);
}

void PointCloudWin::on_resized(int w, int h)
//-------------------------------------------
{
   width = w;
   height = h;
   glViewport(0, 0, width, height);
//      P = glm::infinitePerspective(glm::radians(45.0f), (float)width / (float)height, 0.1f);
   P = glm::perspective(glm::radians(45.0f), (float)width / (float)height, 0.01f, rangez*3);
//   P = glm::ortho(minx-1, maxx+1, miny-1, maxy+1, 0.01f, rangez*3);

}

bool PointCloudWin::on_render()
//---------------------
{
   oglutil::clearGLErrors();
   GLenum err;
   std::stringstream errs;
   glEnable(GL_DEPTH_TEST);
   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
   glClearColor(0, 0, 0, 1.0);
   glClear(GL_COLOR_BUFFER_BIT);

   glm::mat4 MV = glm::lookAt(location, centroid, tangent);//glm::vec3(0, 1, 0));
   if (initialised_axes)
   {
      axes_unit.activate();
      glm::mat4 MVP = P * MV;
      glUniformMatrix4fv(axes_unit.uniform("MVP"), 1, GL_FALSE, &MVP[0][0]);
      if (! oglutil::isGLOk(err, &errs))
         std::cerr << err << ": " << errs.str().c_str() << std::endl;
      if (! oglutil::isGLOk(err, &errs))
         std::cerr << err << ": " << errs.str().c_str() << std::endl;
      glBindVertexArray(axes_unit("VAO_AXES"));
      if (! oglutil::isGLOk(err, &errs))
         std::cerr << err << ": " << errs.str().c_str() << std::endl;
      glDrawArrays(GL_LINES, 0, 6);
      glBindVertexArray(0);
      glUseProgram(0);
   }
   if (initialised_pc)
   {
      pointcloud_unit.activate();
      glUniformMatrix4fv(pointcloud_unit.uniform("MV"), 1, GL_FALSE, &MV[0][0]);
      if (!oglutil::isGLOk(err, &errs)) std::cerr << err << ": " << errs.str().c_str() << std::endl;
      glUniformMatrix4fv(pointcloud_unit.uniform("P"), 1, GL_FALSE, &P[0][0]);
      if (!oglutil::isGLOk(err, &errs)) std::cerr << err << ": " << errs.str().c_str() << std::endl;
      glUniform1f(pointcloud_unit.uniform("maxDistance"), maxDistance);
      glUniform1f(pointcloud_unit.uniform("pointSize"), pointSize);
      glBindVertexArray(pointcloud_unit("VAO_VERTICES"));
      //glPointSize(3);
      glEnable(GL_PROGRAM_POINT_SIZE);
      glDrawArrays(GL_POINTS, 0, count);
      glBindVertexArray(0);
      glUseProgram(0);
#ifdef PCW_DEBUG_SHADER
      const glm::vec3 close_color = glm::vec3(1, 0, 0);
      const glm::vec3 far_color = glm::vec3(0, 0, 0.25);
      const glm::vec4 eye_Position =  MV * glm::vec4(location, 1.0);
      for (const glm::vec3& vPosition : _vertices_)
      {
         glm::vec4 position = MV * glm::vec4(vPosition, 1.0);
         float d = glm::distance(eye_Position, position);
         float scale = static_cast<float>(glm::clamp(1.0 - (d / maxDistance), 0.1, 1.0));
         glm::vec3 colour = glm::mix(close_color, far_color, scale);
         std::cout << glm::to_string(eye_Position) << std::endl;
         std::cout << glm::to_string(position) << " " << glm::to_string(eye_Position) << " "
                   << d << " " << scale << " " << glm::to_string(colour) << std::endl;
      }
#endif

//      for (const glm::vec3& item : vertices)
//      {
//         glm::vec4 wc = MVP*glm::vec4(item.x, item.y, item.z, 1);
//         wc /= wc[3];
//         std::cout << "(" << item.x << ", " << item.y << ", " << item.z << ") = "
//                   << glm::to_string(wc) << std::endl;
//      }
   }

   if (! oglutil::isGLOk(err, &errs))
      std::cerr << err << ": " << errs.str().c_str() << std::endl;
   return true;
}

bool PointCloudWin::init_axes()
//----------------------------------
{
   if (axes_unit("VAO_AXES") != GL_FALSE)
      glDeleteVertexArrays(1, &axes_unit("VAO_AXES"));
   if (axes_unit("VBO_AXES") != GL_FALSE)
      glDeleteBuffers(1, &axes_unit("VBO_AXES"));

   oglutil::clearGLErrors();
   GLfloat ax = centroid.x, ay = centroid.y, az = centroid.z;
   GLfloat axes[] =
         { minx, ay, az, 1.0f, 1.0f, 0.0f,   maxx, ay,  az, 1.0f, 1.0f, 0.0f,
           ax,  miny, az, 0.0f, 1.0f, 0.0f,  ax, maxy, az, 0.0f, 1.0f, 0.0f,
           ax,  ay, minz, 0.0f, 0.0f, 1.0f,  ax, ay, maxz, 0.0f, 0.0f, 1.0f
         };
   glGenBuffers(1, &axes_unit("VBO_AXES"));
   glBindBuffer(GL_ARRAY_BUFFER, axes_unit("VBO_AXES"));
   glBufferData(GL_ARRAY_BUFFER, sizeof(axes), axes, GL_STATIC_DRAW);
   glBindBuffer(GL_ARRAY_BUFFER, 0);

   glGenVertexArrays(1, &axes_unit("VAO_AXES"));
   glBindVertexArray(axes_unit("VAO_AXES"));
   glBindBuffer(GL_ARRAY_BUFFER, axes_unit("VBO_AXES"));
   glEnableVertexAttribArray(0);
   glEnableVertexAttribArray (1);
   GLsizei stride = sizeof(GLfloat) * (3 + 3);
   glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, stride, 0);
   glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, stride, reinterpret_cast<const void *>(3 * sizeof (GLfloat)));
   glBindVertexArray(0);
   GLenum err;
   std::stringstream errs;
   if (! oglutil::isGLOk(err, &errs))
   {
      std::cerr << err << ": " << errs.str().c_str() << std::endl;
      return false;
   }
   return true;
}

inline void _push_vertex(GLfloat*& vertices, GLfloat x, GLfloat y, GLfloat z, GLfloat w,
                         GLfloat r, GLfloat g, GLfloat b, GLfloat a)
{
   *vertices++ = x; *vertices++ = y; *vertices++ = z; *vertices++ = w;
   *vertices++ = r; *vertices++ = g; *vertices++ = b; *vertices++ = a;
}

std::unique_ptr<GLfloat[]> PointCloudWin::load_pointcloud()
//---------------------------------------------------------
{
   if (plyfile.empty()) return nullptr;
   std::ifstream ifs(plyfile.c_str(), std::ios::binary);
   if (ifs.fail())
   {
      std::cerr << "Could not open pointcloud file " << plyfile.filename() << std::endl;;
      initialised_pc = false;
      return nullptr;
   }
   tinyply::PlyFile file;
   std::shared_ptr<tinyply::PlyData> verts, colors;
   try
   {
      if (! file.parse_header(ifs))
      {
         std::cerr << "Could not parse pointcloud file header for " << plyfile.filename() << std::endl;
         initialised_pc = false;
         return nullptr;
      }
      for (auto e : file.get_elements())
      {
         if (e.name == "vertex")
         {
            for (auto p : e.properties)
            {
               if ( (p.name == "red") || (p.name == "green") || (p.name == "blue") )
                  is_color_pointcloud = true;
               if (p.name == "alpha")
                  is_alpha_pointcloud = true;
            }
         }
      }

      verts = file.request_properties_from_element("vertex", { "x", "y", "z" });
      try
      {
         if (is_alpha_pointcloud)
            colors = file.request_properties_from_element("vertex", {"red", "green", "blue", "alpha"});
         else
            colors = file.request_properties_from_element("vertex", {"red", "green", "blue"});
      }
      catch (const std::exception & e)
      {
         is_color_pointcloud = is_alpha_pointcloud = false;
         std::cerr << "Could not read colors from pointcloud file " << plyfile.filename() << std::endl;
      }
      file.read(ifs);
   }
   catch (const std::exception & e)
   {
      std::cerr << "Exception: " << e.what() << " reading ply file " << plyfile.filename() << std::endl;
      initialised_pc = false;
      return nullptr;
   }
   if ( (! verts) || (verts->count == 0) )
   {
      std::stringstream ss;
      ss << "No vertices in file " << plyfile.filename();
      std::cerr << ss.str().c_str() << std::endl;
      initialised_pc = false;
      return nullptr;
   }
   if ( (! colors) || (colors->count == 0) )
      is_color_pointcloud = is_alpha_pointcloud = false;

//   size_t bytes = verts->buffer.size_bytes();
#ifdef BOUNDS_VERTICES
   count = verts->count + 8;
#else
   count = verts->count;
#endif
   struct RGB { u_char r,g,b; };
   struct RGBA { u_char r,g,b,a; };
   std::vector<GLfloat> Xs, Ys, Zs;
   auto vertdata = reinterpret_cast<float3 *>(verts->buffer.get());
   RGB* RGBdata = nullptr;
   RGBA* RGBAdata = nullptr;
   if (is_color_pointcloud)
   {
      if (is_alpha_pointcloud)
         RGBAdata = reinterpret_cast<RGBA *>(colors->buffer.get());
      else
         RGBdata = reinterpret_cast<RGB *>(colors->buffer.get());
   }

   const size_t buffer_size = count*8;
   std::unique_ptr<GLfloat[]> vertices(new GLfloat[buffer_size]);
   GLfloat *vertices_ptr = vertices.get();
#ifndef NDEBUG
   GLfloat *vertices_ptr_end = &vertices_ptr[buffer_size];
#endif
   const GLfloat flip = (yz_flip) ? -1 : 1;
   double totalx = 0, totaly = 0, totalz = 0;
   double n = 0;
#ifdef PCW_DEBUG_SHADER
   _vertices_.clear();
#endif
   if (! mean_center)
   {
      Xs.resize(verts->count);
      Ys.resize(verts->count);
      Zs.resize(verts->count);
   }
   GLfloat x, y, z, red =1.0f, green =0, blue =0, alpha =1.0f;
   for (size_t i=0; i<count; i++)
   {
      float3 item = vertdata[i];
      x = item.x * scale;
      y = item.y * scale*flip;
      z = item.z * scale*flip;
      if ( (is_color_pointcloud) && (i < colors->count) )
      {
         if (is_color_pointcloud)
         {
            if (is_alpha_pointcloud)
            {
               red = static_cast<float>(RGBAdata[i].r) / 255.0f;
               green = static_cast<float>(RGBAdata[i].g) / 255.0f;
               blue = static_cast<float>(RGBAdata[i].b) / 255.0f;
               alpha = static_cast<float>(RGBAdata[i].a) / 255.0f;
            }
            else
            {
               red = static_cast<float>(RGBdata[i].r) / 255.0f;
               green = static_cast<float>(RGBdata[i].g) / 255.0f;
               blue = static_cast<float>(RGBdata[i].b) / 255.0f;
               alpha = 1.0f;
            }
         }
      }
      else
      {
         red = alpha = 1.0f;
         green = blue = 0;
      }
      _push_vertex(vertices_ptr, x, y, z, 1, red, green, blue, alpha);
#ifdef PCW_DEBUG_SHADER
      _vertices_.emplace_back(x, y, z);
#endif
      if (! mean_center)
      {
         Xs[i] = x;
         Ys[i] = y;
         Zs[i] = z;
      }
      // std::cout << std::fixed << std::setprecision(5) << x << ", " << y << ", " << z << std::endl;

      if (x < minx) minx = x;
      if (x > maxx) maxx = x;
      if (y < miny) miny = y;
      if (y > maxy) maxy = y;
      if (z < minz) minz = z;
      if (z > maxz) maxz = z;
      totalx += x; totaly += y; totalz += z;
      n++;
   }
   assert(vertices_ptr == vertices_ptr_end);
   rangex = fabsf(maxx - minx); rangey = fabsf(maxy - miny); rangez = fabsf(maxz - minz);
   max_r = sqrtf(rangex*rangex + rangey*rangey + rangez*rangez);
   if (isnanf(r))
      r = max_r/2.0f;
   phi =PIf/2.0f; theta =0;
   cartesian();
   vertices_ptr = vertices.get();
   maxDistance = std::numeric_limits<float>::lowest();
   for (size_t i=0; i<count; i++)
   {
      GLfloat x = *vertices_ptr++;
      GLfloat y = *vertices_ptr++;
      GLfloat z = *vertices_ptr++;
      glm::vec3 p(x, y, z);
      float d = glm::distance(location, p);
      if (d > maxDistance)
         maxDistance = d;
   }
   if (mean_center)
   {
      const auto meanx = static_cast<float>(totalx / n);
      const auto meany = static_cast<float>(totaly / n);
      const auto meanz = static_cast<float>(totalz / n);
      centroid = glm::vec3(meanx, meany, meanz);
   }
   else
   {
      std::nth_element(Xs.begin(), Xs.begin() + Xs.size() / 2, Xs.end());
      std::nth_element(Ys.begin(), Ys.begin() + Ys.size() / 2, Ys.end());
      std::nth_element(Zs.begin(), Zs.begin() + Zs.size() / 2, Zs.end());
      const float medianx = Xs[Xs.size() / 2];
      const float mediany = Ys[Ys.size() / 2];
      const float medianz = Zs[Zs.size() / 2];
      centroid = glm::vec3(medianx, mediany, medianz);
   }
   return vertices;
}

bool PointCloudWin::init_pointcloud()
//-----------------------------------
{
   if (! pointcloud_unit) return false;
   std::unique_ptr<GLfloat[]> vertices = load_pointcloud();
   if (! vertices) return false;
   if (pointcloud_unit("VAO_VERTICES") != GL_FALSE)
      glDeleteVertexArrays(1, &pointcloud_unit("VAO_VERTICES"));
   if (pointcloud_unit("VBO_VERTICES") != GL_FALSE)
      glDeleteBuffers(1, &pointcloud_unit("VBO_VERTICES"));

   oglutil::clearGLErrors();
   glGenBuffers(1, &pointcloud_unit("VBO_VERTICES"));
   glBindBuffer(GL_ARRAY_BUFFER, pointcloud_unit("VBO_VERTICES"));
   glBufferData(GL_ARRAY_BUFFER, count*8*sizeof(GLfloat), vertices.get(), GL_DYNAMIC_DRAW);
   glBindBuffer(GL_ARRAY_BUFFER, 0);

   glGenVertexArrays(1, &pointcloud_unit("VAO_VERTICES"));
   glBindVertexArray(pointcloud_unit("VAO_VERTICES"));
   glBindBuffer(GL_ARRAY_BUFFER, pointcloud_unit("VBO_VERTICES"));
   glEnableVertexAttribArray(0);
   glEnableVertexAttribArray (1);
   GLsizei stride = sizeof(GLfloat) * (4 + 4);
   glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, stride, 0);
   glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, stride, reinterpret_cast<const void *>(4 * sizeof (GLfloat)));
   glBindVertexArray(0);
   std::stringstream errs;
   GLuint err;
   errs << "OpenGL error loading pointcloud vertices: ";
   if (! oglutil::isGLOk(err, &errs))
   {
      std::cerr << errs.str().c_str() << std::endl;
      glDeleteVertexArrays(1, &pointcloud_unit("VAO_VERTICES"));
      pointcloud_unit("VAO_VERTICES") = GL_FALSE;
      glDeleteBuffers(1, &pointcloud_unit("VBO_VERTICES"));
      pointcloud_unit("VBO_VERTICES") = GL_FALSE;
      initialised_pc = false;
      return false;
   }
   initialised_pc = true;
   return true;
}

std::string PointCloudWin::replace_ver(const char *pch, int ver)
//----------------------------------------------------------------
{
   if (pch == nullptr)
      return "";
   std::string s(pch);
   std::regex r(R"(\{\{ver\}\})");
   std::stringstream ss;
   ss << ver;
   return std::regex_replace (s, r, ss.str());
}

void PointCloudWin::cartesian()
//---------------------------------
{
   float x = r*sinf(phi)*sinf(theta);
   float y = r*cosf(phi);
   float z = r*sinf(phi)*cosf(theta);
   location = glm::vec3(x, y, z);

   // See tangent.tex/tangent.pdf in project root.
   float r2 = r*r;
   tangent = glm::normalize(glm::vec3(-x*y/r2, -y*y/r2 + 1, -y*z/r2));

//    std::cout << std::fixed << std::setprecision(5) << "location: ("
//              << r << ", " << glm::degrees(theta) << ", " << glm::degrees(phi) << ") = ("
//              << x << ", " << y << ", " << z << ")" << std::endl;
}

void PointCloudWin::onCursorUpdate(double xpos, double ypos)
//-----------------------------------------------------------
{
   cursor_pos.first = xpos; cursor_pos.second = ypos;
   if (is_dragging)
   {
      rotation_update(xpos, ypos);
      drag_start = cursor_pos;
   }
}

void PointCloudWin::on_mouse_click(int button, int action, int mods)
//------------------------------------------------------------------
{
   last_button = button; last_button_action = action; last_button_mods = mods;
   if (last_button == GLFW_MOUSE_BUTTON_LEFT)
   {
      if (last_button_action == GLFW_PRESS)
      {
         is_dragging = true;
         drag_start = cursor_pos;
         if (rotating_cursor == nullptr)
         {
            rotating_cursor = glfwCreateStandardCursor(GLFW_HAND_CURSOR);
            glfwSetCursor(GLFW_win(), rotating_cursor);
         }
      }
      else if (last_button_action == GLFW_RELEASE)
      {
         is_dragging = false;
         if (rotating_cursor != nullptr)
         {
            glfwDestroyCursor(rotating_cursor);
            rotating_cursor = nullptr;
            glfwSetInputMode(GLFW_win(), GLFW_CURSOR, GLFW_CURSOR_NORMAL);
         }
      }
   }
//         rotation_update(last_xpos, last_ypos);
}

void PointCloudWin::rotation_update(double xpos, double ypos)
//-----------------------------------------------------------
{
   std::cout << "(" << xpos << ", " << ypos << ")" << std::endl;
   float xdiff = static_cast<float>(xpos - drag_start.first), ydiff = static_cast<float>(ypos - drag_start.second);
   if (fabs(xdiff) >= fabs(ydiff))
      theta = add_angle(theta, sgn(xdiff) * angle_incr, 2 * PIf);
   else
      phi = add_angle(phi, sgn(ydiff)*angle_incr, PIf);
   cartesian();
}

ext: cc

max_stars_repo_name: donaldmunro/FiberGL

max_issues_repo_name: donaldmunro/FiberGL

max_forks_repo_name: donaldmunro/FiberGL


text:
#pragma once

#include <scorum/protocol/authority.hpp>

#include <scorum/chain/schema/scorum_object_types.hpp>

#include <boost/multi_index/composite_key.hpp>

namespace scorum {
namespace chain {

using scorum::protocol::asset;
using scorum::protocol::asset_symbol_type;
using scorum::protocol::chain_properties;
using scorum::protocol::digest_type;
using scorum::protocol::hardfork_version;
using scorum::protocol::public_key_type;
using scorum::protocol::version;
using scorum::protocol::share_type;

/**
 *  All witnesses with at least 1% net positive approval and
 *  at least 2 weeks old are able to participate in block
 *  production.
 */
class witness_object : public object<witness_object_type, witness_object>
{
public:
    CHAINBASE_DEFAULT_DYNAMIC_CONSTRUCTOR(witness_object, (url))

    enum witness_schedule_type
    {
        top20,
        timeshare,
        none
    };

    id_type id;

    /** the account that has authority over this witness */
    account_name_type owner;
    time_point_sec created;
    fc::shared_string url;
    uint32_t total_missed = 0;
    uint64_t last_confirmed_block_num = 0;

    /**
     *  This is the key used to sign blocks on behalf of this witness
     */
    public_key_type signing_key;

    chain_properties proposed_chain_props;

    /**
     *  The total votes for this witness. This determines how the witness is ranked for
     *  scheduling.  The top N witnesses by votes are scheduled every round, every one
     *  else takes turns being scheduled proportional to their votes.
     */
    share_type votes;
    witness_schedule_type schedule = none; /// How the witness was scheduled the last time it was scheduled

    /**
     * These fields are used for the witness scheduling algorithm which uses
     * virtual time to ensure that all witnesses are given proportional time
     * for producing blocks.
     *
     * @ref votes is used to determine speed. The @ref virtual_scheduled_time is
     * the expected time at which this witness should complete a virtual lap which
     * is defined as the position equal to 1000 times MAXVOTES.
     *
     * virtual_scheduled_time = virtual_last_update + (1000*MAXVOTES - virtual_position) / votes
     *
     * Every time the number of votes changes the virtual_position and virtual_scheduled_time must
     * update.  There is a global current virtual_scheduled_time which gets updated every time
     * a witness is scheduled.  To update the virtual_position the following math is performed.
     *
     * virtual_position       = virtual_position + votes * (virtual_current_time - virtual_last_update)
     * virtual_last_update    = virtual_current_time
     * votes                  += delta_vote
     * virtual_scheduled_time = virtual_last_update + (1000*MAXVOTES - virtual_position) / votes
     *
     * @defgroup virtual_time Virtual Time Scheduling
     */
    ///@{
    fc::uint128 virtual_last_update;
    fc::uint128 virtual_position;
    fc::uint128 virtual_scheduled_time = fc::uint128::max_value();
    ///@}

    /**
     * This field represents the Scorum blockchain version the witness is running.
     */
    version running_version;

    hardfork_version hardfork_version_vote;
    time_point_sec hardfork_time_vote;
};

class witness_vote_object : public object<witness_vote_object_type, witness_vote_object>
{
public:
    CHAINBASE_DEFAULT_CONSTRUCTOR(witness_vote_object)

    id_type id;

    witness_id_type witness;
    account_id_type account;
};

class witness_schedule_object : public object<witness_schedule_object_type, witness_schedule_object>
{
public:
    CHAINBASE_DEFAULT_CONSTRUCTOR(witness_schedule_object)

    id_type id;

    fc::uint128 current_virtual_time;
    fc::array<account_name_type, SCORUM_MAX_WITNESSES_LIMIT> current_shuffled_witnesses;
    uint8_t num_scheduled_witnesses = 1;
};

class witness_reward_in_sp_migration_object
    : public object<witness_reward_in_sp_migration_object_type, witness_reward_in_sp_migration_object>
{
public:
    CHAINBASE_DEFAULT_CONSTRUCTOR(witness_reward_in_sp_migration_object)

    id_type id;

    share_type balance;
};

struct by_vote_name;
struct by_name;
struct by_pow;
struct by_schedule_time;
/**
 * @ingroup object_index
 */
typedef shared_multi_index_container<witness_object,
                                     indexed_by<ordered_unique<tag<by_id>,
                                                               member<witness_object,
                                                                      witness_id_type,
                                                                      &witness_object::id>>,
                                                ordered_unique<tag<by_name>,
                                                               member<witness_object,
                                                                      account_name_type,
                                                                      &witness_object::owner>>,
                                                ordered_unique<tag<by_vote_name>,
                                                               composite_key<witness_object,
                                                                             member<witness_object,
                                                                                share_type,
                                                                                &witness_object::votes>,
                                                                             member<witness_object,
                                                                                account_name_type,
                                                                                &witness_object::owner>>,
                                                               composite_key_compare<std::greater<share_type>,
                                                                                std::less<account_name_type>>>,
                                                ordered_unique<tag<by_schedule_time>,
                                                               composite_key<witness_object,
                                                                             member<witness_object,
                                                                                fc::uint128,
                                                                                &witness_object::
                                                                                virtual_scheduled_time>,
                                                                             member<witness_object,
                                                                                witness_id_type,
                                                                                &witness_object::id>>>>>
    witness_index;

struct by_account_witness;
struct by_witness_account;
typedef shared_multi_index_container<witness_vote_object,
                                     indexed_by<ordered_unique<tag<by_id>,
                                                               member<witness_vote_object,
                                                                      witness_vote_id_type,
                                                                      &witness_vote_object::id>>,
                                                ordered_unique<tag<by_account_witness>,
                                                               composite_key<witness_vote_object,
                                                                             member<witness_vote_object,
                                                                                account_id_type,
                                                                                &witness_vote_object::account>,
                                                                             member<witness_vote_object,
                                                                                witness_id_type,
                                                                                &witness_vote_object::witness>>,
                                                               composite_key_compare<std::less<account_id_type>,
                                                                                std::less<witness_id_type>>>,
                                                ordered_unique<tag<by_witness_account>,
                                                               composite_key<witness_vote_object,
                                                                             member<witness_vote_object,
                                                                                witness_id_type,
                                                                                &witness_vote_object::witness>,
                                                                             member<witness_vote_object,
                                                                                account_id_type,
                                                                                &witness_vote_object::account>>,
                                                               composite_key_compare<std::less<witness_id_type>,
                                                                                std::
                                                                                less<account_id_type>>>> // indexed_by
                                     >
    witness_vote_index;

typedef shared_multi_index_container<witness_schedule_object,
                                     indexed_by<ordered_unique<tag<by_id>,
                                                               member<witness_schedule_object,
                                                                      witness_schedule_id_type,
                                                                      &witness_schedule_object::id>>>>
    witness_schedule_index;

typedef shared_multi_index_container<witness_reward_in_sp_migration_object,
                                     indexed_by<ordered_unique<tag<by_id>,
                                                               member<witness_reward_in_sp_migration_object,
                                                                      witness_reward_in_sp_migration_id_type,
                                                                      &witness_reward_in_sp_migration_object::id>>>>
    witness_reward_in_sp_migration_index;

} // namespace chain
} // namespace scorum

// clang-format off

FC_REFLECT_ENUM( scorum::chain::witness_object::witness_schedule_type, (top20)(timeshare)(none) )

FC_REFLECT( scorum::chain::witness_object,
             (id)
             (owner)
             (created)
             (url)(votes)(schedule)(virtual_last_update)(virtual_position)(virtual_scheduled_time)(total_missed)
             (last_confirmed_block_num)(signing_key)
             (proposed_chain_props)
             (running_version)
             (hardfork_version_vote)(hardfork_time_vote)
          )
CHAINBASE_SET_INDEX_TYPE( scorum::chain::witness_object, scorum::chain::witness_index )

FC_REFLECT( scorum::chain::witness_vote_object, (id)(witness)(account) )
CHAINBASE_SET_INDEX_TYPE( scorum::chain::witness_vote_object, scorum::chain::witness_vote_index )

FC_REFLECT( scorum::chain::witness_schedule_object,
             (id)(current_virtual_time)(current_shuffled_witnesses)(num_scheduled_witnesses)
          )
CHAINBASE_SET_INDEX_TYPE( scorum::chain::witness_schedule_object, scorum::chain::witness_schedule_index )

FC_REFLECT( scorum::chain::witness_reward_in_sp_migration_object,
             (id)(balance)
          )
CHAINBASE_SET_INDEX_TYPE( scorum::chain::witness_reward_in_sp_migration_object, scorum::chain::witness_reward_in_sp_migration_index )

// clang-format on

ext: hpp

max_stars_repo_name: scorum/scorum

max_issues_repo_name: Scorum/Scorum

max_forks_repo_name: Scorum/Scorum


text:
/*
 * Copyright 2013 Stanford University.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * - Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in the
 *   documentation and/or other materials provided with the
 *   distribution.
 *
 * - Neither the name of the copyright holders nor the names of
 *   its contributors may be used to endorse or promote products derived
 *   from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
 * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 */

 /*
  * This file has the main function that launches Nimbus scheduler.
  *
  * Author: Omid Mashayekhi <omidm@stanford.edu>
  */

#define DEFAULT_THREAD_NUM 1
#define DEFAULT_ARRAY_SIZE 1  // In (K)

#include <boost/thread.hpp>
#include <boost/program_options.hpp>
#include <iostream> // NOLINT
#include <list>
#include <vector>

void Thread(size_t size) {
  std::list<size_t> array;
  for (size_t i = 0; i < size; ++i) {
    array.push_back(i);
  }
  while (true) {
    size_t add = 0;
    std::list<size_t>::iterator iter;
    for (iter = array.begin(); iter != array.end(); ++iter) {
      add += *iter;
    }
    for (iter = array.begin(); iter != array.end(); ++iter) {
      *iter = *iter + add;
    }
  }
}

int main(int argc, char *argv[]) {
  namespace po = boost::program_options;

  size_t array_size;
  size_t thread_num;

  po::options_description desc("Options");
  desc.add_options()
    ("help,h", "produce help message")
    // Optinal arguments
    ("thread_num,t", po::value<size_t>(&thread_num)->default_value(DEFAULT_THREAD_NUM), "number of threads") // NOLINT
    ("array_size,s", po::value<size_t>(&array_size)->default_value(DEFAULT_ARRAY_SIZE), "size of array (K)"); // NOLINT

  po::variables_map vm;
  po::store(po::parse_command_line(argc, argv, desc), vm);

  if (vm.count("help")) {
    std::cout << desc << "\n";
    return 0;
  }

  try {
    po::notify(vm);
  }
  catch(std::exception& e) { // NOLINT
    std::cerr << "ERROR: " << e.what() << "\n";
    return -1;
  }

  boost::thread::attributes attrs;
  pthread_attr_setschedpolicy(attrs.native_handle(), SCHED_RR);

  std::list<boost::thread*> threads_;

  for (size_t i = 0; i < thread_num; ++i) {
    boost::thread *t = new boost::thread(attrs, boost::bind(Thread, array_size * 1000));
    threads_.push_back(t);
  }

  std::list<boost::thread*>::iterator iter = threads_.begin();
  for (; iter != threads_.end(); ++iter) {
    (*iter)->join();
  }

  return 0;
}

max_stars_repo_name: schinmayee/nimbus

max_issues_repo_name: schinmayee/nimbus

max_forks_repo_name: schinmayee/nimbus