<commit_before>#include "GLCanvas3DManager.hpp"
#include "../../slic3r/GUI/GUI.hpp"
#include "../../slic3r/GUI/AppConfig.hpp"
#include "../../slic3r/GUI/GLCanvas3D.hpp"

#include <GL/glew.h>

#include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string/classification.hpp>

#include <wx/glcanvas.h>
#include <wx/timer.h>

#include <vector>
#include <string>
#include <iostream>

#ifdef __APPLE__
#include "../Utils/MacDarkMode.hpp"
#endif // __APPLE__

namespace Slic3r {
namespace GUI {

GLCanvas3DManager::GLInfo::GLInfo()
    : m_detected(false)
    , m_version("")
    , m_glsl_version("")
    , m_vendor("")
    , m_renderer("")
    , m_max_tex_size(0)
    , m_max_anisotropy(0.0f)
{
}

const std::string& GLCanvas3DManager::GLInfo::get_version() const
{
    if (!m_detected)
        detect();

    return m_version;
}

const std::string& GLCanvas3DManager::GLInfo::get_glsl_version() const
{
    if (!m_detected)
        detect();

    return m_glsl_version;
}

const std::string& GLCanvas3DManager::GLInfo::get_vendor() const
{
    if (!m_detected)
        detect();

    return m_vendor;
}

const std::string& GLCanvas3DManager::GLInfo::get_renderer() const
{
    if (!m_detected)
        detect();

    return m_renderer;
}

int GLCanvas3DManager::GLInfo::get_max_tex_size() const
{
    if (!m_detected)
        detect();

    // clamp to avoid the texture generation become too slow and use too much GPU memory
#ifdef __APPLE__
    // and use smaller texture for non retina systems
    return (Slic3r::GUI::mac_max_scaling_factor() > 1.0) ? std::min(m_max_tex_size, 8192) : std::min(m_max_tex_size / 2, 4096);
#else
    // and use smaller texture for older OpenGL versions
    return is_version_greater_or_equal_to(3, 0) ? std::min(m_max_tex_size, 8192) : std::min(m_max_tex_size / 2, 4096);
#endif // __APPLE__
}

float GLCanvas3DManager::GLInfo::get_max_anisotropy() const
{
    if (!m_detected)
        detect();

    return m_max_anisotropy;
}

void GLCanvas3DManager::GLInfo::detect() const
{
    const char* data = (const char*)::glGetString(GL_VERSION);
    if (data != nullptr)
        m_version = data;

    data = (const char*)::glGetString(GL_SHADING_LANGUAGE_VERSION);
    if (data != nullptr)
        m_glsl_version = data;

    data = (const char*)::glGetString(GL_VENDOR);
    if (data != nullptr)
        m_vendor = data;

    data = (const char*)::glGetString(GL_RENDERER);
    if (data != nullptr)
        m_renderer = data;

    glsafe(::glGetIntegerv(GL_MAX_TEXTURE_SIZE, &m_max_tex_size));

    if (GLEW_EXT_texture_filter_anisotropic)
        glsafe(::glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &m_max_anisotropy));

    m_detected = true;
}

bool GLCanvas3DManager::GLInfo::is_version_greater_or_equal_to(unsigned int major, unsigned int minor) const
{
    if (!m_detected)
        detect();

    std::vector<std::string> tokens;
    boost::split(tokens, m_version, boost::is_any_of(" "), boost::token_compress_on);

    if (tokens.empty())
        return false;

    std::vector<std::string> numbers;
    boost::split(numbers, tokens[0], boost::is_any_of("."), boost::token_compress_on);

    unsigned int gl_major = 0;
    unsigned int gl_minor = 0;

    if (numbers.size() > 0)
        gl_major = ::atoi(numbers[0].c_str());

    if (numbers.size() > 1)
        gl_minor = ::atoi(numbers[1].c_str());

    if (gl_major < major)
        return false;
    else if (gl_major > major)
        return true;
    else
        return gl_minor >= minor;
}

std::string GLCanvas3DManager::GLInfo::to_string(bool format_as_html, bool extensions) const
{
    if (!m_detected)
        detect();

    std::stringstream out;

    std::string h2_start = format_as_html ? "" : "";
    std::string h2_end = format_as_html ? "" : "";
    std::string b_start = format_as_html ? "" : "";
    std::string b_end = format_as_html ? "" : "";
    std::string line_end = format_as_html ? "
" : "\n";

    out << h2_start << "OpenGL installation" << h2_end << line_end;
    out << b_start << "GL version:   " << b_end << (m_version.empty() ? "N/A" : m_version) << line_end;
    out << b_start << "Vendor:       " << b_end << (m_vendor.empty() ? "N/A" : m_vendor) << line_end;
    out << b_start << "Renderer:     " << b_end << (m_renderer.empty() ? "N/A" : m_renderer) << line_end;
    out << b_start << "GLSL version: " << b_end << (m_glsl_version.empty() ? "N/A" : m_glsl_version) << line_end;

    if (extensions)
    {
        std::vector<std::string> extensions_list;
        std::string extensions_str = (const char*)::glGetString(GL_EXTENSIONS);
        boost::split(extensions_list, extensions_str, boost::is_any_of(" "), boost::token_compress_off);

        if (!extensions_list.empty())
        {
            out << h2_start << "Installed extensions:" << h2_end << line_end;

            std::sort(extensions_list.begin(), extensions_list.end());
            for (const std::string& ext : extensions_list)
            {
                out << ext << line_end;
            }
        }
    }

    return out.str();
}

GLCanvas3DManager::EMultisampleState GLCanvas3DManager::s_multisample = GLCanvas3DManager::MS_Unknown;
bool GLCanvas3DManager::s_compressed_textures_supported = false;
GLCanvas3DManager::GLInfo GLCanvas3DManager::s_gl_info;

GLCanvas3DManager::GLCanvas3DManager()
    : m_context(nullptr)
    , m_gl_initialized(false)
{
}

GLCanvas3DManager::~GLCanvas3DManager()
{
    if (m_context != nullptr)
    {
        delete m_context;
        m_context = nullptr;
    }
}

bool GLCanvas3DManager::add(wxGLCanvas* canvas, Bed3D& bed, Camera& camera, GLToolbar& view_toolbar)
{
    if (canvas == nullptr)
        return false;

    if (do_get_canvas(canvas) != m_canvases.end())
        return false;

    GLCanvas3D* canvas3D = new GLCanvas3D(canvas, bed, camera, view_toolbar);
    if (canvas3D == nullptr)
        return false;

    canvas3D->bind_event_handlers();

    if (m_context == nullptr)
    {
        m_context = new wxGLContext(canvas);
        if (m_context == nullptr)
            return false;
    }

    canvas3D->set_context(m_context);

    m_canvases.insert(CanvasesMap::value_type(canvas, canvas3D));

    return true;
}

bool GLCanvas3DManager::remove(wxGLCanvas* canvas)
{
    CanvasesMap::iterator it = do_get_canvas(canvas);
    if (it == m_canvases.end())
        return false;

    it->second->unbind_event_handlers();
    delete it->second;
    m_canvases.erase(it);

    return true;
}

void GLCanvas3DManager::remove_all()
{
    for (CanvasesMap::value_type& item : m_canvases)
    {
        item.second->unbind_event_handlers();
        delete item.second;
    }
    m_canvases.clear();
}

unsigned int GLCanvas3DManager::count() const
{
    return (unsigned int)m_canvases.size();
}

void GLCanvas3DManager::init_gl()
{
    if (!m_gl_initialized)
    {
        glewInit();
        m_gl_initialized = true;
        if (GLEW_EXT_texture_compression_s3tc)
            s_compressed_textures_supported = true;
        else
            s_compressed_textures_supported = false;
    }
}

bool GLCanvas3DManager::init(wxGLCanvas* canvas)
{
    CanvasesMap::const_iterator it = do_get_canvas(canvas);
    if (it != m_canvases.end())
        return (it->second != nullptr) ? init(*it->second) : false;
    else
        return false;
}

GLCanvas3D* GLCanvas3DManager::get_canvas(wxGLCanvas* canvas)
{
    CanvasesMap::const_iterator it = do_get_canvas(canvas);
    return (it != m_canvases.end()) ? it->second : nullptr;
}

wxGLCanvas* GLCanvas3DManager::create_wxglcanvas(wxWindow *parent)
{
    int attribList[] = {
    	WX_GL_RGBA,
    	WX_GL_DOUBLEBUFFER,
    	// RGB channels each should be allocated with 8 bit depth. One should almost certainly get these bit depths by default.
      	WX_GL_MIN_RED, 			8,
      	WX_GL_MIN_GREEN, 		8,
      	WX_GL_MIN_BLUE, 		8,
      	// Requesting an 8 bit alpha channel. Interestingly, the NVIDIA drivers would most likely work with some alpha plane, but glReadPixels would not return
      	// the alpha channel on NVIDIA if not requested when the GL context is created.
      	WX_GL_MIN_ALPHA, 		0,
    	WX_GL_DEPTH_SIZE, 		24,
    	WX_GL_SAMPLE_BUFFERS, 	GL_TRUE,
    	WX_GL_SAMPLES, 			4,
    	0
    };

    if (s_multisample == MS_Unknown)
    {
        detect_multisample(attribList);
//        // debug output
//        std::cout << "Multisample " << (can_multisample() ? "enabled" : "disabled") << std::endl;
    }

    if (! can_multisample())
        attribList[4] = 0;

    return new wxGLCanvas(parent, wxID_ANY, attribList, wxDefaultPosition, wxDefaultSize, wxWANTS_CHARS);
}

GLCanvas3DManager::CanvasesMap::iterator GLCanvas3DManager::do_get_canvas(wxGLCanvas* canvas)
{
    return (canvas == nullptr) ? m_canvases.end() : m_canvases.find(canvas);
}

GLCanvas3DManager::CanvasesMap::const_iterator GLCanvas3DManager::do_get_canvas(wxGLCanvas* canvas) const
{
    return (canvas == nullptr) ? m_canvases.end() : m_canvases.find(canvas);
}

bool GLCanvas3DManager::init(GLCanvas3D& canvas)
{
    if (!m_gl_initialized)
        init_gl();

    return canvas.init();
}

void GLCanvas3DManager::detect_multisample(int* attribList)
{
    int wxVersion = wxMAJOR_VERSION * 10000 + wxMINOR_VERSION * 100 + wxRELEASE_NUMBER;
    const AppConfig* app_config = GUI::get_app_config();
    bool enable_multisample = wxVersion >= 30003;

    s_multisample = (enable_multisample && wxGLCanvas::IsDisplaySupported(attribList)) ? MS_Enabled : MS_Disabled;
    // Alternative method: it was working on previous version of wxWidgets but not with the latest, at least on Windows
    // s_multisample = enable_multisample && wxGLCanvas::IsExtensionSupported("WGL_ARB_multisample");
}

} // namespace GUI
} // namespace Slic3r
<commit_msg>Yet another fix of the preceding commit.<commit_after>#include "GLCanvas3DManager.hpp"
#include "../../slic3r/GUI/GUI.hpp"
#include "../../slic3r/GUI/AppConfig.hpp"
#include "../../slic3r/GUI/GLCanvas3D.hpp"

#include <GL/glew.h>

#include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string/classification.hpp>

#include <wx/glcanvas.h>
#include <wx/timer.h>

#include <vector>
#include <string>
#include <iostream>

#ifdef __APPLE__
#include "../Utils/MacDarkMode.hpp"
#endif // __APPLE__

namespace Slic3r {
namespace GUI {

GLCanvas3DManager::GLInfo::GLInfo()
    : m_detected(false)
    , m_version("")
    , m_glsl_version("")
    , m_vendor("")
    , m_renderer("")
    , m_max_tex_size(0)
    , m_max_anisotropy(0.0f)
{
}

const std::string& GLCanvas3DManager::GLInfo::get_version() const
{
    if (!m_detected)
        detect();

    return m_version;
}

const std::string& GLCanvas3DManager::GLInfo::get_glsl_version() const
{
    if (!m_detected)
        detect();

    return m_glsl_version;
}

const std::string& GLCanvas3DManager::GLInfo::get_vendor() const
{
    if (!m_detected)
        detect();

    return m_vendor;
}

const std::string& GLCanvas3DManager::GLInfo::get_renderer() const
{
    if (!m_detected)
        detect();

    return m_renderer;
}

int GLCanvas3DManager::GLInfo::get_max_tex_size() const
{
    if (!m_detected)
        detect();

    // clamp to avoid the texture generation become too slow and use too much GPU memory
#ifdef __APPLE__
    // and use smaller texture for non retina systems
    return (Slic3r::GUI::mac_max_scaling_factor() > 1.0) ? std::min(m_max_tex_size, 8192) : std::min(m_max_tex_size / 2, 4096);
#else
    // and use smaller texture for older OpenGL versions
    return is_version_greater_or_equal_to(3, 0) ? std::min(m_max_tex_size, 8192) : std::min(m_max_tex_size / 2, 4096);
#endif // __APPLE__
}

float GLCanvas3DManager::GLInfo::get_max_anisotropy() const
{
    if (!m_detected)
        detect();

    return m_max_anisotropy;
}

void GLCanvas3DManager::GLInfo::detect() const
{
    const char* data = (const char*)::glGetString(GL_VERSION);
    if (data != nullptr)
        m_version = data;

    data = (const char*)::glGetString(GL_SHADING_LANGUAGE_VERSION);
    if (data != nullptr)
        m_glsl_version = data;

    data = (const char*)::glGetString(GL_VENDOR);
    if (data != nullptr)
        m_vendor = data;

    data = (const char*)::glGetString(GL_RENDERER);
    if (data != nullptr)
        m_renderer = data;

    glsafe(::glGetIntegerv(GL_MAX_TEXTURE_SIZE, &m_max_tex_size));

    if (GLEW_EXT_texture_filter_anisotropic)
        glsafe(::glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &m_max_anisotropy));

    m_detected = true;
}

bool GLCanvas3DManager::GLInfo::is_version_greater_or_equal_to(unsigned int major, unsigned int minor) const
{
    if (!m_detected)
        detect();

    std::vector<std::string> tokens;
    boost::split(tokens, m_version, boost::is_any_of(" "), boost::token_compress_on);

    if (tokens.empty())
        return false;

    std::vector<std::string> numbers;
    boost::split(numbers, tokens[0], boost::is_any_of("."), boost::token_compress_on);

    unsigned int gl_major = 0;
    unsigned int gl_minor = 0;

    if (numbers.size() > 0)
        gl_major = ::atoi(numbers[0].c_str());

    if (numbers.size() > 1)
        gl_minor = ::atoi(numbers[1].c_str());

    if (gl_major < major)
        return false;
    else if (gl_major > major)
        return true;
    else
        return gl_minor >= minor;
}

std::string GLCanvas3DManager::GLInfo::to_string(bool format_as_html, bool extensions) const
{
    if (!m_detected)
        detect();

    std::stringstream out;

    std::string h2_start = format_as_html ? "" : "";
    std::string h2_end = format_as_html ? "" : "";
    std::string b_start = format_as_html ? "" : "";
    std::string b_end = format_as_html ? "" : "";
    std::string line_end = format_as_html ? "
" : "\n";

    out << h2_start << "OpenGL installation" << h2_end << line_end;
    out << b_start << "GL version:   " << b_end << (m_version.empty() ? "N/A" : m_version) << line_end;
    out << b_start << "Vendor:       " << b_end << (m_vendor.empty() ? "N/A" : m_vendor) << line_end;
    out << b_start << "Renderer:     " << b_end << (m_renderer.empty() ? "N/A" : m_renderer) << line_end;
    out << b_start << "GLSL version: " << b_end << (m_glsl_version.empty() ? "N/A" : m_glsl_version) << line_end;

    if (extensions)
    {
        std::vector<std::string> extensions_list;
        std::string extensions_str = (const char*)::glGetString(GL_EXTENSIONS);
        boost::split(extensions_list, extensions_str, boost::is_any_of(" "), boost::token_compress_off);

        if (!extensions_list.empty())
        {
            out << h2_start << "Installed extensions:" << h2_end << line_end;

            std::sort(extensions_list.begin(), extensions_list.end());
            for (const std::string& ext : extensions_list)
            {
                out << ext << line_end;
            }
        }
    }

    return out.str();
}

GLCanvas3DManager::EMultisampleState GLCanvas3DManager::s_multisample = GLCanvas3DManager::MS_Unknown;
bool GLCanvas3DManager::s_compressed_textures_supported = false;
GLCanvas3DManager::GLInfo GLCanvas3DManager::s_gl_info;

GLCanvas3DManager::GLCanvas3DManager()
    : m_context(nullptr)
    , m_gl_initialized(false)
{
}

GLCanvas3DManager::~GLCanvas3DManager()
{
    if (m_context != nullptr)
    {
        delete m_context;
        m_context = nullptr;
    }
}

bool GLCanvas3DManager::add(wxGLCanvas* canvas, Bed3D& bed, Camera& camera, GLToolbar& view_toolbar)
{
    if (canvas == nullptr)
        return false;

    if (do_get_canvas(canvas) != m_canvases.end())
        return false;

    GLCanvas3D* canvas3D = new GLCanvas3D(canvas, bed, camera, view_toolbar);
    if (canvas3D == nullptr)
        return false;

    canvas3D->bind_event_handlers();

    if (m_context == nullptr)
    {
        m_context = new wxGLContext(canvas);
        if (m_context == nullptr)
            return false;
    }

    canvas3D->set_context(m_context);

    m_canvases.insert(CanvasesMap::value_type(canvas, canvas3D));

    return true;
}

bool GLCanvas3DManager::remove(wxGLCanvas* canvas)
{
    CanvasesMap::iterator it = do_get_canvas(canvas);
    if (it == m_canvases.end())
        return false;

    it->second->unbind_event_handlers();
    delete it->second;
    m_canvases.erase(it);

    return true;
}

void GLCanvas3DManager::remove_all()
{
    for (CanvasesMap::value_type& item : m_canvases)
    {
        item.second->unbind_event_handlers();
        delete item.second;
    }
    m_canvases.clear();
}

unsigned int GLCanvas3DManager::count() const
{
    return (unsigned int)m_canvases.size();
}

void GLCanvas3DManager::init_gl()
{
    if (!m_gl_initialized)
    {
        glewInit();
        m_gl_initialized = true;
        if (GLEW_EXT_texture_compression_s3tc)
            s_compressed_textures_supported = true;
        else
            s_compressed_textures_supported = false;
    }
}

bool GLCanvas3DManager::init(wxGLCanvas* canvas)
{
    CanvasesMap::const_iterator it = do_get_canvas(canvas);
    if (it != m_canvases.end())
        return (it->second != nullptr) ? init(*it->second) : false;
    else
        return false;
}

GLCanvas3D* GLCanvas3DManager::get_canvas(wxGLCanvas* canvas)
{
    CanvasesMap::const_iterator it = do_get_canvas(canvas);
    return (it != m_canvases.end()) ? it->second : nullptr;
}

wxGLCanvas* GLCanvas3DManager::create_wxglcanvas(wxWindow *parent)
{
    int attribList[] = {
    	WX_GL_RGBA,
    	WX_GL_DOUBLEBUFFER,
    	// RGB channels each should be allocated with 8 bit depth. One should almost certainly get these bit depths by default.
      	WX_GL_MIN_RED, 			8,
      	WX_GL_MIN_GREEN, 		8,
      	WX_GL_MIN_BLUE, 		8,
      	// Requesting an 8 bit alpha channel. Interestingly, the NVIDIA drivers would most likely work with some alpha plane, but glReadPixels would not return
      	// the alpha channel on NVIDIA if not requested when the GL context is created.
      	WX_GL_MIN_ALPHA, 		8,
    	WX_GL_DEPTH_SIZE, 		24,
    	WX_GL_SAMPLE_BUFFERS, 	GL_TRUE,
    	WX_GL_SAMPLES, 			4,
    	0
    };

    if (s_multisample == MS_Unknown)
    {
        detect_multisample(attribList);
//        // debug output
//        std::cout << "Multisample " << (can_multisample() ? "enabled" : "disabled") << std::endl;
    }

    if (! can_multisample())
        attribList[12] = 0;

    return new wxGLCanvas(parent, wxID_ANY, attribList, wxDefaultPosition, wxDefaultSize, wxWANTS_CHARS);
}

GLCanvas3DManager::CanvasesMap::iterator GLCanvas3DManager::do_get_canvas(wxGLCanvas* canvas)
{
    return (canvas == nullptr) ? m_canvases.end() : m_canvases.find(canvas);
}

GLCanvas3DManager::CanvasesMap::const_iterator GLCanvas3DManager::do_get_canvas(wxGLCanvas* canvas) const
{
    return (canvas == nullptr) ? m_canvases.end() : m_canvases.find(canvas);
}

bool GLCanvas3DManager::init(GLCanvas3D& canvas)
{
    if (!m_gl_initialized)
        init_gl();

    return canvas.init();
}

void GLCanvas3DManager::detect_multisample(int* attribList)
{
    int wxVersion = wxMAJOR_VERSION * 10000 + wxMINOR_VERSION * 100 + wxRELEASE_NUMBER;
    const AppConfig* app_config = GUI::get_app_config();
    bool enable_multisample = wxVersion >= 30003;

    s_multisample = (enable_multisample && wxGLCanvas::IsDisplaySupported(attribList)) ? MS_Enabled : MS_Disabled;
    // Alternative method: it was working on previous version of wxWidgets but not with the latest, at least on Windows
    // s_multisample = enable_multisample && wxGLCanvas::IsExtensionSupported("WGL_ARB_multisample");
}

} // namespace GUI
} // namespace Slic3r
<|endoftext|>


<commit_before>///
/// @file  LoadBalancer.cpp
/// @brief The LoadBalancer assigns work to the individual threads
///        in the computation of the special leaves in the
///        Lagarias-Miller-Odlyzko and Deleglise-Rivat prime
///        counting algorithms.
///
///        Simply parallelizing the computation of the special
///        leaves in the Lagarias-Miller-Odlyzko algorithm by
///        subdividing the sieve interval by the number of threads
///        into equally sized subintervals does not scale because
///        the distribution of the special leaves is highly skewed
///        and most special leaves are in the first few segments
///        whereas later on there are very few special leaves.
///
///        This LoadBalancer gradually increases the number of
///        segments to sieve as long the expected runtime of the
///        sieve distance is smaller than the expected finish time
///        of the algorithm. Near the end the LoadBalancer will
///        gradually decrease the number of segments to sieve in
///        order to prevent that 1 thread will run much longer
///        than all the other threads.
///
/// Copyright (C) 2019 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#include <LoadBalancer.hpp>
#include <primecount-internal.hpp>
#include <S2Status.hpp>
#include <Sieve.hpp>
#include <imath.hpp>
#include <int128_t.hpp>
#include <min.hpp>
#include <print.hpp>

#include <stdint.h>
#include <cmath>

using namespace std;

namespace primecount {

LoadBalancer::LoadBalancer(maxint_t x,
                           int64_t y,
                           int64_t z,
                           maxint_t s2_approx) :
  low_(0),
  max_low_(0),
  z_(z),
  segments_(1),
  s2_total_(0),
  s2_approx_(s2_approx),
  time_(get_time()),
  status_(x)
{
  init_size();
  maxint_t x16 = iroot<6>(x);
  double alpha = get_alpha(x, y);
  smallest_hard_leaf_ = (int64_t) (x / (y * sqrt(alpha) * x16));
}

void LoadBalancer::init_size()
{
  // start with a tiny segment_size as most
  // special leaves are in the first few segments
  // and we need to ensure that all threads are
  // assigned an equal amount of work
  int64_t sqrtz = isqrt(z_);
  int64_t log = ilog(sqrtz);
  log = max(log, 1);
  segment_size_ = sqrtz / log;

  int64_t min_size = 1 << 9;
  segment_size_ = max(segment_size_, min_size);
  segment_size_ = Sieve::get_segment_size(segment_size_);

  // try to use a segment size that fits exactly
  // into the CPUs L1 data cache
  int64_t l1_dcache_size = 1 << 15;
  max_size_ = l1_dcache_size * 30;
  max_size_ = max(max_size_, sqrtz);
  max_size_ = Sieve::get_segment_size(max_size_);
}

maxint_t LoadBalancer::get_result() const
{
  return s2_total_;
}

bool LoadBalancer::get_work(int64_t* low,
                            int64_t* segments,
                            int64_t* segment_size,
                            maxint_t s2,
                            Runtime& runtime)
{
  #pragma omp critical (get_work)
  {
    s2_total_ += s2;

    update(low, segments, runtime);

    *low = low_;
    *segments = segments_;
    *segment_size = segment_size_;
    low_ += segments_ * segment_size_;

    if (is_print())
      status_.print(s2_total_, s2_approx_);
  }

  return *low <= z_;
}

void LoadBalancer::update(int64_t* low,
                          int64_t* segments,
                          Runtime& runtime)
{
  if (*low > max_low_)
  {
    max_low_ = *low;
    segments_ = *segments;

    if (segment_size_ < max_size_)
      segment_size_ = min(segment_size_ * 2, max_size_);
    else
      update_segments(runtime);
  }

  // Most hard special leaves are located just past
  // smallest_hard_leaf_. In order to prevent assigning
  // the bulk of work to a single thread we reduce
  // the number of segments to a minimum.

  int64_t high = low_ + segments_ * segment_size_;

  if (smallest_hard_leaf_ >= low_ &&
      smallest_hard_leaf_ <= high)
  {
    segments_ = 1;
  }
}

/// Remaining seconds till finished
double LoadBalancer::remaining_secs() const
{
  double percent = status_.getPercent(low_, z_, s2_total_, s2_approx_);
  percent = in_between(20, percent, 100);
  double total_secs = get_time() - time_;
  double secs = total_secs * (100 / percent) - total_secs;
  return secs;
}

/// Increase or decrease the number of segments based on the
/// remaining runtime. Near the end it is important that
/// threads run only for a short amount of time in order to
/// ensure all threads finish nearly at the same time.
///
void LoadBalancer::update_segments(Runtime& runtime)
{
  double rem = remaining_secs();
  double threshold = rem / 8;
  double min_secs = 0.01;

  // Each thread should run at least 10x
  // longer than its initialization time
  threshold = max(threshold, runtime.init * 10);
  threshold = max(threshold, min_secs);

  // divider must not be 0
  double divider = max(runtime.secs, min_secs / 10);
  double factor = threshold / divider;
  factor = in_between(0.5, factor, 2.0);

  // Prevent threads from running for very long periods of time
  if (runtime.secs > min_secs &&
      runtime.secs > runtime.init * 1000)
    factor = min(factor, 0.8);

  double new_segments = round(segments_ * factor);
  segments_ = (int64_t) new_segments;
  segments_ = max(segments_, 1);
}

} // namespace
<commit_msg>tweak load balancing<commit_after>///
/// @file  LoadBalancer.cpp
/// @brief The LoadBalancer assigns work to the individual threads
///        in the computation of the special leaves in the
///        Lagarias-Miller-Odlyzko and Deleglise-Rivat prime
///        counting algorithms.
///
///        Simply parallelizing the computation of the special
///        leaves in the Lagarias-Miller-Odlyzko algorithm by
///        subdividing the sieve interval by the number of threads
///        into equally sized subintervals does not scale because
///        the distribution of the special leaves is highly skewed
///        and most special leaves are in the first few segments
///        whereas later on there are very few special leaves.
///
///        This LoadBalancer gradually increases the number of
///        segments to sieve as long the expected runtime of the
///        sieve distance is smaller than the expected finish time
///        of the algorithm. Near the end the LoadBalancer will
///        gradually decrease the number of segments to sieve in
///        order to prevent that 1 thread will run much longer
///        than all the other threads.
///
/// Copyright (C) 2019 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#include <LoadBalancer.hpp>
#include <primecount-internal.hpp>
#include <S2Status.hpp>
#include <Sieve.hpp>
#include <imath.hpp>
#include <int128_t.hpp>
#include <min.hpp>
#include <print.hpp>

#include <stdint.h>
#include <cmath>

using namespace std;

namespace primecount {

LoadBalancer::LoadBalancer(maxint_t x,
                           int64_t y,
                           int64_t z,
                           maxint_t s2_approx) :
  low_(0),
  max_low_(0),
  z_(z),
  segments_(1),
  s2_total_(0),
  s2_approx_(s2_approx),
  time_(get_time()),
  status_(x)
{
  init_size();
  maxint_t x16 = iroot<6>(x);
  double alpha = get_alpha(x, y);
  smallest_hard_leaf_ = (int64_t) (x / (y * sqrt(alpha) * x16));
}

void LoadBalancer::init_size()
{
  // start with a tiny segment_size as most
  // special leaves are in the first few segments
  // and we need to ensure that all threads are
  // assigned an equal amount of work
  int64_t sqrtz = isqrt(z_);
  int64_t log = ilog(sqrtz);
  log = max(log, 1);
  segment_size_ = sqrtz / log;

  int64_t min_size = 1 << 9;
  segment_size_ = max(segment_size_, min_size);
  segment_size_ = Sieve::get_segment_size(segment_size_);

  // try to use a segment size that fits exactly
  // into the CPUs L1 data cache
  int64_t l1_dcache_size = 1 << 15;
  max_size_ = l1_dcache_size * 30;
  max_size_ = max(max_size_, sqrtz);
  max_size_ = Sieve::get_segment_size(max_size_);
}

maxint_t LoadBalancer::get_result() const
{
  return s2_total_;
}

bool LoadBalancer::get_work(int64_t* low,
                            int64_t* segments,
                            int64_t* segment_size,
                            maxint_t s2,
                            Runtime& runtime)
{
  #pragma omp critical (get_work)
  {
    s2_total_ += s2;

    update(low, segments, runtime);

    *low = low_;
    *segments = segments_;
    *segment_size = segment_size_;
    low_ += segments_ * segment_size_;

    if (is_print())
      status_.print(s2_total_, s2_approx_);
  }

  return *low <= z_;
}

void LoadBalancer::update(int64_t* low,
                          int64_t* segments,
                          Runtime& runtime)
{
  if (*low > max_low_)
  {
    max_low_ = *low;
    segments_ = *segments;

    if (segment_size_ < max_size_)
      segment_size_ = min(segment_size_ * 2, max_size_);
    else
      update_segments(runtime);
  }

  // Most hard special leaves are located just past
  // smallest_hard_leaf_. In order to prevent assigning
  // the bulk of work to a single thread we reduce
  // the number of segments to a minimum.

  int64_t high = low_ + segments_ * segment_size_;

  if (smallest_hard_leaf_ >= low_ &&
      smallest_hard_leaf_ <= high)
  {
    segments_ = 1;
  }
}

/// Remaining seconds till finished
double LoadBalancer::remaining_secs() const
{
  double percent = status_.getPercent(low_, z_, s2_total_, s2_approx_);
  percent = in_between(10, percent, 100);
  double total_secs = get_time() - time_;
  double secs = total_secs * (100 / percent) - total_secs;
  return secs;
}

/// Increase or decrease the number of segments based on the
/// remaining runtime. Near the end it is important that
/// threads run only for a short amount of time in order to
/// ensure all threads finish nearly at the same time.
///
void LoadBalancer::update_segments(Runtime& runtime)
{
  double rem = remaining_secs();
  double threshold = rem / 8;
  double min_secs = 0.01;

  // Each thread should run at least 10x
  // longer than its initialization time
  threshold = max(threshold, runtime.init * 10);
  threshold = max(threshold, min_secs);

  // divider must not be 0
  double divider = max(runtime.secs, min_secs / 10);
  double factor = threshold / divider;
  factor = in_between(0.5, factor, 2.0);

  // Prevent threads from running for very long periods of time
  if (runtime.secs > min_secs &&
      runtime.secs > runtime.init * 1000)
    factor = min(factor, 0.8);

  double new_segments = round(segments_ * factor);
  segments_ = (int64_t) new_segments;
  segments_ = max(segments_, 1);
}

} // namespace
<|endoftext|>


<commit_before>#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <iomanip>
#include "orc_proto.pb.h"

using namespace org::apache::hadoop::hive::ql::io::orc;

long getTotalPaddingSize(Footer footer);
StripeFooter readStripeFooter(StripeInformation stripe);

std::ifstream input;

int main(int argc, char* argv[])
{
	GOOGLE_PROTOBUF_VERIFY_VERSION;

	// Read the input arguments
	const char ROWINDEX_PREFIX[] = "--rowindex=";
	const int ROWINDEX_PREFIX_LENGTH = strlen(ROWINDEX_PREFIX);

	std::vector<char*> files;
	std::vector<int> rowIndexCols;

	char* pChar ;
	for (int i=1; i<argc; i++)
	{
		if (argv[i][0]=='-' & argv[i][1]=='-') {
			pChar = strstr(argv[i], ROWINDEX_PREFIX);
			if (pChar == argv[i]) {	// the argument string starts with ROWINDEX_PREFIX
				pChar = strtok(argv[i]+ROWINDEX_PREFIX_LENGTH,",");
				while (pChar != NULL)
				{
					rowIndexCols.push_back(atoi(pChar));
					pChar = strtok(NULL,",");
				};
			} else {
				std::cout << "Unknown argument " << argv[i] << std::endl ;
				std::cout << "Usage: localfiledump <filename1> [... <filenameN>] [--rowindex=i1,i2,...,iN]" << std::endl ;
			};
		} else {
			files.push_back(argv[i]);
		};
	};

	for(int fileIx=0; fileIx<files.size(); fileIx++) {
		std::cout << "Structure for " << files[fileIx] << std::endl;

		// FIXIT: Instead of allocating memory for each part of the ORC file (postscript, footer, etc),
		// find a way to provide the stream + initial position + length to the ParseFromXXX() functions
		// Java implementation of protobuf has it, but C++ seems to lack.
		char* buffer ;

		// Determine the file size
		// FIXIT: Should be done using filesystem info
		input.open(files[fileIx], std::ios::in | std::ios::binary);
		input.seekg(0,input.end);
		unsigned int fileSize = input.tellg();

		// Read the postscript size
		input.seekg(fileSize-1);
		unsigned int postscriptSize = (int)input.get() ;

		// Read the postscript
		input.seekg(fileSize - postscriptSize-1);
		buffer = new char[postscriptSize];
		input.read(buffer, postscriptSize);
		PostScript postscript ;
		postscript.ParseFromArray(buffer, postscriptSize);
		delete[] buffer;
		std::cout << std::endl << "Postscript: " << std::endl ;
		postscript.PrintDebugString();

		// Everything but the postscript is compressed
		//CompressionCodec codec ;
		switch (postscript.compression())
		{
			  case NONE:
				  //codec = NULL;
				  break;
			  case ZLIB:
				  //codec = ZlibCodec(); break;
			  case SNAPPY:
				  //codec = SnappyCodec(); break;
			  case LZO:
				  //codec = LzoCodec(); break;
			  default:
				  std::cout << "Unsupported compression!" << std::endl ;
				  input.close();
				  return -1;
		};

		int footerSize = postscript.footerlength();
		int metadataSize = postscript.metadatalength();

		// Read the metadata
		input.seekg(fileSize - 1 - postscriptSize - footerSize - metadataSize);
		buffer = new char[metadataSize];
		input.read(buffer, metadataSize);
		Metadata metadata ;
		metadata.ParseFromArray(buffer, metadataSize);
		delete[] buffer;
		std::cout << std::endl << "Metadata: " << std::endl ;
		postscript.PrintDebugString();

		// Read the footer
		//input.seekg(fileSize -1 - postscriptSize-footerSize);
		buffer = new char[footerSize];
		input.read(buffer, footerSize);
		Footer footer ;
		footer.ParseFromArray(buffer, footerSize);
		delete[] buffer;
		std::cout << std::endl << "Footer: " << std::endl ;
		postscript.PrintDebugString();

		std::cout << std::endl << "Rows: " << footer.numberofrows() << std::endl;
		std::cout << "Compression: " << postscript.compression() << std::endl;
		if (postscript.compression() != NONE)
			std::cout << "Compression size: " << postscript.compressionblocksize() << std::endl;
		std::cout << "Type: " ;
		for (int typeIx=0; typeIx < footer.types_size(); typeIx++) {
			Type type = footer.types(typeIx);
			type.PrintDebugString();
		};

		std::cout << "\nStripe Statistics:" << std::endl;

		StripeInformation stripe ;
		Stream section;
		ColumnEncoding encoding;
		for (int stripeIx=0; stripeIx<footer.stripes_size(); stripeIx++)
		{
			std::cout << "  Stripe " << stripeIx+1 <<": " << std::endl ;
			stripe = footer.stripes(stripeIx);
			stripe.PrintDebugString();

			long offset = stripe.offset() + stripe.indexlength() + stripe.datalength();
			int tailLength = stripe.footerlength();

			// read the stripe footer
			input.seekg(offset);
			buffer = new char[tailLength];
			input.read(buffer, tailLength);

			StripeFooter stripeFooter;
			stripeFooter.ParseFromArray(buffer, tailLength);
			//stripeFooter.PrintDebugString();
			long stripeStart = stripe.offset();
			long sectionStart = stripeStart;
			for (int streamIx=0; streamIx<stripeFooter.streams_size(); streamIx++) {
				section = stripeFooter.streams(streamIx);
				std::cout << "    Stream: column " << section.column()  << " section "
						  << section.kind() << " start: " << sectionStart << " length " << section.length() << std::endl;
				sectionStart += section.length();
			};
			for (int columnIx=0; columnIx<stripeFooter.columns_size(); columnIx++) {
				encoding = stripeFooter.columns(columnIx);
				std::cout << "    Encoding column " << columnIx << ": " << encoding.kind() ;
				if (encoding.kind() == ColumnEncoding_Kind_DICTIONARY || encoding.kind() == ColumnEncoding_Kind_DICTIONARY_V2)
					std::cout << "[" << encoding.dictionarysize() << "]";
				std::cout << std::endl;
			};

			/*
	        if (!rowIndexCols.empty()) {
	        	std::vector<RowIndex> indices;
	        	long offset = stripeStart;

	        	stripeFooter = readStripeFooter(stripe);

	        	for(int streamIx=0; streamIx< stripeFooter.streams_size();streamIx++) {
	        		section = stripeFooter.streams(streamIx);
	        		if (section.kind() == Stream_Kind_ROW_INDEX) {
	        			int col = section.column();

	        			int streamLength = section.length();
	        			char* bufferRowIndex = new char[streamLength];
	        			input.seekg(offset);
	        			input.read(bufferRowIndex, streamLength);
	        			RowIndex rowIndex;
	        			rowIndex.ParseFromArray(bufferRowIndex, streamLength);
	        			delete[] bufferRowIndex ;
	        			indices.push_back(rowIndex);
	        		};
	        		offset += section.length();
	        	};

	        	for (int rowIx = 0; rowIx < rowIndexCols.size(); rowIx++) {
	        		int col = rowIndexCols[rowIx];
	        		std::cout << "    Row group index column " << col << ":" ;
	        		if (col >= indices.size())  {
	        			std::cout << " not found" << std::endl ;
	        			continue;
	        		};
	        		RowIndex index = indices[col];
	        		for (int entryIx = 0; entryIx < index.entry_size(); ++entryIx) {
	        			std::cout << "\n      Entry " << entryIx << ":";
	        			RowIndexEntry entry = index.entry(entryIx);
	        			ColumnStatistics colStats = entry.statistics();
	        			std::cout << " number of values: " << colStats.numberofvalues() ;
	        			for (int posIx = 0; posIx < entry.positions_size(); ++posIx) {
	        				if (posIx != 0)
	        					std::cout << ",";
	        				std::cout << entry.positions(posIx);
	        			};
	        		};
	        		std::cout <<std::endl ;
	        	};
	        };*/
		};

		long paddedBytes = getTotalPaddingSize(footer);
		// empty ORC file is ~45 bytes. Assumption here is file length always >0
		double percentPadding = ((double) paddedBytes / (double) fileSize) * 100;
		std::cout << "File length: " << fileSize << " bytes" << std::endl;
		std::cout <<"Padding length: " << paddedBytes << " bytes" << std::endl;
		std::cout <<"Padding ratio: " << std::fixed << std::setprecision(2) << percentPadding << " %" << std::endl;

		input.close();
	};

	google::protobuf::ShutdownProtobufLibrary();

    return 0;
}

StripeFooter readStripeFooter(StripeInformation stripe) {
	long offset = stripe.offset() + stripe.indexlength() + stripe.datalength();
	int tailLength = (int) stripe.footerlength();

	char* buffer = new char[tailLength];
	input.seekg(offset);
	input.read(buffer, tailLength);
	StripeFooter stripeFooter ;
	stripeFooter.ParseFromArray(buffer, tailLength);
	delete[] buffer;

	return stripeFooter;
}

long getTotalPaddingSize(Footer footer) {
	long paddedBytes = 0;
	StripeInformation stripe;
	for (int stripeIx=1; stripeIx<footer.stripes_size(); stripeIx++) {
		stripe = footer.stripes(stripeIx-1);
		long prevStripeOffset = stripe.offset();
		long prevStripeLen = stripe.datalength() + stripe.indexlength() + stripe.footerlength();
		paddedBytes += footer.stripes(stripeIx).offset() - (prevStripeOffset + prevStripeLen);
	};
	return paddedBytes;
}

<commit_msg>Modified namespace.<commit_after>#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <iomanip>
#include "orc_proto.pb.h"

using namespace orc;

long getTotalPaddingSize(Footer footer);
StripeFooter readStripeFooter(StripeInformation stripe);

std::ifstream input;

int main(int argc, char* argv[])
{
	GOOGLE_PROTOBUF_VERIFY_VERSION;

	// Read the input arguments
	const char ROWINDEX_PREFIX[] = "--rowindex=";
	const int ROWINDEX_PREFIX_LENGTH = strlen(ROWINDEX_PREFIX);

	std::vector<char*> files;
	std::vector<int> rowIndexCols;

	char* pChar ;
	for (int i=1; i<argc; i++)
	{
		if (argv[i][0]=='-' & argv[i][1]=='-') {
			pChar = strstr(argv[i], ROWINDEX_PREFIX);
			if (pChar == argv[i]) {	// the argument string starts with ROWINDEX_PREFIX
				pChar = strtok(argv[i]+ROWINDEX_PREFIX_LENGTH,",");
				while (pChar != NULL)
				{
					rowIndexCols.push_back(atoi(pChar));
					pChar = strtok(NULL,",");
				};
			} else {
				std::cout << "Unknown argument " << argv[i] << std::endl ;
				std::cout << "Usage: localfiledump <filename1> [... <filenameN>] [--rowindex=i1,i2,...,iN]" << std::endl ;
			};
		} else {
			files.push_back(argv[i]);
		};
	};

	for(int fileIx=0; fileIx<files.size(); fileIx++) {
		std::cout << "Structure for " << files[fileIx] << std::endl;

		// FIXIT: Instead of allocating memory for each part of the ORC file (postscript, footer, etc),
		// find a way to provide the stream + initial position + length to the ParseFromXXX() functions
		// Java implementation of protobuf has it, but C++ seems to lack.
		char* buffer ;

		// Determine the file size
		// FIXIT: Should be done using filesystem info
		input.open(files[fileIx], std::ios::in | std::ios::binary);
		input.seekg(0,input.end);
		unsigned int fileSize = input.tellg();

		// Read the postscript size
		input.seekg(fileSize-1);
		unsigned int postscriptSize = (int)input.get() ;

		// Read the postscript
		input.seekg(fileSize - postscriptSize-1);
		buffer = new char[postscriptSize];
		input.read(buffer, postscriptSize);
		PostScript postscript ;
		postscript.ParseFromArray(buffer, postscriptSize);
		delete[] buffer;
		std::cout << std::endl << "Postscript: " << std::endl ;
		postscript.PrintDebugString();

		// Everything but the postscript is compressed
		//CompressionCodec codec ;
		switch (postscript.compression())
		{
			  case NONE:
				  //codec = NULL;
				  break;
			  case ZLIB:
				  //codec = ZlibCodec(); break;
			  case SNAPPY:
				  //codec = SnappyCodec(); break;
			  case LZO:
				  //codec = LzoCodec(); break;
			  default:
				  std::cout << "Unsupported compression!" << std::endl ;
				  input.close();
				  return -1;
		};

		int footerSize = postscript.footerlength();
		int metadataSize = postscript.metadatalength();

		// Read the metadata
		input.seekg(fileSize - 1 - postscriptSize - footerSize - metadataSize);
		buffer = new char[metadataSize];
		input.read(buffer, metadataSize);
		Metadata metadata ;
		metadata.ParseFromArray(buffer, metadataSize);
		delete[] buffer;
		std::cout << std::endl << "Metadata: " << std::endl ;
		postscript.PrintDebugString();

		// Read the footer
		//input.seekg(fileSize -1 - postscriptSize-footerSize);
		buffer = new char[footerSize];
		input.read(buffer, footerSize);
		Footer footer ;
		footer.ParseFromArray(buffer, footerSize);
		delete[] buffer;
		std::cout << std::endl << "Footer: " << std::endl ;
		postscript.PrintDebugString();

		std::cout << std::endl << "Rows: " << footer.numberofrows() << std::endl;
		std::cout << "Compression: " << postscript.compression() << std::endl;
		if (postscript.compression() != NONE)
			std::cout << "Compression size: " << postscript.compressionblocksize() << std::endl;
		std::cout << "Type: " ;
		for (int typeIx=0; typeIx < footer.types_size(); typeIx++) {
			Type type = footer.types(typeIx);
			type.PrintDebugString();
		};

		std::cout << "\nStripe Statistics:" << std::endl;

		StripeInformation stripe ;
		Stream section;
		ColumnEncoding encoding;
		for (int stripeIx=0; stripeIx<footer.stripes_size(); stripeIx++)
		{
			std::cout << "  Stripe " << stripeIx+1 <<": " << std::endl ;
			stripe = footer.stripes(stripeIx);
			stripe.PrintDebugString();

			long offset = stripe.offset() + stripe.indexlength() + stripe.datalength();
			int tailLength = stripe.footerlength();

			// read the stripe footer
			input.seekg(offset);
			buffer = new char[tailLength];
			input.read(buffer, tailLength);

			StripeFooter stripeFooter;
			stripeFooter.ParseFromArray(buffer, tailLength);
			//stripeFooter.PrintDebugString();
			long stripeStart = stripe.offset();
			long sectionStart = stripeStart;
			for (int streamIx=0; streamIx<stripeFooter.streams_size(); streamIx++) {
				section = stripeFooter.streams(streamIx);
				std::cout << "    Stream: column " << section.column()  << " section "
						  << section.kind() << " start: " << sectionStart << " length " << section.length() << std::endl;
				sectionStart += section.length();
			};
			for (int columnIx=0; columnIx<stripeFooter.columns_size(); columnIx++) {
				encoding = stripeFooter.columns(columnIx);
				std::cout << "    Encoding column " << columnIx << ": " << encoding.kind() ;
				if (encoding.kind() == ColumnEncoding_Kind_DICTIONARY || encoding.kind() == ColumnEncoding_Kind_DICTIONARY_V2)
					std::cout << "[" << encoding.dictionarysize() << "]";
				std::cout << std::endl;
			};

			/*
	        if (!rowIndexCols.empty()) {
	        	std::vector<RowIndex> indices;
	        	long offset = stripeStart;

	        	stripeFooter = readStripeFooter(stripe);

	        	for(int streamIx=0; streamIx< stripeFooter.streams_size();streamIx++) {
	        		section = stripeFooter.streams(streamIx);
	        		if (section.kind() == Stream_Kind_ROW_INDEX) {
	        			int col = section.column();

	        			int streamLength = section.length();
	        			char* bufferRowIndex = new char[streamLength];
	        			input.seekg(offset);
	        			input.read(bufferRowIndex, streamLength);
	        			RowIndex rowIndex;
	        			rowIndex.ParseFromArray(bufferRowIndex, streamLength);
	        			delete[] bufferRowIndex ;
	        			indices.push_back(rowIndex);
	        		};
	        		offset += section.length();
	        	};

	        	for (int rowIx = 0; rowIx < rowIndexCols.size(); rowIx++) {
	        		int col = rowIndexCols[rowIx];
	        		std::cout << "    Row group index column " << col << ":" ;
	        		if (col >= indices.size())  {
	        			std::cout << " not found" << std::endl ;
	        			continue;
	        		};
	        		RowIndex index = indices[col];
	        		for (int entryIx = 0; entryIx < index.entry_size(); ++entryIx) {
	        			std::cout << "\n      Entry " << entryIx << ":";
	        			RowIndexEntry entry = index.entry(entryIx);
	        			ColumnStatistics colStats = entry.statistics();
	        			std::cout << " number of values: " << colStats.numberofvalues() ;
	        			for (int posIx = 0; posIx < entry.positions_size(); ++posIx) {
	        				if (posIx != 0)
	        					std::cout << ",";
	        				std::cout << entry.positions(posIx);
	        			};
	        		};
	        		std::cout <<std::endl ;
	        	};
	        };*/
		};

		long paddedBytes = getTotalPaddingSize(footer);
		// empty ORC file is ~45 bytes. Assumption here is file length always >0
		double percentPadding = ((double) paddedBytes / (double) fileSize) * 100;
		std::cout << "File length: " << fileSize << " bytes" << std::endl;
		std::cout <<"Padding length: " << paddedBytes << " bytes" << std::endl;
		std::cout <<"Padding ratio: " << std::fixed << std::setprecision(2) << percentPadding << " %" << std::endl;

		input.close();
	};

	google::protobuf::ShutdownProtobufLibrary();

    return 0;
}

StripeFooter readStripeFooter(StripeInformation stripe) {
	long offset = stripe.offset() + stripe.indexlength() + stripe.datalength();
	int tailLength = (int) stripe.footerlength();

	char* buffer = new char[tailLength];
	input.seekg(offset);
	input.read(buffer, tailLength);
	StripeFooter stripeFooter ;
	stripeFooter.ParseFromArray(buffer, tailLength);
	delete[] buffer;

	return stripeFooter;
}

long getTotalPaddingSize(Footer footer) {
	long paddedBytes = 0;
	StripeInformation stripe;
	for (int stripeIx=1; stripeIx<footer.stripes_size(); stripeIx++) {
		stripe = footer.stripes(stripeIx-1);
		long prevStripeOffset = stripe.offset();
		long prevStripeLen = stripe.datalength() + stripe.indexlength() + stripe.footerlength();
		paddedBytes += footer.stripes(stripeIx).offset() - (prevStripeOffset + prevStripeLen);
	};
	return paddedBytes;
}

<|endoftext|>


<commit_before>/*
 * LoggingEvent.cpp
 *
 * Copyright 2000, LifeLine Networks BV (www.lifeline.nl). All rights reserved.
 * Copyright 2000, Bastiaan Bakker. All rights reserved.
 *
 * See the COPYING file for the terms of usage and distribution.
 */

#include "log4cpp/LoggingEvent.hh"

namespace log4cpp {

    LoggingEvent::LoggingEvent(const std::string& categoryName,
                               const std::string& message,
                               const std::string& ndc, int priority) :
        categoryName(categoryName),
        message(message),
        ndc(ndc),
        priority(priority),
        threadName("thread1"),
        timeStamp(::time(NULL)) {
    }
}
<commit_msg>Type of priority is Priority::Value.<commit_after>/*
 * LoggingEvent.cpp
 *
 * Copyright 2000, LifeLine Networks BV (www.lifeline.nl). All rights reserved.
 * Copyright 2000, Bastiaan Bakker. All rights reserved.
 *
 * See the COPYING file for the terms of usage and distribution.
 */

#include "log4cpp/LoggingEvent.hh"

namespace log4cpp {

    LoggingEvent::LoggingEvent(const std::string& categoryName,
                               const std::string& message,
                               const std::string& ndc,
                               Priority::Value priority) :
        categoryName(categoryName),
        message(message),
        ndc(ndc),
        priority(priority),
        threadName("thread1"),
        timeStamp(::time(NULL)) {
    }
}
<|endoftext|>


<commit_before>#include "BLEHIDReportMapCharacteristic.h"

BLEHIDReportMapCharacteristic::BLEHIDReportMapCharacteristic() :
  BLEConstantCharacteristic("2a4b", NULL, 0),
  _devices(NULL),
  _numDevices(0)
{

}

unsigned char BLEHIDReportMapCharacteristic::valueSize() const {
  unsigned char valueSize = 0;

  for (unsigned char i = 0; i < this->_numDevices; i++) {
    valueSize += this->_devices[i]->getDescriptorLength();
  }

  return valueSize;
}

unsigned char BLEHIDReportMapCharacteristic::valueLength() const {
  return this->valueSize();
}

unsigned char BLEHIDReportMapCharacteristic::operator[] (int offset) const {
  unsigned char value = 0x00;
  unsigned char totalOffset = 0;

  for (unsigned char i = 0; i < this->_numDevices; i++) {
    unsigned char descriptorLength = this->_devices[i]->getDescriptorLength();

    if ((offset >= totalOffset) && (offset < (totalOffset + descriptorLength))) {
      value = this->_devices[i]->getDescriptorValueAtOffset(offset - totalOffset);
      break;
    }

    totalOffset = descriptorLength;
  }

  return value;
}

void BLEHIDReportMapCharacteristic::setDevices(BLEHIDDevice** devices, unsigned char numDevices) {
  this->_devices = devices;
  this->_numDevices = numDevices;
}
<commit_msg>- correct total offset calculations<commit_after>#include "BLEHIDReportMapCharacteristic.h"

BLEHIDReportMapCharacteristic::BLEHIDReportMapCharacteristic() :
  BLEConstantCharacteristic("2a4b", NULL, 0),
  _devices(NULL),
  _numDevices(0)
{

}

unsigned char BLEHIDReportMapCharacteristic::valueSize() const {
  unsigned char valueSize = 0;

  for (unsigned char i = 0; i < this->_numDevices; i++) {
    valueSize += this->_devices[i]->getDescriptorLength();
  }

  return valueSize;
}

unsigned char BLEHIDReportMapCharacteristic::valueLength() const {
  return this->valueSize();
}

unsigned char BLEHIDReportMapCharacteristic::operator[] (int offset) const {
  unsigned char value = 0x00;
  unsigned char totalOffset = 0;

  for (unsigned char i = 0; i < this->_numDevices; i++) {
    unsigned char descriptorLength = this->_devices[i]->getDescriptorLength();

    if ((offset >= totalOffset) && (offset < (totalOffset + descriptorLength))) {
      value = this->_devices[i]->getDescriptorValueAtOffset(offset - totalOffset);
      break;
    }

    totalOffset += descriptorLength;
  }

  return value;
}

void BLEHIDReportMapCharacteristic::setDevices(BLEHIDDevice** devices, unsigned char numDevices) {
  this->_devices = devices;
  this->_numDevices = numDevices;
}
<|endoftext|>


<commit_before>#include "WaterObject.hpp"

#include "MPACK.hpp"
#include "Render.hpp"
#include "DemoApplication.hpp"
#include "Context.hpp"
#include <cassert>

using namespace MPACK;
using namespace MPACK::Math;
using namespace MPACK::Graphics;

const Vector2f WaterObject::s_targetHeight = Vector2f(0.f, 300.f);
const float	WaterObject::s_dampening = 0.1f;
const int WaterObject::m_springsCount = 201;
WaterObject* WaterObject::g_water = nullptr;

WaterObject::WaterObject()
	: m_spread(0.25f)
{

	CreateSprings();

	m_pWhiteTexture = new Texture2D;
	m_pWhiteTexture->Load("@Backgrounds/whitetexture.png");
	m_pWhiteTexture->SetWrapMode(GL_REPEAT, GL_REPEAT);

	/// create dem positions regarding to screen width
}

void WaterObject::CreateSprings()
{
	m_springs.reserve(m_springsCount);

	float step = 1.f * Render::GetScreenWidth() / (m_springsCount - 1);

	for (int i = 0; i < m_springsCount; ++ i)
	{
		WaterSpring currentSpring;
		currentSpring.m_position.x = i*step;
		m_springs.push_back(currentSpring);
	}
}

void WaterObject::CreateWavesVertices()
{
	for (int i = 1; i < m_springs.size(); ++ i)
	{
		SpriteVertex vertices[3];
		GLushort indices[3];

		for (int j = 0; j < 3; ++ j) indices[j] = j;

		const float x1 = m_springs[i-1].m_position.x;
		const float x2 = m_springs[i].m_position.x;
		const float y1 = m_springs[i-1].m_position.y;
		const float y2 = m_springs[i].m_position.y;

		//LOGI("%lf %lf %lf %lf", x1, y1, x2, y2);
		const float downCoord = Render::GetScreenHeight();

		//LOGI("%f", downCoord);

		vertices[0] = SpriteVertex(x1, downCoord, 0.f, 0.f, 0.f, 0.f, 0.f, 0.7f, SpriteVertex::ALPHA_BLEND);
		vertices[1] = SpriteVertex(x2, downCoord - y2, 1.f, 0.f, 0.f, 0.f, 1.f, 0.5f, SpriteVertex::ALPHA_BLEND);
		vertices[2] = SpriteVertex(x1, downCoord - y1, 0.f, 1.f, 0.f, 0.f, 1.f, 0.5f, SpriteVertex::ALPHA_BLEND);

		Batcher::SendSpriteVertexData(vertices, 3, indices, 3, m_pWhiteTexture, IndexData::TRIANGLES, 0.f);

		vertices[2] = SpriteVertex(x2, downCoord - y2, 1.f, 0.f, 0.f, 0.f, 1.f, 0.5f, SpriteVertex::ALPHA_BLEND);
		vertices[0] = SpriteVertex(x1, downCoord, 0.f, 0.f, 0.f, 0.f, 0.f, 0.7f, SpriteVertex::ALPHA_BLEND);
		vertices[1] = SpriteVertex(x2, downCoord, 0.f, 1.f, 0.f, 0.f, 0.f, 0.7f, SpriteVertex::ALPHA_BLEND);

		Batcher::SendSpriteVertexData(vertices, 3, indices, 3, m_pWhiteTexture, IndexData::TRIANGLES, 0.f);
	}

}

void WaterObject::Update(float dtime)
{
	for (auto &spring : m_springs)
		spring.Update(dtime);

	Vector2f leftDeltas[m_springs.size()];
	Vector2f rightDeltas[m_springs.size()];

	for (int i = 0; i < m_springs.size(); ++ i)
		leftDeltas[i] = rightDeltas[i] = Vector2f(0.f, 0.f);

	for (int j = 0; j < 8; j++)
	{
	    for (int i = 0; i < m_springs.size(); ++ i)
	    {
	        if (i > 0)
	        {
	            leftDeltas[i] = (m_springs[i].m_position - m_springs[i - 1].m_position) * m_spread;
	            m_springs[i - 1].m_velocity.y += leftDeltas[i].y; //
	        }
	        if (i < m_springs.size() - 1)
	        {
	            rightDeltas[i] = (m_springs[i].m_position - m_springs[i + 1].m_position) * m_spread;
	            m_springs[i + 1].m_velocity.y += rightDeltas[i].y;
	        }
	    }

	    for (int i = 0; i < m_springs.size(); ++ i)
	    {
	        if (i > 0)
	            m_springs[i - 1].m_position.y += leftDeltas[i].y;
	        if (i < m_springs.size() - 1)
	        	m_springs[i + 1].m_position.y += rightDeltas[i].y;
	    }
	}
}

void WaterObject::Render()
{
	CreateWavesVertices();
}

int WaterObject::GetSpringsCount()
{
	return m_springsCount;
}

void WaterObject::Splash(int index, Vector2f velocity)
{
	if (!(0 <= index && index < m_springs.size()))
		return ;
	m_springs[index].m_velocity = velocity;
}

void WaterObject::ClickSplash(Vector2f pos)
{
	int index;
	if (pos.x < 0.f) index = 0;
	else if (pos.x > Render::GetScreenWidth()) index = m_springsCount;
	else
	{
		index = pos.x * m_springsCount / Render::GetScreenWidth();
	}
	Splash(index, Vector2f(0.f, 500.f));
}

WaterObject::~WaterObject()
{

	delete m_pWhiteTexture;

}
<commit_msg>adjusted spread<commit_after>#include "WaterObject.hpp"

#include "MPACK.hpp"
#include "Render.hpp"
#include "DemoApplication.hpp"
#include "Context.hpp"
#include <cassert>

using namespace MPACK;
using namespace MPACK::Math;
using namespace MPACK::Graphics;

const Vector2f WaterObject::s_targetHeight = Vector2f(0.f, 300.f);
const float	WaterObject::s_dampening = 0.1f;
const int WaterObject::m_springsCount = 201;
WaterObject* WaterObject::g_water = nullptr;

WaterObject::WaterObject()
	: m_spread(0.4f)
{

	CreateSprings();

	m_pWhiteTexture = new Texture2D;
	m_pWhiteTexture->Load("@Backgrounds/whitetexture.png");
	m_pWhiteTexture->SetWrapMode(GL_REPEAT, GL_REPEAT);

	/// create dem positions regarding to screen width
}

void WaterObject::CreateSprings()
{
	m_springs.reserve(m_springsCount);

	float step = 1.f * Render::GetScreenWidth() / (m_springsCount - 1);

	for (int i = 0; i < m_springsCount; ++ i)
	{
		WaterSpring currentSpring;
		currentSpring.m_position.x = i*step;
		m_springs.push_back(currentSpring);
	}
}

void WaterObject::CreateWavesVertices()
{
	for (int i = 1; i < m_springs.size(); ++ i)
	{
		SpriteVertex vertices[3];
		GLushort indices[3];

		for (int j = 0; j < 3; ++ j) indices[j] = j;

		const float x1 = m_springs[i-1].m_position.x;
		const float x2 = m_springs[i].m_position.x;
		const float y1 = m_springs[i-1].m_position.y;
		const float y2 = m_springs[i].m_position.y;

		//LOGI("%lf %lf %lf %lf", x1, y1, x2, y2);
		const float downCoord = Render::GetScreenHeight();

		//LOGI("%f", downCoord);

		vertices[0] = SpriteVertex(x1, downCoord, 0.f, 0.f, 0.f, 0.f, 0.f, 0.7f, SpriteVertex::ALPHA_BLEND);
		vertices[1] = SpriteVertex(x2, downCoord - y2, 1.f, 0.f, 0.f, 0.f, 1.f, 0.5f, SpriteVertex::ALPHA_BLEND);
		vertices[2] = SpriteVertex(x1, downCoord - y1, 0.f, 1.f, 0.f, 0.f, 1.f, 0.5f, SpriteVertex::ALPHA_BLEND);

		Batcher::SendSpriteVertexData(vertices, 3, indices, 3, m_pWhiteTexture, IndexData::TRIANGLES, 0.f);

		vertices[2] = SpriteVertex(x2, downCoord - y2, 1.f, 0.f, 0.f, 0.f, 1.f, 0.5f, SpriteVertex::ALPHA_BLEND);
		vertices[0] = SpriteVertex(x1, downCoord, 0.f, 0.f, 0.f, 0.f, 0.f, 0.7f, SpriteVertex::ALPHA_BLEND);
		vertices[1] = SpriteVertex(x2, downCoord, 0.f, 1.f, 0.f, 0.f, 0.f, 0.7f, SpriteVertex::ALPHA_BLEND);

		Batcher::SendSpriteVertexData(vertices, 3, indices, 3, m_pWhiteTexture, IndexData::TRIANGLES, 0.f);
	}

}

void WaterObject::Update(float dtime)
{
	for (auto &spring : m_springs)
		spring.Update(dtime);

	Vector2f leftDeltas[m_springs.size()];
	Vector2f rightDeltas[m_springs.size()];

	for (int i = 0; i < m_springs.size(); ++ i)
		leftDeltas[i] = rightDeltas[i] = Vector2f(0.f, 0.f);

	for (int j = 0; j < 8; j++)
	{
	    for (int i = 0; i < m_springs.size(); ++ i)
	    {
	        if (i > 0)
	        {
	            leftDeltas[i] = (m_springs[i].m_position - m_springs[i - 1].m_position) * m_spread;
	            m_springs[i - 1].m_velocity.y += leftDeltas[i].y; //
	        }
	        if (i < m_springs.size() - 1)
	        {
	            rightDeltas[i] = (m_springs[i].m_position - m_springs[i + 1].m_position) * m_spread;
	            m_springs[i + 1].m_velocity.y += rightDeltas[i].y;
	        }
	    }

	    for (int i = 0; i < m_springs.size(); ++ i)
	    {
	        if (i > 0)
	            m_springs[i - 1].m_position.y += leftDeltas[i].y;
	        if (i < m_springs.size() - 1)
	        	m_springs[i + 1].m_position.y += rightDeltas[i].y;
	    }
	}
}

void WaterObject::Render()
{
	CreateWavesVertices();
}

int WaterObject::GetSpringsCount()
{
	return m_springsCount;
}

void WaterObject::Splash(int index, Vector2f velocity)
{
	if (!(0 <= index && index < m_springs.size()))
		return ;
	m_springs[index].m_velocity = velocity;
}

void WaterObject::ClickSplash(Vector2f pos)
{
	int index;
	if (pos.x < 0.f) index = 0;
	else if (pos.x > Render::GetScreenWidth()) index = m_springsCount;
	else
	{
		index = pos.x * m_springsCount / Render::GetScreenWidth();
	}
	Splash(index, Vector2f(0.f, 500.f));
}

WaterObject::~WaterObject()
{

	delete m_pWhiteTexture;

}
<|endoftext|>


<commit_before>//
// Matrix/macro.hpp
// ~~~~~~~~~~~~~~~~
//
// Copyright (c) 2014 Rick Yang (rick68 at gmail dot com)
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
//

#ifndef EIGENJS_MATRIX_MACRO_HPP
#define EIGENJS_MATRIX_MACRO_HPP

#include <v8.h>
#include <node.h>
#include <nan.h>

#include <boost/preprocessor/cat.hpp>

#include "../throw_error.hpp"
#include "../detail/add_complex.hpp"

#define EIGENJS_MATRIX_BINARY_OPERATOR_CONTEXT( OP )                         \
  {                                                                          \
    NanScope();                                                              \
                                                                             \
    if ( args.Length() == 1 ) {                                              \
      const T* const& obj =                                                  \
          node::ObjectWrap::Unwrap< T >( args.This() );                      \
      const typename T::value_type& value = **obj;                           \
      const typename T::value_type::Index& rows = value.rows();              \
      const typename T::value_type::Index& cols = value.cols();              \
      v8::Local<v8::Value> argv[] = {                                        \
        NanNew<v8::Integer>( rows )                                          \
      , NanNew<v8::Integer>( cols )                                          \
      };                                                                     \
                                                                             \
      if ( Matrix::is_matrix( args[0] ) ) {                                  \
        const Matrix* const& rhs_obj =                                       \
            node::ObjectWrap::Unwrap< Matrix >( args[0]->ToObject() );       \
        const typename Matrix::value_type& rhs_matrix = **rhs_obj;           \
                                                                             \
        if ( T::is_nonconformate_arguments( obj, rhs_obj ) ) {               \
          NanReturnUndefined();                                              \
        }                                                                    \
                                                                             \
        v8::Local< v8::Object > instance = U::new_instance(                  \
          args                                                               \
        , sizeof( argv ) / sizeof( v8::Local< v8::Value > )                  \
        , argv                                                               \
        );                                                                   \
                                                                             \
        U* new_obj = node::ObjectWrap::Unwrap< U >( instance );              \
        typename U::value_type& new_value = **new_obj;                       \
                                                                             \
        new_value = value OP rhs_matrix;                                     \
                                                                             \
        NanReturnValue( instance );                                          \
      } else if ( Vector::is_vector( args[0] ) ) {                           \
        const Vector* const& rhs_obj =                                       \
            node::ObjectWrap::Unwrap< Vector >( args[0]->ToObject() );       \
        const typename Vector::value_type& rhs_vector = **rhs_obj;           \
                                                                             \
        if ( T::is_nonconformate_arguments( obj, rhs_obj ) ) {               \
          NanReturnUndefined();                                              \
        }                                                                    \
                                                                             \
        v8::Local< v8::Object > instance = U::new_instance(                  \
          args                                                               \
        , sizeof( argv ) / sizeof( v8::Local< v8::Value > )                  \
        , argv                                                               \
        );                                                                   \
                                                                             \
        U* new_obj = node::ObjectWrap::Unwrap< U >( instance );              \
        typename U::value_type& new_value = **new_obj;                       \
                                                                             \
        new_value = value OP rhs_vector;                                     \
                                                                             \
        NanReturnValue( instance );                                          \
      } else if ( RowVector::is_rowvector( args[0] ) ) {                     \
        const RowVector* const& rhs_obj =                                    \
            node::ObjectWrap::Unwrap< RowVector >( args[0]->ToObject() );    \
        const typename RowVector::value_type& rhs_rowvector = **rhs_obj;     \
                                                                             \
        if ( T::is_nonconformate_arguments( obj, rhs_obj ) ) {               \
          NanReturnUndefined();                                              \
        }                                                                    \
                                                                             \
        v8::Local< v8::Object > instance = U::new_instance(                  \
          args                                                               \
        , sizeof( argv ) / sizeof( v8::Local< v8::Value > )                  \
        , argv                                                               \
        );                                                                   \
                                                                             \
        U* new_obj = node::ObjectWrap::Unwrap< U >( instance );              \
        typename U::value_type& new_value = **new_obj;                       \
                                                                             \
        new_value = value OP rhs_rowvector;                                  \
                                                                             \
        NanReturnValue( instance );                                          \
      } else if ( CMatrix::is_cmatrix( args[0]) ) {                          \
        const CMatrix* const& rhs_obj =                                      \
            node::ObjectWrap::Unwrap< CMatrix >( args[0]->ToObject() );      \
        const typename CMatrix::value_type& rhs_cmatrix = **rhs_obj;         \
                                                                             \
        if ( T::is_nonconformate_arguments( obj, rhs_obj ) ) {               \
          NanReturnUndefined();                                              \
        }                                                                    \
                                                                             \
        typedef typename detail::add_complex<U>::type CU;                    \
                                                                             \
        v8::Local< v8::Object > instance = CU::new_instance(                 \
          args                                                               \
        , sizeof( argv ) / sizeof( v8::Local< v8::Value > )                  \
        , argv                                                               \
        );                                                                   \
                                                                             \
        CU* new_obj = node::ObjectWrap::Unwrap< CU >( instance );            \
        typename CU::value_type& new_value = **new_obj;                      \
                                                                             \
        new_value =                                                          \
          value.template cast< typename Complex::value_type >()              \
            OP                                                               \
          rhs_cmatrix;                                                       \
                                                                             \
        NanReturnValue( instance );                                          \
      } else if ( CVector::is_cvector( args[0]) ) {                          \
        const CVector* const& rhs_obj =                                      \
            node::ObjectWrap::Unwrap< CVector >( args[0]->ToObject() );      \
        const typename CVector::value_type& rhs_cvector = **rhs_obj;         \
                                                                             \
        if ( T::is_nonconformate_arguments( obj, rhs_obj ) ) {               \
          NanReturnUndefined();                                              \
        }                                                                    \
                                                                             \
        typedef typename detail::add_complex<U>::type CU;                    \
                                                                             \
        v8::Local< v8::Object > instance = CU::new_instance(                 \
          args                                                               \
        , sizeof( argv ) / sizeof( v8::Local< v8::Value > )                  \
        , argv                                                               \
        );                                                                   \
                                                                             \
        CU* new_obj = node::ObjectWrap::Unwrap< CU >( instance );            \
        typename CU::value_type& new_value = **new_obj;                      \
                                                                             \
        new_value =                                                          \
          value.template cast< typename Complex::value_type >()              \
            OP                                                               \
          rhs_cvector;                                                       \
                                                                             \
        NanReturnValue( instance );                                          \
      } else if ( CRowVector::is_crowvector( args[0] ) ) {                   \
        const CRowVector* const& rhs_obj =                                   \
            node::ObjectWrap::Unwrap< CRowVector >( args[0]->ToObject() );   \
        const typename CRowVector::value_type& rhs_crowvector = **rhs_obj;   \
                                                                             \
        if ( T::is_nonconformate_arguments( obj, rhs_obj ) ) {               \
          NanReturnUndefined();                                              \
        }                                                                    \
                                                                             \
        typedef typename detail::add_complex<U>::type CU;                    \
                                                                             \
        v8::Local< v8::Object > instance = CU::new_instance(                 \
          args                                                               \
        , sizeof( argv ) / sizeof( v8::Local< v8::Value > )                  \
        , argv                                                               \
        );                                                                   \
                                                                             \
        CU* new_obj = node::ObjectWrap::Unwrap< CU >( instance );            \
        typename CU::value_type& new_value = **new_obj;                      \
                                                                             \
        new_value =                                                          \
          value.template cast< typename Complex::value_type >()              \
            OP                                                               \
          rhs_crowvector;                                                    \
                                                                             \
        NanReturnValue( instance );                                          \
      }                                                                      \
    }                                                                        \
                                                                             \
    EIGENJS_THROW_ERROR_INVALID_ARGUMENT()                                   \
    NanReturnUndefined();                                                    \
  }                                                                          \
  /**/

#define EIGENJS_MATRIX_BINARY_OPERATOR_COMMUTATIVE_CONTEXT( OP )             \
  {                                                                          \
    NanScope();                                                              \
                                                                             \
    if ( args.Length() == 1) {                                               \
      T* obj = node::ObjectWrap::Unwrap< T >( args.This() );                 \
      typename T::value_type& value = **obj;                                 \
                                                                             \
      if ( Matrix::is_matrix( args[0] ) ) {                                  \
        const Matrix* const& rhs_obj =                                       \
            node::ObjectWrap::Unwrap< Matrix >( args[0]->ToObject() );       \
        const typename Matrix::value_type& rhs_matrix = **rhs_obj;           \
                                                                             \
        if ( T::is_nonconformate_arguments( obj, rhs_obj ) ) {               \
          NanReturnUndefined();                                              \
        }                                                                    \
                                                                             \
        value BOOST_PP_CAT( OP, = ) rhs_matrix;                              \
                                                                             \
        NanReturnValue( args.This() );                                       \
      } else if ( Vector::is_vector( args[0] ) ) {                           \
        const Vector* const& rhs_obj =                                       \
            node::ObjectWrap::Unwrap< Vector >( args[0]->ToObject() );       \
        const typename Vector::value_type& rhs_vector = **rhs_obj;           \
                                                                             \
        if ( T::is_nonconformate_arguments( obj, rhs_obj ) ) {               \
          NanReturnUndefined();                                              \
        }                                                                    \
                                                                             \
        value BOOST_PP_CAT( OP, = ) rhs_vector;                              \
                                                                             \
        NanReturnValue( args.This() );                                       \
      } else if ( RowVector::is_rowvector( args[0] ) ) {                     \
        const RowVector* const& rhs_obj =                                    \
            node::ObjectWrap::Unwrap< RowVector >( args[0]->ToObject() );    \
        const typename RowVector::value_type& rhs_rowvector = **rhs_obj;     \
                                                                             \
        if ( T::is_nonconformate_arguments( obj, rhs_obj ) ) {               \
          NanReturnUndefined();                                              \
        }                                                                    \
                                                                             \
        value BOOST_PP_CAT( OP, = ) rhs_rowvector;                           \
                                                                             \
        NanReturnValue( args.This() );                                       \
      }                                                                      \
    }                                                                        \
                                                                             \
    EIGENJS_THROW_ERROR_INVALID_ARGUMENT()                                   \
    NanReturnUndefined();                                                    \
  }                                                                          \
  /**/

#endif  // EIGENJS_MATRIX_MACRO_HPP
<commit_msg>src: support MatrixBlock and CMatrixBlock<commit_after>//
// Matrix/macro.hpp
// ~~~~~~~~~~~~~~~~
//
// Copyright (c) 2014 Rick Yang (rick68 at gmail dot com)
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
//

#ifndef EIGENJS_MATRIX_MACRO_HPP
#define EIGENJS_MATRIX_MACRO_HPP

#include <v8.h>
#include <node.h>
#include <nan.h>

#include <boost/preprocessor/cat.hpp>

#include "../throw_error.hpp"
#include "../detail/add_complex.hpp"

#define EIGENJS_MATRIX_BINARY_OPERATOR_CONTEXT( OP )                         \
  {                                                                          \
    NanScope();                                                              \
                                                                             \
    if ( args.Length() == 1 ) {                                              \
      const T* const& obj =                                                  \
          node::ObjectWrap::Unwrap< T >( args.This() );                      \
      const typename T::value_type& value = **obj;                           \
      const typename T::value_type::Index& rows = value.rows();              \
      const typename T::value_type::Index& cols = value.cols();              \
      v8::Local<v8::Value> argv[] = {                                        \
        NanNew<v8::Integer>( rows )                                          \
      , NanNew<v8::Integer>( cols )                                          \
      };                                                                     \
                                                                             \
      if ( Matrix::is_matrix( args[0] ) ) {                                  \
        const Matrix* const& rhs_obj =                                       \
            node::ObjectWrap::Unwrap< Matrix >( args[0]->ToObject() );       \
        const typename Matrix::value_type& rhs_matrix = **rhs_obj;           \
                                                                             \
        if ( T::is_nonconformate_arguments( obj, rhs_obj ) ) {               \
          NanReturnUndefined();                                              \
        }                                                                    \
                                                                             \
        v8::Local< v8::Object > instance = U::new_instance(                  \
          args                                                               \
        , sizeof( argv ) / sizeof( v8::Local< v8::Value > )                  \
        , argv                                                               \
        );                                                                   \
                                                                             \
        U* new_obj = node::ObjectWrap::Unwrap< U >( instance );              \
        typename U::value_type& new_value = **new_obj;                       \
                                                                             \
        new_value = value OP rhs_matrix;                                     \
                                                                             \
        NanReturnValue( instance );                                          \
      } else if ( Vector::is_vector( args[0] ) ) {                           \
        const Vector* const& rhs_obj =                                       \
            node::ObjectWrap::Unwrap< Vector >( args[0]->ToObject() );       \
        const typename Vector::value_type& rhs_vector = **rhs_obj;           \
                                                                             \
        if ( T::is_nonconformate_arguments( obj, rhs_obj ) ) {               \
          NanReturnUndefined();                                              \
        }                                                                    \
                                                                             \
        v8::Local< v8::Object > instance = U::new_instance(                  \
          args                                                               \
        , sizeof( argv ) / sizeof( v8::Local< v8::Value > )                  \
        , argv                                                               \
        );                                                                   \
                                                                             \
        U* new_obj = node::ObjectWrap::Unwrap< U >( instance );              \
        typename U::value_type& new_value = **new_obj;                       \
                                                                             \
        new_value = value OP rhs_vector;                                     \
                                                                             \
        NanReturnValue( instance );                                          \
      } else if ( RowVector::is_rowvector( args[0] ) ) {                     \
        const RowVector* const& rhs_obj =                                    \
            node::ObjectWrap::Unwrap< RowVector >( args[0]->ToObject() );    \
        const typename RowVector::value_type& rhs_rowvector = **rhs_obj;     \
                                                                             \
        if ( T::is_nonconformate_arguments( obj, rhs_obj ) ) {               \
          NanReturnUndefined();                                              \
        }                                                                    \
                                                                             \
        v8::Local< v8::Object > instance = U::new_instance(                  \
          args                                                               \
        , sizeof( argv ) / sizeof( v8::Local< v8::Value > )                  \
        , argv                                                               \
        );                                                                   \
                                                                             \
        U* new_obj = node::ObjectWrap::Unwrap< U >( instance );              \
        typename U::value_type& new_value = **new_obj;                       \
                                                                             \
        new_value = value OP rhs_rowvector;                                  \
                                                                             \
        NanReturnValue( instance );                                          \
      } else if ( MatrixBlock::is_matrixblock( args[0] ) ) {                 \
        const MatrixBlock* const& rhs_obj =                                  \
            node::ObjectWrap::Unwrap< MatrixBlock >( args[0]->ToObject() );  \
        const typename MatrixBlock::value_type& rhs_matrixblock = **rhs_obj; \
                                                                             \
        if ( T::is_nonconformate_arguments( obj, rhs_obj ) ) {               \
          NanReturnUndefined();                                              \
        }                                                                    \
                                                                             \
        v8::Local< v8::Object > instance = U::new_instance(                  \
          args                                                               \
        , sizeof( argv ) / sizeof( v8::Local< v8::Value > )                  \
        , argv                                                               \
        );                                                                   \
                                                                             \
        U* new_obj = node::ObjectWrap::Unwrap< U >( instance );              \
        typename U::value_type& new_value = **new_obj;                       \
                                                                             \
        new_value = value OP rhs_matrixblock;                                \
                                                                             \
        NanReturnValue( instance );                                          \
      } else if ( CMatrix::is_cmatrix( args[0]) ) {                          \
        const CMatrix* const& rhs_obj =                                      \
            node::ObjectWrap::Unwrap< CMatrix >( args[0]->ToObject() );      \
        const typename CMatrix::value_type& rhs_cmatrix = **rhs_obj;         \
                                                                             \
        if ( T::is_nonconformate_arguments( obj, rhs_obj ) ) {               \
          NanReturnUndefined();                                              \
        }                                                                    \
                                                                             \
        typedef typename detail::add_complex<U>::type CU;                    \
                                                                             \
        v8::Local< v8::Object > instance = CU::new_instance(                 \
          args                                                               \
        , sizeof( argv ) / sizeof( v8::Local< v8::Value > )                  \
        , argv                                                               \
        );                                                                   \
                                                                             \
        CU* new_obj = node::ObjectWrap::Unwrap< CU >( instance );            \
        typename CU::value_type& new_value = **new_obj;                      \
                                                                             \
        new_value =                                                          \
          value.template cast< typename Complex::value_type >()              \
            OP                                                               \
          rhs_cmatrix;                                                       \
                                                                             \
        NanReturnValue( instance );                                          \
      } else if ( CVector::is_cvector( args[0]) ) {                          \
        const CVector* const& rhs_obj =                                      \
            node::ObjectWrap::Unwrap< CVector >( args[0]->ToObject() );      \
        const typename CVector::value_type& rhs_cvector = **rhs_obj;         \
                                                                             \
        if ( T::is_nonconformate_arguments( obj, rhs_obj ) ) {               \
          NanReturnUndefined();                                              \
        }                                                                    \
                                                                             \
        typedef typename detail::add_complex<U>::type CU;                    \
                                                                             \
        v8::Local< v8::Object > instance = CU::new_instance(                 \
          args                                                               \
        , sizeof( argv ) / sizeof( v8::Local< v8::Value > )                  \
        , argv                                                               \
        );                                                                   \
                                                                             \
        CU* new_obj = node::ObjectWrap::Unwrap< CU >( instance );            \
        typename CU::value_type& new_value = **new_obj;                      \
                                                                             \
        new_value =                                                          \
          value.template cast< typename Complex::value_type >()              \
            OP                                                               \
          rhs_cvector;                                                       \
                                                                             \
        NanReturnValue( instance );                                          \
      } else if ( CRowVector::is_crowvector( args[0] ) ) {                   \
        const CRowVector* const& rhs_obj =                                   \
            node::ObjectWrap::Unwrap< CRowVector >( args[0]->ToObject() );   \
        const typename CRowVector::value_type& rhs_crowvector = **rhs_obj;   \
                                                                             \
        if ( T::is_nonconformate_arguments( obj, rhs_obj ) ) {               \
          NanReturnUndefined();                                              \
        }                                                                    \
                                                                             \
        typedef typename detail::add_complex<U>::type CU;                    \
                                                                             \
        v8::Local< v8::Object > instance = CU::new_instance(                 \
          args                                                               \
        , sizeof( argv ) / sizeof( v8::Local< v8::Value > )                  \
        , argv                                                               \
        );                                                                   \
                                                                             \
        CU* new_obj = node::ObjectWrap::Unwrap< CU >( instance );            \
        typename CU::value_type& new_value = **new_obj;                      \
                                                                             \
        new_value =                                                          \
          value.template cast< typename Complex::value_type >()              \
            OP                                                               \
          rhs_crowvector;                                                    \
                                                                             \
        NanReturnValue( instance );                                          \
      } else if ( CMatrixBlock::is_cmatrixblock( args[0] ) ) {               \
        const CMatrixBlock* const& rhs_obj =                                 \
            node::ObjectWrap::Unwrap< CMatrixBlock >( args[0]->ToObject() ); \
        const typename CMatrixBlock::value_type& rhs_cmatrixblock =          \
            **rhs_obj;                                                       \
                                                                             \
        if ( T::is_nonconformate_arguments( obj, rhs_obj ) ) {               \
          NanReturnUndefined();                                              \
        }                                                                    \
                                                                             \
        typedef typename detail::add_complex<U>::type CU;                    \
                                                                             \
        v8::Local< v8::Object > instance = CU::new_instance(                 \
          args                                                               \
        , sizeof( argv ) / sizeof( v8::Local< v8::Value > )                  \
        , argv                                                               \
        );                                                                   \
                                                                             \
        CU* new_obj = node::ObjectWrap::Unwrap< CU >( instance );            \
        typename CU::value_type& new_value = **new_obj;                      \
                                                                             \
        new_value =                                                          \
          value.template cast< typename Complex::value_type >()              \
            OP                                                               \
          rhs_cmatrixblock;                                                  \
                                                                             \
        NanReturnValue( instance );                                          \
      }                                                                      \
    }                                                                        \
                                                                             \
    EIGENJS_THROW_ERROR_INVALID_ARGUMENT()                                   \
    NanReturnUndefined();                                                    \
  }                                                                          \
  /**/

#define EIGENJS_MATRIX_BINARY_OPERATOR_COMMUTATIVE_CONTEXT( OP )             \
  {                                                                          \
    NanScope();                                                              \
                                                                             \
    if ( args.Length() == 1) {                                               \
      T* obj = node::ObjectWrap::Unwrap< T >( args.This() );                 \
      typename T::value_type& value = **obj;                                 \
                                                                             \
      if ( Matrix::is_matrix( args[0] ) ) {                                  \
        const Matrix* const& rhs_obj =                                       \
            node::ObjectWrap::Unwrap< Matrix >( args[0]->ToObject() );       \
        const typename Matrix::value_type& rhs_matrix = **rhs_obj;           \
                                                                             \
        if ( T::is_nonconformate_arguments( obj, rhs_obj ) ) {               \
          NanReturnUndefined();                                              \
        }                                                                    \
                                                                             \
        value BOOST_PP_CAT( OP, = ) rhs_matrix;                              \
                                                                             \
        NanReturnValue( args.This() );                                       \
      } else if ( Vector::is_vector( args[0] ) ) {                           \
        const Vector* const& rhs_obj =                                       \
            node::ObjectWrap::Unwrap< Vector >( args[0]->ToObject() );       \
        const typename Vector::value_type& rhs_vector = **rhs_obj;           \
                                                                             \
        if ( T::is_nonconformate_arguments( obj, rhs_obj ) ) {               \
          NanReturnUndefined();                                              \
        }                                                                    \
                                                                             \
        value BOOST_PP_CAT( OP, = ) rhs_vector;                              \
                                                                             \
        NanReturnValue( args.This() );                                       \
      } else if ( RowVector::is_rowvector( args[0] ) ) {                     \
        const RowVector* const& rhs_obj =                                    \
            node::ObjectWrap::Unwrap< RowVector >( args[0]->ToObject() );    \
        const typename RowVector::value_type& rhs_rowvector = **rhs_obj;     \
                                                                             \
        if ( T::is_nonconformate_arguments( obj, rhs_obj ) ) {               \
          NanReturnUndefined();                                              \
        }                                                                    \
                                                                             \
        value BOOST_PP_CAT( OP, = ) rhs_rowvector;                           \
                                                                             \
        NanReturnValue( args.This() );                                       \
      } else if ( MatrixBlock::is_matrixblock( args[0] ) ) {                 \
        const MatrixBlock* const& rhs_obj =                                  \
            node::ObjectWrap::Unwrap< MatrixBlock >( args[0]->ToObject() );  \
        const typename MatrixBlock::value_type& rhs_matrixblock = **rhs_obj; \
                                                                             \
        if ( T::is_nonconformate_arguments( obj, rhs_obj ) ) {               \
          NanReturnUndefined();                                              \
        }                                                                    \
                                                                             \
        value BOOST_PP_CAT( OP, = ) rhs_matrixblock;                         \
                                                                             \
        NanReturnValue( args.This() );                                       \
      }                                                                      \
    }                                                                        \
                                                                             \
    EIGENJS_THROW_ERROR_INVALID_ARGUMENT()                                   \
    NanReturnUndefined();                                                    \
  }                                                                          \
  /**/

#endif  // EIGENJS_MATRIX_MACRO_HPP
<|endoftext|>