<commit_before>#include <vector>
#include <string>
#include <set>

#include <math.h>
#include <matrix.h>
#include <mex.h>

#include "mex_helper.h"
#include "emd_flow.h"
#include "emd_flow_network_factory.h"

using namespace std;

void output_function(const char* s) {
  mexPrintf(s);
  mexEvalString("drawnow;");
}

void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) {
  if (nrhs < 3) {
    mexErrMsgTxt("At least three input argument required (amplitudes, sparsity,"
        " EMD budget.");
  }
  if (nlhs > 5) {
    mexErrMsgTxt("Too many output arguments.");
  }

  vector<vector<double> > a;
  if (!get_double_matrix(prhs[0], &a)) {
    mexErrMsgTxt("Amplitudes need to be a two-dimensional double array.");
  }

  int k = 0;
  if (!get_double_as_int(prhs[1], &k)) {
    mexErrMsgTxt("Sparsity has to be a double scalar.");
  }

  int emd_bound_low = 0;
  int emd_bound_high = 0;
  if (!get_double_as_int(prhs[2], &emd_bound_low)) {
    if (!get_double_interval_as_ints(prhs[2], &emd_bound_low,
        &emd_bound_high)) {
      mexErrMsgTxt("EMD budget has to be a double scalar or a double "
          "interval.");
    }
  } else {
    emd_bound_high = emd_bound_low;
  }

  // optional parameters
  bool verbose = false;
  double lambda_low = 1.0;
  double lambda_high = 1.0;
  int num_iter = 10;
  if (nrhs == 4) {
    set<string> known_options;
    known_options.insert("verbose");
    known_options.insert("lambda_low");
    known_options.insert("lambda_high");
    known_options.insert("num_iterations");
    vector<string> options;
    if (!get_fields(prhs[3], &options)) {
      mexErrMsgTxt("Cannot get fields from options argument.");
    }
    for (size_t ii = 0; ii < options.size(); ++ii) {
      if (known_options.find(options[ii]) == known_options.end()) {
        const size_t tmp_size = 1000;
        char tmp[tmp_size];
        snprintf(tmp, tmp_size, "Unknown option \"%s\"\n", options[ii].c_str());
        mexErrMsgTxt(tmp);
      }
    }

    if (has_field(prhs[3], "verbose")
        && !get_bool_field(prhs[3], "verbose", &verbose)) {
      mexErrMsgTxt("verbose flag has to be a boolean scalar.");
    }

    if (has_field(prhs[3], "lambda_low")
        && !get_double_field(prhs[3], "lambda_low", &lambda_low)) {
      mexErrMsgTxt("lambda_low field has to be a double scalar.");
    }

    if (has_field(prhs[3], "lambda_high")
        && !get_double_field(prhs[3], "lambda_high", &lambda_high)) {
      mexErrMsgTxt("lambda_high field has to be a double scalar.");
    }

    if (has_field(prhs[3], "num_iterations")
        && !get_double_field_as_int(prhs[3], "num_iterations", &num_iter)) {
      mexErrMsgTxt("num_iterations field has to be a double scalar.");
    }
  }

  emd_flow_args args(a);
  args.k = k;
  args.emd_bound_low = emd_bound_low;
  args.emd_bound_high = emd_bound_high;
  args.lambda_low = lambda_low;
  args.lambda_high = lambda_high;
  args.num_search_iterations = num_iter;
  args.outdegree_vertical_distance = -1;
  args.alg_type = EMDFlowNetworkFactory::kShortestAugmentingPath;
  args.output_function = output_function;
  args.verbose = verbose;

  emd_flow_result result;

  emd_flow(args, &result);

  if (nlhs >= 1) {
    set_double_matrix(&(plhs[0]), *(result.support));
  }

  if (nlhs >= 2) {
    set_double(&(plhs[1]), result.emd_cost);
  }

  if (nlhs >= 3) {
    set_double(&(plhs[2]), result.amp_sum);
  }

  if (nlhs >= 4) {
    set_double(&(plhs[3]), result.final_lambda_low);
  }

  if (nlhs >= 5) {
    set_double(&(plhs[4]), result.final_lambda_high);
  }

  /*
  mexPrintf("r = %d, c = %d, k = %d, EMD budget = %d\n", r, c, k, emd_budget);
  for (int ii = 0; ii < r; ++ii) {
    for (int jj = 0; jj < c; ++jj) {
      mexPrintf("%lf ", a[ii][jj]);
    }
    mexPrintf("\n");
  }
  */
}
<commit_msg>adding TODO<commit_after>#include <vector>
#include <string>
#include <set>

#include <math.h>
#include <matrix.h>
#include <mex.h>

#include "mex_helper.h"
#include "emd_flow.h"
#include "emd_flow_network_factory.h"

using namespace std;

void output_function(const char* s) {
  mexPrintf(s);
  mexEvalString("drawnow;");
}

void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) {
  if (nrhs < 3) {
    mexErrMsgTxt("At least three input argument required (amplitudes, sparsity,"
        " EMD budget.");
  }
  // TODO: Also check that we don't get too many arguments.
  if (nlhs > 5) {
    mexErrMsgTxt("Too many output arguments.");
  }

  vector<vector<double> > a;
  if (!get_double_matrix(prhs[0], &a)) {
    mexErrMsgTxt("Amplitudes need to be a two-dimensional double array.");
  }

  int k = 0;
  if (!get_double_as_int(prhs[1], &k)) {
    mexErrMsgTxt("Sparsity has to be a double scalar.");
  }

  int emd_bound_low = 0;
  int emd_bound_high = 0;
  if (!get_double_as_int(prhs[2], &emd_bound_low)) {
    if (!get_double_interval_as_ints(prhs[2], &emd_bound_low,
        &emd_bound_high)) {
      mexErrMsgTxt("EMD budget has to be a double scalar or a double "
          "interval.");
    }
  } else {
    emd_bound_high = emd_bound_low;
  }

  // optional parameters
  bool verbose = false;
  double lambda_low = 1.0;
  double lambda_high = 1.0;
  int num_iter = 10;
  if (nrhs == 4) {
    set<string> known_options;
    known_options.insert("verbose");
    known_options.insert("lambda_low");
    known_options.insert("lambda_high");
    known_options.insert("num_iterations");
    vector<string> options;
    if (!get_fields(prhs[3], &options)) {
      mexErrMsgTxt("Cannot get fields from options argument.");
    }
    for (size_t ii = 0; ii < options.size(); ++ii) {
      if (known_options.find(options[ii]) == known_options.end()) {
        const size_t tmp_size = 1000;
        char tmp[tmp_size];
        snprintf(tmp, tmp_size, "Unknown option \"%s\"\n", options[ii].c_str());
        mexErrMsgTxt(tmp);
      }
    }

    if (has_field(prhs[3], "verbose")
        && !get_bool_field(prhs[3], "verbose", &verbose)) {
      mexErrMsgTxt("verbose flag has to be a boolean scalar.");
    }

    if (has_field(prhs[3], "lambda_low")
        && !get_double_field(prhs[3], "lambda_low", &lambda_low)) {
      mexErrMsgTxt("lambda_low field has to be a double scalar.");
    }

    if (has_field(prhs[3], "lambda_high")
        && !get_double_field(prhs[3], "lambda_high", &lambda_high)) {
      mexErrMsgTxt("lambda_high field has to be a double scalar.");
    }

    if (has_field(prhs[3], "num_iterations")
        && !get_double_field_as_int(prhs[3], "num_iterations", &num_iter)) {
      mexErrMsgTxt("num_iterations field has to be a double scalar.");
    }
  }

  emd_flow_args args(a);
  args.k = k;
  args.emd_bound_low = emd_bound_low;
  args.emd_bound_high = emd_bound_high;
  args.lambda_low = lambda_low;
  args.lambda_high = lambda_high;
  args.num_search_iterations = num_iter;
  args.outdegree_vertical_distance = -1;
  args.alg_type = EMDFlowNetworkFactory::kShortestAugmentingPath;
  args.output_function = output_function;
  args.verbose = verbose;

  emd_flow_result result;

  emd_flow(args, &result);

  if (nlhs >= 1) {
    set_double_matrix(&(plhs[0]), *(result.support));
  }

  if (nlhs >= 2) {
    set_double(&(plhs[1]), result.emd_cost);
  }

  if (nlhs >= 3) {
    set_double(&(plhs[2]), result.amp_sum);
  }

  if (nlhs >= 4) {
    set_double(&(plhs[3]), result.final_lambda_low);
  }

  if (nlhs >= 5) {
    set_double(&(plhs[4]), result.final_lambda_high);
  }

  /*
  mexPrintf("r = %d, c = %d, k = %d, EMD budget = %d\n", r, c, k, emd_budget);
  for (int ii = 0; ii < r; ++ii) {
    for (int jj = 0; jj < c; ++jj) {
      mexPrintf("%lf ", a[ii][jj]);
    }
    mexPrintf("\n");
  }
  */
}
<|endoftext|>


<commit_before>/*****************************************************************************
 * libVLC backend for the Phonon library                                     *
 *                                                                           *
 * Copyright (C) 2007-2008 Tanguy Krotoff <tkrotoff@gmail.com>               *
 * Copyright (C) 2008 Lukas Durfina <lukas.durfina@gmail.com>                *
 * Copyright (C) 2009 Fathi Boudra <fabo@kde.org>                            *
 * Copyright (C) 2009-2010 vlc-phonon AUTHORS                                *
 *                                                                           *
 * This program is free software; you can redistribute it and/or             *
 * modify it under the terms of the GNU Lesser General Public                *
 * License as published by the Free Software Foundation; either              *
 * version 2.1 of the License, or (at your option) any later version.        *
 *                                                                           *
 * This program is distributed in the hope that it will be useful,           *
 * but WITHOUT ANY WARRANTY; without even the implied warranty of            *
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU         *
 * Lesser General Public License for more details.                           *
 *                                                                           *
 * You should have received a copy of the GNU Lesser General Public          *
 * License along with this package; if not, write to the Free Software       *
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA *
 *****************************************************************************/

#include "overlaywidget.h"

#include <QtGui/QPainter>

namespace Phonon
{
namespace VLC
{
OverlayWidget::OverlayWidget(QWidget *parent) :
    BaseWidget(parent)
{
    // When resizing fill with black (backgroundRole color) the rest is done by paintEvent
    setAttribute(Qt::WA_OpaquePaintEvent);

    // Disable Qt composition management as MPlayer draws onto the widget directly
    setAttribute(Qt::WA_PaintOnScreen);

    // Indicates that the widget has no background,
    // i.e. when the widget receives paint events, the background is not automatically repainted.
    setAttribute(Qt::WA_NoSystemBackground);

    // Required for dvdnav
    setMouseTracking(true);
}

void OverlayWidget::paintEvent(QPaintEvent *event)
{
    Q_UNUSED(event);
    // FIXME this makes the video flicker
    // Make everything backgroundRole color
    QPainter painter(this);
    painter.eraseRect(rect());
}

void OverlayWidget::setBackgroundColor(const QColor &color)
{
    QPalette p = palette();
    p.setColor(backgroundRole(), color);
    setPalette(p);
}

}
} // Namespace Phonon::VLC
<commit_msg>add warning about broken dvd menu mouse inputs<commit_after>/*****************************************************************************
 * libVLC backend for the Phonon library                                     *
 *                                                                           *
 * Copyright (C) 2007-2008 Tanguy Krotoff <tkrotoff@gmail.com>               *
 * Copyright (C) 2008 Lukas Durfina <lukas.durfina@gmail.com>                *
 * Copyright (C) 2009 Fathi Boudra <fabo@kde.org>                            *
 * Copyright (C) 2009-2010 vlc-phonon AUTHORS                                *
 *                                                                           *
 * This program is free software; you can redistribute it and/or             *
 * modify it under the terms of the GNU Lesser General Public                *
 * License as published by the Free Software Foundation; either              *
 * version 2.1 of the License, or (at your option) any later version.        *
 *                                                                           *
 * This program is distributed in the hope that it will be useful,           *
 * but WITHOUT ANY WARRANTY; without even the implied warranty of            *
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU         *
 * Lesser General Public License for more details.                           *
 *                                                                           *
 * You should have received a copy of the GNU Lesser General Public          *
 * License along with this package; if not, write to the Free Software       *
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA *
 *****************************************************************************/

#include "overlaywidget.h"

#include <QtGui/QPainter>

namespace Phonon
{
namespace VLC
{
OverlayWidget::OverlayWidget(QWidget *parent) :
    BaseWidget(parent)
{
    // When resizing fill with black (backgroundRole color) the rest is done by paintEvent
    setAttribute(Qt::WA_OpaquePaintEvent);

    // Disable Qt composition management as MPlayer draws onto the widget directly
    setAttribute(Qt::WA_PaintOnScreen);

    // Indicates that the widget has no background,
    // i.e. when the widget receives paint events, the background is not automatically repainted.
    setAttribute(Qt::WA_NoSystemBackground);

    // Required for dvdnav
#ifdef __GNUC__
#warning dragonplayer munches on our mouse events, so clicking in a DVD menu does not work - vlc 1.2 where are thu?
#endif // __GNUC__
    setMouseTracking(true);
}

void OverlayWidget::paintEvent(QPaintEvent *event)
{
    Q_UNUSED(event);
    // FIXME this makes the video flicker
    // Make everything backgroundRole color
    QPainter painter(this);
    painter.eraseRect(rect());
}

void OverlayWidget::setBackgroundColor(const QColor &color)
{
    QPalette p = palette();
    p.setColor(backgroundRole(), color);
    setPalette(p);
}

}
} // Namespace Phonon::VLC
<|endoftext|>


<commit_before>///
/// @file  P2_mpi.cpp
/// @brief 2nd partial sieve function. P2(x, y) counts the
///        numbers <= x that have exactly 2 prime factors
///        each exceeding the a-th prime.
///
/// Copyright (C) 2017 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#include <primecount-internal.hpp>
#include <primesieve.hpp>
#include <aligned_vector.hpp>
#include <int128_t.hpp>
#include <min.hpp>
#include <mpi_reduce_sum.hpp>
#include <imath.hpp>
#include <print.hpp>

#include <stdint.h>
#include <algorithm>
#include <iostream>
#include <iomanip>

using namespace std;
using namespace primecount;

namespace {

/// Count the primes inside [prime, stop]
template <typename T>
int64_t count_primes(primesieve::iterator& it, int64_t& prime, T stop)
{
  int64_t count = 0;

  for (; prime <= stop; count++)
    prime = it.next_prime();

  return count;
}

/// Calculate the thread sieving distance. The idea is to
/// gradually increase the thread_distance in order to
/// keep all CPU cores busy.
///
void balanceLoad(int64_t* thread_distance,
                 int64_t low,
                 int64_t z,
                 int threads,
                 double start_time)
{
  double seconds = get_time() - start_time;

  int64_t min_distance = 1 << 23;
  int64_t max_distance = ceil_div(z - low, threads);

  if (seconds < 60)
    *thread_distance *= 2;
  if (seconds > 60)
    *thread_distance /= 2;

  *thread_distance = in_between(min_distance, *thread_distance, max_distance);
}

template <typename T>
T P2_thread(T x,
            int64_t y,
            int64_t z,
            int64_t low,
            int64_t thread_num,
            int64_t thread_distance,
            int64_t& pix,
            int64_t& pix_count)
{
  pix = 0;
  pix_count = 0;
  low += thread_distance * thread_num;
  z = min(low + thread_distance, z);
  int64_t start = (int64_t) max(x / z, y);
  int64_t stop = (int64_t) min(x / low, isqrt(x));

  primesieve::iterator rit(stop + 1, start);
  primesieve::iterator it(low - 1, z);

  int64_t next = it.next_prime();
  int64_t prime = rit.prev_prime();
  T p2 = 0;

  // \sum_{i = pi[start]+1}^{pi[stop]} pi(x / primes[i])
  while (prime > start &&
         x / prime < z)
  {
    pix += count_primes(it, next, x / prime);
    p2 += pix;
    pix_count++;
    prime = rit.prev_prime();
  }

  pix += count_primes(it, next, z - 1);

  return p2;
}

/// P2(x, y) counts the numbers <= x that have exactly 2
/// prime factors each exceeding the a-th prime.
/// Memory usage: O(z^(1/2))
///
template <typename T>
T P2_mpi_master(T x, int64_t y, int threads)
{
  static_assert(prt::is_signed<T>::value,
                "P2(T x, ...): T must be signed integer type");

  if (x < 4)
    return 0;

  T a = pi_legendre(y, threads);
  T b = pi_legendre((int64_t) isqrt(x), threads);

  if (a >= b)
    return 0;

  int64_t low = 2;
  int64_t z = (int64_t)(x / max(y, 1));
  int64_t min_distance = 1 << 23;
  int64_t thread_distance = min_distance;

  int proc_id = mpi_proc_id();
  int procs = mpi_num_procs();

  int64_t distance = z - low;
  int64_t proc_distance = ceil_div(distance, procs);
  low += proc_distance * proc_id;
  z = min(low + proc_distance, z);

  T p2 = 0;
  T pix_total = pi_legendre(low - 1, threads);

  if (is_mpi_master_proc())
    p2 = (a - 2) * (a + 1) / 2 - (b - 2) * (b + 1) / 2;

  aligned_vector<int64_t> pix(threads);
  aligned_vector<int64_t> pix_counts(threads);

  // \sum_{i=a+1}^{b} pi(x / primes[i])
  while (low < z)
  {
    int64_t max_threads = ceil_div(z - low, thread_distance);
    threads = in_between(1, threads, max_threads);
    double time = get_time();

    #pragma omp parallel for num_threads(threads) reduction(+: p2)
    for (int i = 0; i < threads; i++)
      p2 += P2_thread(x, y, z, low, i, thread_distance, pix[i], pix_counts[i]);

    low += thread_distance * threads;
    balanceLoad(&thread_distance, low, z, threads, time);

    // add missing sum contributions in order
    for (int i = 0; i < threads; i++)
    {
      p2 += pix_total * pix_counts[i];
      pix_total += pix[i];
    }

    if (is_print())
    {
      double percent = get_percent(low, z);
      cout << "\rStatus: " << fixed << setprecision(get_status_precision(x))
           << percent << '%' << flush;
    }
  }

  p2 = mpi_reduce_sum(p2);

  return p2;
}

} // namespace

namespace primecount {

int64_t P2_mpi(int64_t x, int64_t y, int threads)
{
  print("");
  print("=== P2_mpi(x, y) ===");
  print("Computation of the 2nd partial sieve function");
  print(x, y, threads);

  double time = get_time();
  int64_t p2 = P2_mpi_master(x, y, threads);

  print("P2", p2, time);
  return p2;
}

#ifdef HAVE_INT128_T

int128_t P2_mpi(int128_t x, int64_t y, int threads)
{
  print("");
  print("=== P2_mpi(x, y) ===");
  print("Computation of the 2nd partial sieve function");
  print(x, y, threads);

  double time = get_time();
  int128_t p2 = P2_mpi_master(x, y, threads);

  print("P2", p2, time);
  return p2;
}

#endif

} // namespace
<commit_msg>Refactor<commit_after>///
/// @file  P2_mpi.cpp
/// @brief 2nd partial sieve function. P2(x, y) counts the
///        numbers <= x that have exactly 2 prime factors
///        each exceeding the a-th prime.
///
/// 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 <primecount-internal.hpp>
#include <primesieve.hpp>
#include <aligned_vector.hpp>
#include <int128_t.hpp>
#include <min.hpp>
#include <mpi_reduce_sum.hpp>
#include <imath.hpp>
#include <print.hpp>

#include <stdint.h>
#include <algorithm>
#include <iostream>
#include <iomanip>

using namespace std;
using namespace primecount;

namespace {

int64_t count_primes(primesieve::iterator& it, int64_t& prime, int64_t stop)
{
  int64_t count = 0;

  for (; prime <= stop; count++)
    prime = it.next_prime();

  return count;
}

/// Calculate the thread sieving distance. The idea is to
/// gradually increase the thread_distance in order to
/// keep all CPU cores busy.
///
void balanceLoad(int64_t* thread_distance,
                 int64_t low,
                 int64_t z,
                 int threads,
                 double start_time)
{
  double seconds = get_time() - start_time;

  int64_t min_distance = 1 << 23;
  int64_t max_distance = ceil_div(z - low, threads);

  if (seconds < 60)
    *thread_distance *= 2;
  if (seconds > 60)
    *thread_distance /= 2;

  *thread_distance = in_between(min_distance, *thread_distance, max_distance);
}

template <typename T>
T P2_thread(T x,
            int64_t y,
            int64_t z,
            int64_t low,
            int64_t thread_num,
            int64_t thread_distance,
            int64_t& pix,
            int64_t& pix_count)
{
  T p2 = 0;
  pix = 0;
  pix_count = 0;

  low += thread_distance * thread_num;
  z = min(low + thread_distance, z);
  int64_t start = (int64_t) max(x / z, y);
  int64_t stop = (int64_t) min(x / low, isqrt(x));

  primesieve::iterator rit(stop + 1, start);
  primesieve::iterator it(low - 1, z);

  int64_t next = it.next_prime();
  int64_t prime = rit.prev_prime();

  // \sum_{i = pi[start]+1}^{pi[stop]} pi(x / primes[i])
  while (prime > start)
  {
    int64_t xp = (int64_t)(x / prime);
    if (xp >= z) break;
    pix += count_primes(it, next, xp);
    pix_count++;
    p2 += pix;
    prime = rit.prev_prime();
  }

  pix += count_primes(it, next, z - 1);

  return p2;
}

/// P2(x, y) counts the numbers <= x that have exactly 2
/// prime factors each exceeding the a-th prime.
/// Memory usage: O(z^(1/2))
///
template <typename T>
T P2_mpi_master(T x, int64_t y, int threads)
{
  static_assert(prt::is_signed<T>::value,
                "P2(T x, ...): T must be signed integer type");

  if (x < 4)
    return 0;

  T a = pi_legendre(y, threads);
  T b = pi_legendre((int64_t) isqrt(x), threads);

  if (a >= b)
    return 0;

  int64_t low = 2;
  int64_t z = (int64_t)(x / max(y, 1));
  int64_t min_distance = 1 << 23;
  int64_t thread_distance = min_distance;

  int proc_id = mpi_proc_id();
  int procs = mpi_num_procs();

  int64_t distance = z - low;
  int64_t proc_distance = ceil_div(distance, procs);
  low += proc_distance * proc_id;
  z = min(low + proc_distance, z);

  T p2 = 0;
  T pix_total = pi_legendre(low - 1, threads);

  if (is_mpi_master_proc())
    p2 = (a - 2) * (a + 1) / 2 - (b - 2) * (b + 1) / 2;

  aligned_vector<int64_t> pix(threads);
  aligned_vector<int64_t> pix_counts(threads);

  // \sum_{i=a+1}^{b} pi(x / primes[i])
  while (low < z)
  {
    int64_t max_threads = ceil_div(z - low, thread_distance);
    threads = in_between(1, threads, max_threads);
    double time = get_time();

    #pragma omp parallel for num_threads(threads) reduction(+: p2)
    for (int i = 0; i < threads; i++)
      p2 += P2_thread(x, y, z, low, i, thread_distance, pix[i], pix_counts[i]);

    low += thread_distance * threads;
    balanceLoad(&thread_distance, low, z, threads, time);

    // add missing sum contributions in order
    for (int i = 0; i < threads; i++)
    {
      p2 += pix_total * pix_counts[i];
      pix_total += pix[i];
    }

    if (is_print())
    {
      double percent = get_percent(low, z);
      cout << "\rStatus: " << fixed << setprecision(get_status_precision(x))
           << percent << '%' << flush;
    }
  }

  p2 = mpi_reduce_sum(p2);

  return p2;
}

} // namespace

namespace primecount {

int64_t P2_mpi(int64_t x, int64_t y, int threads)
{
  print("");
  print("=== P2_mpi(x, y) ===");
  print("Computation of the 2nd partial sieve function");
  print(x, y, threads);

  double time = get_time();
  int64_t p2 = P2_mpi_master(x, y, threads);

  print("P2", p2, time);
  return p2;
}

#ifdef HAVE_INT128_T

int128_t P2_mpi(int128_t x, int64_t y, int threads)
{
  print("");
  print("=== P2_mpi(x, y) ===");
  print("Computation of the 2nd partial sieve function");
  print(x, y, threads);

  double time = get_time();
  int128_t p2 = P2_mpi_master(x, y, threads);

  print("P2", p2, time);
  return p2;
}

#endif

} // namespace
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2011, Nathan Rajlich <nathan@tootallnate.net>
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#include <v8.h>
#include <node.h>
#include <node_buffer.h>
#include <mpg123.h>

using namespace v8;
using namespace node;

namespace nodelame {

#define UNWRAP_MH \
  HandleScope scope; \
  Local<Object>wrapper = args[0]->ToObject(); \
  mpg123_handle *mh = (mpg123_handle *)wrapper->GetPointerFromInternalField(0);

/* Wrapper ObjectTemplate to hold `mpg123_handle` instances */
Persistent<ObjectTemplate> mhClass;

Handle<Value> node_mpg123_init (const Arguments& args) {
  HandleScope scope;
  return scope.Close(Integer::New(mpg123_init()));
}

Handle<Value> node_mpg123_exit (const Arguments& args) {
  HandleScope scope;
  mpg123_exit();
  return Undefined();
}

void mh_weak_callback (Persistent<Value> wrapper, void *arg) {
  HandleScope scope;
  mpg123_handle *mh = (mpg123_handle *)arg;
  mpg123_delete(mh);
  wrapper.Dispose();
}

// TODO: Make async
Handle<Value> node_mpg123_new (const Arguments& args) {
  HandleScope scope;

  // TODO: Accept an input decoder String
  int error = 0;
  mpg123_handle *mh = mpg123_new(NULL, &error);

  Handle<Value> rtn;
  if (error == MPG123_OK) {
    Persistent<Object> o = Persistent<Object>::New(mhClass->NewInstance());
    o->SetPointerInInternalField(0, mh);
    o.MakeWeak(mh, mh_weak_callback);
    rtn = o;
  } else {
    rtn = Integer::New(error);
  }
  return scope.Close(rtn);
}

Handle<Value> node_mpg123_current_decoder (const Arguments& args) {
  UNWRAP_MH;
  const char *decoder = mpg123_current_decoder(mh);
  return scope.Close(String::New(decoder));
}

Handle<Value> node_mpg123_supported_decoders (const Arguments& args) {
  HandleScope scope;
  const char **decoders = mpg123_supported_decoders();
  int i = 0;
  Handle<Array> rtn = Array::New();
  while (*decoders != NULL) {
    rtn->Set(Integer::New(i++), String::New(*decoders));
    decoders++;
  }
  return scope.Close(rtn);
}

Handle<Value> node_mpg123_decoders (const Arguments& args) {
  HandleScope scope;
  const char **decoders = mpg123_decoders();
  int i = 0;
  Handle<Array> rtn = Array::New();
  while (*decoders != NULL) {
    rtn->Set(Integer::New(i++), String::New(*decoders));
    decoders++;
  }
  return scope.Close(rtn);
}

// TODO: Make async
Handle<Value> node_mpg123_open_feed (const Arguments& args) {
  UNWRAP_MH;
  int ret = mpg123_open_feed(mh);
  return scope.Close(Integer::New(ret));
}

// TODO: Make async
Handle<Value> node_mpg123_decode (const Arguments& args) {
  UNWRAP_MH;

  // input MP3 data
  const unsigned char *input = (const unsigned char *)Buffer::Data(args[1]->ToObject());
  size_t insize = args[2]->Int32Value();

  // the output buffer
  Local<Object> outbuf = args[3]->ToObject();
  int out_offset = args[4]->Int32Value();
  unsigned char *output = (unsigned char *)(Buffer::Data(outbuf) + out_offset);
  size_t outsize = args[5]->Int32Value();

  size_t size = 0;
  int ret = mpg123_decode(mh, input, insize, output, outsize, &size);

  Local<Object> rtn = Object::New();
  rtn->Set(String::NewSymbol("ret"), Integer::New(ret));
  rtn->Set(String::NewSymbol("size"), Integer::New(size));
  return scope.Close(rtn);
}

void InitMPG123(Handle<Object> target) {
  HandleScope scope;

  mhClass = Persistent<ObjectTemplate>::New(ObjectTemplate::New());
  mhClass->SetInternalFieldCount(1);

#define CONST_INT(value) \
  target->Set(String::NewSymbol(#value), Integer::New(value), \
      static_cast<PropertyAttribute>(ReadOnly|DontDelete));

  // mpg123_errors
  CONST_INT(MPG123_DONE);  /**< Message: Track ended. Stop decoding. */
  CONST_INT(MPG123_NEW_FORMAT);  /**< Message: Output format will be different on next call. Note that some libmpg123 versions between 1.4.3 and 1.8.0 insist on you calling mpg123_getformat() after getting this message code. Newer verisons behave like advertised: You have the chance to call mpg123_getformat(), but you can also just continue decoding and get your data. */
  CONST_INT(MPG123_NEED_MORE);  /**< Message: For feed reader: "Feed me more!" (call mpg123_feed() or mpg123_decode() with some new input data). */
  CONST_INT(MPG123_ERR);      /**< Generic Error */
  CONST_INT(MPG123_OK);       /**< Success */
  CONST_INT(MPG123_BAD_OUTFORMAT);   /**< Unable to set up output format! */
  CONST_INT(MPG123_BAD_CHANNEL);    /**< Invalid channel number specified. */
  CONST_INT(MPG123_BAD_RATE);    /**< Invalid sample rate specified.  */
  CONST_INT(MPG123_ERR_16TO8TABLE);  /**< Unable to allocate memory for 16 to 8 converter table! */
  CONST_INT(MPG123_BAD_PARAM);    /**< Bad parameter id! */
  CONST_INT(MPG123_BAD_BUFFER);    /**< Bad buffer given -- invalid pointer or too small size. */
  CONST_INT(MPG123_OUT_OF_MEM);    /**< Out of memory -- some malloc() failed. */
  CONST_INT(MPG123_NOT_INITIALIZED);  /**< You didn't initialize the library! */
  CONST_INT(MPG123_BAD_DECODER);    /**< Invalid decoder choice. */
  CONST_INT(MPG123_BAD_HANDLE);    /**< Invalid mpg123 handle. */
  CONST_INT(MPG123_NO_BUFFERS);    /**< Unable to initialize frame buffers (out of memory?). */
  CONST_INT(MPG123_BAD_RVA);      /**< Invalid RVA mode. */
  CONST_INT(MPG123_NO_GAPLESS);    /**< This build doesn't support gapless decoding. */
  CONST_INT(MPG123_NO_SPACE);    /**< Not enough buffer space. */
  CONST_INT(MPG123_BAD_TYPES);    /**< Incompatible numeric data types. */
  CONST_INT(MPG123_BAD_BAND);    /**< Bad equalizer band. */
  CONST_INT(MPG123_ERR_NULL);    /**< Null pointer given where valid storage address needed. */
  CONST_INT(MPG123_ERR_READER);    /**< Error reading the stream. */
  CONST_INT(MPG123_NO_SEEK_FROM_END);/**< Cannot seek from end (end is not known). */
  CONST_INT(MPG123_BAD_WHENCE);    /**< Invalid 'whence' for seek function.*/
  CONST_INT(MPG123_NO_TIMEOUT);    /**< Build does not support stream timeouts. */
  CONST_INT(MPG123_BAD_FILE);    /**< File access error. */
  CONST_INT(MPG123_NO_SEEK);     /**< Seek not supported by stream. */
  CONST_INT(MPG123_NO_READER);    /**< No stream opened. */
  CONST_INT(MPG123_BAD_PARS);    /**< Bad parameter handle. */
  CONST_INT(MPG123_BAD_INDEX_PAR);  /**< Bad parameters to mpg123_index() and mpg123_set_index() */
  CONST_INT(MPG123_OUT_OF_SYNC);  /**< Lost track in bytestream and did not try to resync. */
  CONST_INT(MPG123_RESYNC_FAIL);  /**< Resync failed to find valid MPEG data. */
  CONST_INT(MPG123_NO_8BIT);  /**< No 8bit encoding possible. */
  CONST_INT(MPG123_BAD_ALIGN);  /**< Stack aligmnent error */
  CONST_INT(MPG123_NULL_BUFFER);  /**< NULL input buffer with non-zero size... */
  CONST_INT(MPG123_NO_RELSEEK);  /**< Relative seek not possible (screwed up file offset) */
  CONST_INT(MPG123_NULL_POINTER); /**< You gave a null pointer somewhere where you shouldn't have. */
  CONST_INT(MPG123_BAD_KEY);   /**< Bad key value given. */
  CONST_INT(MPG123_NO_INDEX);  /**< No frame index in this build. */
  CONST_INT(MPG123_INDEX_FAIL);  /**< Something with frame index went wrong. */
  CONST_INT(MPG123_BAD_DECODER_SETUP);  /**< Something prevents a proper decoder setup */
  CONST_INT(MPG123_MISSING_FEATURE);  /**< This feature has not been built into libmpg123. */
  CONST_INT(MPG123_BAD_VALUE); /**< A bad value has been given, somewhere. */
  CONST_INT(MPG123_LSEEK_FAILED); /**< Low-level seek failed. */
  CONST_INT(MPG123_BAD_CUSTOM_IO); /**< Custom I/O not prepared. */
  CONST_INT(MPG123_LFS_OVERFLOW); /**< Offset value overflow during translation of large file API calls -- your client program cannot handle that large file. */

  /* mpg123_channelcount */
  CONST_INT(MPG123_MONO);
  CONST_INT(MPG123_STEREO);

  // mpg123_channels
  CONST_INT(MPG123_LEFT);
  CONST_INT(MPG123_RIGHT);
  CONST_INT(MPG123_LR);

  CONST_INT(MPG123_ID3);
  CONST_INT(MPG123_NEW_ID3);
  CONST_INT(MPG123_ICY);
  CONST_INT(MPG123_NEW_ICY);

  NODE_SET_METHOD(target, "mpg123_init", node_mpg123_init);
  NODE_SET_METHOD(target, "mpg123_exit", node_mpg123_exit);
  NODE_SET_METHOD(target, "mpg123_new", node_mpg123_new);
  NODE_SET_METHOD(target, "mpg123_decoders", node_mpg123_decoders);
  NODE_SET_METHOD(target, "mpg123_current_decoder", node_mpg123_current_decoder);
  NODE_SET_METHOD(target, "mpg123_supported_decoders", node_mpg123_supported_decoders);
  NODE_SET_METHOD(target, "mpg123_open_feed", node_mpg123_open_feed);
  NODE_SET_METHOD(target, "mpg123_decode", node_mpg123_decode);
}

} // nodelame namespace
<commit_msg>Add support for passing in a null Buffer to decode()<commit_after>/*
 * Copyright (c) 2011, Nathan Rajlich <nathan@tootallnate.net>
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#include <v8.h>
#include <node.h>
#include <node_buffer.h>
#include <mpg123.h>

using namespace v8;
using namespace node;

namespace nodelame {

#define UNWRAP_MH \
  HandleScope scope; \
  Local<Object>wrapper = args[0]->ToObject(); \
  mpg123_handle *mh = (mpg123_handle *)wrapper->GetPointerFromInternalField(0);

/* Wrapper ObjectTemplate to hold `mpg123_handle` instances */
Persistent<ObjectTemplate> mhClass;

Handle<Value> node_mpg123_init (const Arguments& args) {
  HandleScope scope;
  return scope.Close(Integer::New(mpg123_init()));
}

Handle<Value> node_mpg123_exit (const Arguments& args) {
  HandleScope scope;
  mpg123_exit();
  return Undefined();
}

void mh_weak_callback (Persistent<Value> wrapper, void *arg) {
  HandleScope scope;
  mpg123_handle *mh = (mpg123_handle *)arg;
  mpg123_delete(mh);
  wrapper.Dispose();
}

// TODO: Make async
Handle<Value> node_mpg123_new (const Arguments& args) {
  HandleScope scope;

  // TODO: Accept an input decoder String
  int error = 0;
  mpg123_handle *mh = mpg123_new(NULL, &error);

  Handle<Value> rtn;
  if (error == MPG123_OK) {
    Persistent<Object> o = Persistent<Object>::New(mhClass->NewInstance());
    o->SetPointerInInternalField(0, mh);
    o.MakeWeak(mh, mh_weak_callback);
    rtn = o;
  } else {
    rtn = Integer::New(error);
  }
  return scope.Close(rtn);
}

Handle<Value> node_mpg123_current_decoder (const Arguments& args) {
  UNWRAP_MH;
  const char *decoder = mpg123_current_decoder(mh);
  return scope.Close(String::New(decoder));
}

Handle<Value> node_mpg123_supported_decoders (const Arguments& args) {
  HandleScope scope;
  const char **decoders = mpg123_supported_decoders();
  int i = 0;
  Handle<Array> rtn = Array::New();
  while (*decoders != NULL) {
    rtn->Set(Integer::New(i++), String::New(*decoders));
    decoders++;
  }
  return scope.Close(rtn);
}

Handle<Value> node_mpg123_decoders (const Arguments& args) {
  HandleScope scope;
  const char **decoders = mpg123_decoders();
  int i = 0;
  Handle<Array> rtn = Array::New();
  while (*decoders != NULL) {
    rtn->Set(Integer::New(i++), String::New(*decoders));
    decoders++;
  }
  return scope.Close(rtn);
}

// TODO: Make async
Handle<Value> node_mpg123_open_feed (const Arguments& args) {
  UNWRAP_MH;
  int ret = mpg123_open_feed(mh);
  return scope.Close(Integer::New(ret));
}

// TODO: Make async
Handle<Value> node_mpg123_decode (const Arguments& args) {
  UNWRAP_MH;

  // input MP3 data
  const unsigned char *input = NULL;
  if (!args[1]->IsNull()) {
    input = (const unsigned char *)Buffer::Data(args[1]->ToObject());
  }
  size_t insize = args[2]->Int32Value();

  // the output buffer
  Local<Object> outbuf = args[3]->ToObject();
  int out_offset = args[4]->Int32Value();
  unsigned char *output = (unsigned char *)(Buffer::Data(outbuf) + out_offset);
  size_t outsize = args[5]->Int32Value();

  size_t size = 0;
  int ret = mpg123_decode(mh, input, insize, output, outsize, &size);

  Local<Object> rtn = Object::New();
  rtn->Set(String::NewSymbol("ret"), Integer::New(ret));
  rtn->Set(String::NewSymbol("size"), Integer::New(size));

  if (ret == MPG123_NEW_FORMAT) {
    printf("got New Format\n");
    long rate;
    int channels;
    int encoding;
    mpg123_getformat(mh, &rate, &channels, &encoding);
    printf("rate: %lu\n", rate);
    printf("channels: %d\n", channels);
    printf("encoding: %d\n", encoding);
  }

  return scope.Close(rtn);
}

void InitMPG123(Handle<Object> target) {
  HandleScope scope;

  mhClass = Persistent<ObjectTemplate>::New(ObjectTemplate::New());
  mhClass->SetInternalFieldCount(1);

#define CONST_INT(value) \
  target->Set(String::NewSymbol(#value), Integer::New(value), \
      static_cast<PropertyAttribute>(ReadOnly|DontDelete));

  // mpg123_errors
  CONST_INT(MPG123_DONE);  /**< Message: Track ended. Stop decoding. */
  CONST_INT(MPG123_NEW_FORMAT);  /**< Message: Output format will be different on next call. Note that some libmpg123 versions between 1.4.3 and 1.8.0 insist on you calling mpg123_getformat() after getting this message code. Newer verisons behave like advertised: You have the chance to call mpg123_getformat(), but you can also just continue decoding and get your data. */
  CONST_INT(MPG123_NEED_MORE);  /**< Message: For feed reader: "Feed me more!" (call mpg123_feed() or mpg123_decode() with some new input data). */
  CONST_INT(MPG123_ERR);      /**< Generic Error */
  CONST_INT(MPG123_OK);       /**< Success */
  CONST_INT(MPG123_BAD_OUTFORMAT);   /**< Unable to set up output format! */
  CONST_INT(MPG123_BAD_CHANNEL);    /**< Invalid channel number specified. */
  CONST_INT(MPG123_BAD_RATE);    /**< Invalid sample rate specified.  */
  CONST_INT(MPG123_ERR_16TO8TABLE);  /**< Unable to allocate memory for 16 to 8 converter table! */
  CONST_INT(MPG123_BAD_PARAM);    /**< Bad parameter id! */
  CONST_INT(MPG123_BAD_BUFFER);    /**< Bad buffer given -- invalid pointer or too small size. */
  CONST_INT(MPG123_OUT_OF_MEM);    /**< Out of memory -- some malloc() failed. */
  CONST_INT(MPG123_NOT_INITIALIZED);  /**< You didn't initialize the library! */
  CONST_INT(MPG123_BAD_DECODER);    /**< Invalid decoder choice. */
  CONST_INT(MPG123_BAD_HANDLE);    /**< Invalid mpg123 handle. */
  CONST_INT(MPG123_NO_BUFFERS);    /**< Unable to initialize frame buffers (out of memory?). */
  CONST_INT(MPG123_BAD_RVA);      /**< Invalid RVA mode. */
  CONST_INT(MPG123_NO_GAPLESS);    /**< This build doesn't support gapless decoding. */
  CONST_INT(MPG123_NO_SPACE);    /**< Not enough buffer space. */
  CONST_INT(MPG123_BAD_TYPES);    /**< Incompatible numeric data types. */
  CONST_INT(MPG123_BAD_BAND);    /**< Bad equalizer band. */
  CONST_INT(MPG123_ERR_NULL);    /**< Null pointer given where valid storage address needed. */
  CONST_INT(MPG123_ERR_READER);    /**< Error reading the stream. */
  CONST_INT(MPG123_NO_SEEK_FROM_END);/**< Cannot seek from end (end is not known). */
  CONST_INT(MPG123_BAD_WHENCE);    /**< Invalid 'whence' for seek function.*/
  CONST_INT(MPG123_NO_TIMEOUT);    /**< Build does not support stream timeouts. */
  CONST_INT(MPG123_BAD_FILE);    /**< File access error. */
  CONST_INT(MPG123_NO_SEEK);     /**< Seek not supported by stream. */
  CONST_INT(MPG123_NO_READER);    /**< No stream opened. */
  CONST_INT(MPG123_BAD_PARS);    /**< Bad parameter handle. */
  CONST_INT(MPG123_BAD_INDEX_PAR);  /**< Bad parameters to mpg123_index() and mpg123_set_index() */
  CONST_INT(MPG123_OUT_OF_SYNC);  /**< Lost track in bytestream and did not try to resync. */
  CONST_INT(MPG123_RESYNC_FAIL);  /**< Resync failed to find valid MPEG data. */
  CONST_INT(MPG123_NO_8BIT);  /**< No 8bit encoding possible. */
  CONST_INT(MPG123_BAD_ALIGN);  /**< Stack aligmnent error */
  CONST_INT(MPG123_NULL_BUFFER);  /**< NULL input buffer with non-zero size... */
  CONST_INT(MPG123_NO_RELSEEK);  /**< Relative seek not possible (screwed up file offset) */
  CONST_INT(MPG123_NULL_POINTER); /**< You gave a null pointer somewhere where you shouldn't have. */
  CONST_INT(MPG123_BAD_KEY);   /**< Bad key value given. */
  CONST_INT(MPG123_NO_INDEX);  /**< No frame index in this build. */
  CONST_INT(MPG123_INDEX_FAIL);  /**< Something with frame index went wrong. */
  CONST_INT(MPG123_BAD_DECODER_SETUP);  /**< Something prevents a proper decoder setup */
  CONST_INT(MPG123_MISSING_FEATURE);  /**< This feature has not been built into libmpg123. */
  CONST_INT(MPG123_BAD_VALUE); /**< A bad value has been given, somewhere. */
  CONST_INT(MPG123_LSEEK_FAILED); /**< Low-level seek failed. */
  CONST_INT(MPG123_BAD_CUSTOM_IO); /**< Custom I/O not prepared. */
  CONST_INT(MPG123_LFS_OVERFLOW); /**< Offset value overflow during translation of large file API calls -- your client program cannot handle that large file. */

  /* mpg123_channelcount */
  CONST_INT(MPG123_MONO);
  CONST_INT(MPG123_STEREO);

  // mpg123_channels
  CONST_INT(MPG123_LEFT);
  CONST_INT(MPG123_RIGHT);
  CONST_INT(MPG123_LR);

  CONST_INT(MPG123_ID3);
  CONST_INT(MPG123_NEW_ID3);
  CONST_INT(MPG123_ICY);
  CONST_INT(MPG123_NEW_ICY);

  NODE_SET_METHOD(target, "mpg123_init", node_mpg123_init);
  NODE_SET_METHOD(target, "mpg123_exit", node_mpg123_exit);
  NODE_SET_METHOD(target, "mpg123_new", node_mpg123_new);
  NODE_SET_METHOD(target, "mpg123_decoders", node_mpg123_decoders);
  NODE_SET_METHOD(target, "mpg123_current_decoder", node_mpg123_current_decoder);
  NODE_SET_METHOD(target, "mpg123_supported_decoders", node_mpg123_supported_decoders);
  NODE_SET_METHOD(target, "mpg123_open_feed", node_mpg123_open_feed);
  NODE_SET_METHOD(target, "mpg123_decode", node_mpg123_decode);
}

} // nodelame namespace
<|endoftext|>


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

/* Author: Matt Maly */

#include <ompl/control/SpaceInformation.h>
#include <ompl/base/spaces/SE2StateSpace.h>
#include <ompl/control/spaces/RealVectorControlSpace.h>
#include <ompl/control/SimpleSetup.h>
#include <ompl/config.h>
#include <iostream>
#include <vector>

#include <ompl/extensions/triangle/PropositionalTriangularDecomposition.h>
#include <ompl/control/planners/ltl/PropositionalDecomposition.h>
#include <ompl/control/planners/ltl/Automaton.h>
#include <ompl/control/planners/ltl/ProductGraph.h>
#include <ompl/control/planners/ltl/LTLPlanner.h>
#include <ompl/control/planners/ltl/LTLProblemDefinition.h>

namespace ob = ompl::base;
namespace oc = ompl::control;

typedef oc::PropositionalTriangularDecomposition::Polygon Polygon;
typedef oc::PropositionalTriangularDecomposition::Vertex Vertex;

// a decomposition is only needed for SyclopRRT and SyclopEST
// use TriangularDecomp
class MyDecomposition : public oc::PropositionalTriangularDecomposition
{
public:
    MyDecomposition(const ob::RealVectorBounds& bounds)
        : oc::PropositionalTriangularDecomposition(bounds) { }
    virtual ~MyDecomposition() { }

    virtual void project(const ob::State* s, std::vector<double>& coord) const
    {
        coord.resize(2);
        coord[0] = s->as<ob::SE2StateSpace::StateType>()->getX();
        coord[1] = s->as<ob::SE2StateSpace::StateType>()->getY();
    }

    virtual void sampleFullState(const ob::StateSamplerPtr& sampler, const std::vector<double>& coord, ob::State* s) const
    {
       sampler->sampleUniform(s);
       ob::SE2StateSpace::StateType* ws = s->as<ob::SE2StateSpace::StateType>();
       ws->setXY(coord[0], coord[1]);
    }

private:
    ompl::RNG rng_;
};

void addObstaclesAndPropositions(oc::PropositionalTriangularDecomposition* decomp)
{
    Polygon obstacle(4);
    obstacle.pts[0] = Vertex(0.,.9);
    obstacle.pts[1] = Vertex(1.1,.9);
    obstacle.pts[2] = Vertex(1.1,1.1);
    obstacle.pts[3] = Vertex(0.,1.1);
    decomp->addHole(obstacle);

    Polygon p0(4);
    p0.pts[0] = Vertex(.9,.3);
    p0.pts[1] = Vertex(1.1,.3);
    p0.pts[2] = Vertex(1.1,.5);
    p0.pts[3] = Vertex(.9,.5);
    decomp->addProposition(p0);

    Polygon p1(4);
    p1.pts[0] = Vertex(1.5,1.6);
    p1.pts[1] = Vertex(1.6,1.6);
    p1.pts[2] = Vertex(1.6,1.7);
    p1.pts[3] = Vertex(1.5,1.7);
    decomp->addProposition(p1);

    Polygon p2(4);
    p2.pts[0] = Vertex(.2,1.7);
    p2.pts[1] = Vertex(.3,1.7);
    p2.pts[2] = Vertex(.3,1.8);
    p2.pts[3] = Vertex(.2,1.8);
    decomp->addProposition(p2);
}

/* Returns whether a point (x,y) is within a given polygon.
   We are assuming that the polygon is a axis-aligned rectangle, with vertices stored
   in counter-clockwise order, beginning with the bottom-left vertex. */
bool polyContains(const Polygon& poly, double x, double y)
{
    return x >= poly.pts[0].x && x <= poly.pts[2].x
        && y >= poly.pts[0].y && y <= poly.pts[2].y;
}

/* Our state validity checker queries the decomposition for its obstacles,
   and checks for collisions against them.
   This is to prevent us from having to redefine the obstacles in multiple places. */
bool isStateValid(
    const oc::SpaceInformation *si,
    const oc::PropositionalTriangularDecomposition* decomp,
    const ob::State *state)
{
    if (!si->satisfiesBounds(state))
        return false;
    const ob::SE2StateSpace::StateType* se2 = state->as<ob::SE2StateSpace::StateType>();

	double x = se2->getX();
	double y = se2->getY();
    const std::vector<Polygon>& obstacles = decomp->getHoles();
    typedef std::vector<Polygon>::const_iterator ObstacleIter;
    for (ObstacleIter o = obstacles.begin(); o != obstacles.end(); ++o)
    {
        if (polyContains(*o, x, y))
            return false;
    }
	return true;
}

void propagate(const ob::State *start, const oc::Control *control, const double duration, ob::State *result)
{
    const ob::SE2StateSpace::StateType* se2 = start->as<ob::SE2StateSpace::StateType>();
    const oc::RealVectorControlSpace::ControlType* rctrl = control->as<oc::RealVectorControlSpace::ControlType>();

    double xout = se2->getX() + rctrl->values[0]*duration*cos(se2->getYaw());
    double yout = se2->getY() + rctrl->values[0]*duration*sin(se2->getYaw());
    double yawout = se2->getYaw() + rctrl->values[1];

    ob::SE2StateSpace::StateType* se2out = result->as<ob::SE2StateSpace::StateType>();
    se2out->setXY(xout, yout);
    se2out->setYaw(yawout);

    ob::SO2StateSpace::StateType* so2out = se2out->as<ob::SO2StateSpace::StateType>(1);
    ob::SO2StateSpace SO2;
    SO2.enforceBounds (so2out);
}

void plan(void)
{
    // construct the state space we are planning in
    ob::StateSpacePtr space(new ob::SE2StateSpace());

    // set the bounds for the R^2 part of SE(2)
    ob::RealVectorBounds bounds(2);
    bounds.setLow(0);
    bounds.setHigh(2);

    space->as<ob::SE2StateSpace>()->setBounds(bounds);

    // create triangulation that ignores obstacle and respects propositions
    MyDecomposition* ptd = new MyDecomposition(bounds);
    addObstaclesAndPropositions(ptd);
    ptd->setup();
    oc::PropositionalDecompositionPtr pd(ptd);

    // create a control space
    oc::ControlSpacePtr cspace(new oc::RealVectorControlSpace(space, 2));

    // set the bounds for the control space
    ob::RealVectorBounds cbounds(2);
    cbounds.setLow(-.5);
    cbounds.setHigh(.5);

    cspace->as<oc::RealVectorControlSpace>()->setBounds(cbounds);

    oc::SpaceInformationPtr si(new oc::SpaceInformation(space, cspace));
    si->setStateValidityChecker(boost::bind(&isStateValid, si.get(), ptd, _1));
    si->setStatePropagator(boost::bind(&propagate, _1, _2, _3, _4));
    si->setPropagationStepSize(0.025);

    //LTL co-safety sequencing formula: visit p2,p0 in that order
    std::vector<unsigned int> sequence(2);
    sequence[0] = 2;
    sequence[1] = 0;
    oc::AutomatonPtr cosafety = oc::Automaton::SequenceAutomaton(3, sequence);

    //LTL safety avoidance formula: never visit p1
    std::vector<unsigned int> toAvoid(1);
    toAvoid[0] = 1;
    oc::AutomatonPtr safety = oc::Automaton::AvoidanceAutomaton(3, toAvoid);

    //construct product graph (propDecomp x A_{cosafety} x A_{safety})
    oc::ProductGraphPtr product(new oc::ProductGraph(pd, cosafety, safety));
    oc::LTLSpaceInformationPtr ltlsi(new oc::LTLSpaceInformation(si, product));

    ob::LTLProblemDefinitionPtr pdef(new ob::LTLProblemDefinition(ltlsi));

    // create a start state
    ob::ScopedState<ob::SE2StateSpace> start(space);
    start->setX(0.2);
    start->setY(0.2);
    start->setYaw(0.0);

    pdef->addLowerStartState(start.get());

    //LTL planner (input: state information, product automaton)
    oc::LTLPlanner* ltlPlanner = new oc::LTLPlanner(ltlsi, product);

    ltlPlanner->setProblemDefinition(pdef);

    // attempt to solve the problem within thirty seconds of planning time
    ob::PlannerStatus solved = ltlPlanner->as<ob::Planner>()->solve(30.0);

    if (solved)
    {
        std::cout << "Found solution:" << std::endl;
        pdef->getLowerSolutionPath()->print(std::cout);
    }
    else
        std::cout << "No solution found" << std::endl;
}

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

/* Author: Matt Maly */

#include <ompl/control/SpaceInformation.h>
#include <ompl/base/spaces/SE2StateSpace.h>
#include <ompl/control/spaces/RealVectorControlSpace.h>
#include <ompl/control/SimpleSetup.h>
#include <ompl/config.h>
#include <iostream>
#include <vector>

#include <ompl/extensions/triangle/PropositionalTriangularDecomposition.h>
#include <ompl/control/planners/ltl/PropositionalDecomposition.h>
#include <ompl/control/planners/ltl/Automaton.h>
#include <ompl/control/planners/ltl/ProductGraph.h>
#include <ompl/control/planners/ltl/LTLPlanner.h>
#include <ompl/control/planners/ltl/LTLProblemDefinition.h>

namespace ob = ompl::base;
namespace oc = ompl::control;

typedef oc::PropositionalTriangularDecomposition::Polygon Polygon;
typedef oc::PropositionalTriangularDecomposition::Vertex Vertex;

// a decomposition is only needed for SyclopRRT and SyclopEST
// use TriangularDecomp
class MyDecomposition : public oc::PropositionalTriangularDecomposition
{
public:
    MyDecomposition(const ob::RealVectorBounds& bounds)
        : oc::PropositionalTriangularDecomposition(bounds) { }
    virtual ~MyDecomposition() { }

    virtual void project(const ob::State* s, std::vector<double>& coord) const
    {
        coord.resize(2);
        coord[0] = s->as<ob::SE2StateSpace::StateType>()->getX();
        coord[1] = s->as<ob::SE2StateSpace::StateType>()->getY();
    }

    virtual void sampleFullState(const ob::StateSamplerPtr& sampler, const std::vector<double>& coord, ob::State* s) const
    {
       sampler->sampleUniform(s);
       ob::SE2StateSpace::StateType* ws = s->as<ob::SE2StateSpace::StateType>();
       ws->setXY(coord[0], coord[1]);
    }

private:
    ompl::RNG rng_;
};

void addObstaclesAndPropositions(oc::PropositionalTriangularDecomposition* decomp)
{
    Polygon obstacle(4);
    obstacle.pts[0] = Vertex(0.,.9);
    obstacle.pts[1] = Vertex(1.1,.9);
    obstacle.pts[2] = Vertex(1.1,1.1);
    obstacle.pts[3] = Vertex(0.,1.1);
    decomp->addHole(obstacle);

    Polygon p0(4);
    p0.pts[0] = Vertex(.9,.3);
    p0.pts[1] = Vertex(1.1,.3);
    p0.pts[2] = Vertex(1.1,.5);
    p0.pts[3] = Vertex(.9,.5);
    decomp->addProposition(p0);

    Polygon p1(4);
    p1.pts[0] = Vertex(1.5,1.6);
    p1.pts[1] = Vertex(1.6,1.6);
    p1.pts[2] = Vertex(1.6,1.7);
    p1.pts[3] = Vertex(1.5,1.7);
    decomp->addProposition(p1);

    Polygon p2(4);
    p2.pts[0] = Vertex(.2,1.7);
    p2.pts[1] = Vertex(.3,1.7);
    p2.pts[2] = Vertex(.3,1.8);
    p2.pts[3] = Vertex(.2,1.8);
    decomp->addProposition(p2);
}

/* Returns whether a point (x,y) is within a given polygon.
   We are assuming that the polygon is a axis-aligned rectangle, with vertices stored
   in counter-clockwise order, beginning with the bottom-left vertex. */
bool polyContains(const Polygon& poly, double x, double y)
{
    return x >= poly.pts[0].x && x <= poly.pts[2].x
        && y >= poly.pts[0].y && y <= poly.pts[2].y;
}

/* Our state validity checker queries the decomposition for its obstacles,
   and checks for collisions against them.
   This is to prevent us from having to redefine the obstacles in multiple places. */
bool isStateValid(
    const oc::SpaceInformation *si,
    const oc::PropositionalTriangularDecomposition* decomp,
    const ob::State *state)
{
    if (!si->satisfiesBounds(state))
        return false;
    const ob::SE2StateSpace::StateType* se2 = state->as<ob::SE2StateSpace::StateType>();

	double x = se2->getX();
	double y = se2->getY();
    const std::vector<Polygon>& obstacles = decomp->getHoles();
    typedef std::vector<Polygon>::const_iterator ObstacleIter;
    for (ObstacleIter o = obstacles.begin(); o != obstacles.end(); ++o)
    {
        if (polyContains(*o, x, y))
            return false;
    }
	return true;
}

void propagate(const ob::State *start, const oc::Control *control, const double duration, ob::State *result)
{
    const ob::SE2StateSpace::StateType* se2 = start->as<ob::SE2StateSpace::StateType>();
    const oc::RealVectorControlSpace::ControlType* rctrl = control->as<oc::RealVectorControlSpace::ControlType>();

    double xout = se2->getX() + rctrl->values[0]*duration*cos(se2->getYaw());
    double yout = se2->getY() + rctrl->values[0]*duration*sin(se2->getYaw());
    double yawout = se2->getYaw() + rctrl->values[1];

    ob::SE2StateSpace::StateType* se2out = result->as<ob::SE2StateSpace::StateType>();
    se2out->setXY(xout, yout);
    se2out->setYaw(yawout);

    ob::SO2StateSpace::StateType* so2out = se2out->as<ob::SO2StateSpace::StateType>(1);
    ob::SO2StateSpace SO2;
    SO2.enforceBounds (so2out);
}

void plan(void)
{
    // construct the state space we are planning in
    ob::StateSpacePtr space(new ob::SE2StateSpace());

    // set the bounds for the R^2 part of SE(2)
    ob::RealVectorBounds bounds(2);
    bounds.setLow(0);
    bounds.setHigh(2);

    space->as<ob::SE2StateSpace>()->setBounds(bounds);

    // create triangulation that ignores obstacle and respects propositions
    MyDecomposition* ptd = new MyDecomposition(bounds);
    // helper method that adds an obstacle, as well as three propositions p0,p1,p2
    addObstaclesAndPropositions(ptd);
    ptd->setup();
    oc::PropositionalDecompositionPtr pd(ptd);

    // create a control space
    oc::ControlSpacePtr cspace(new oc::RealVectorControlSpace(space, 2));

    // set the bounds for the control space
    ob::RealVectorBounds cbounds(2);
    cbounds.setLow(-.5);
    cbounds.setHigh(.5);

    cspace->as<oc::RealVectorControlSpace>()->setBounds(cbounds);

    oc::SpaceInformationPtr si(new oc::SpaceInformation(space, cspace));
    si->setStateValidityChecker(boost::bind(&isStateValid, si.get(), ptd, _1));
    si->setStatePropagator(boost::bind(&propagate, _1, _2, _3, _4));
    si->setPropagationStepSize(0.025);

    //LTL co-safety sequencing formula: visit p2,p0 in that order
    std::vector<unsigned int> sequence(2);
    sequence[0] = 2;
    sequence[1] = 0;
    oc::AutomatonPtr cosafety = oc::Automaton::SequenceAutomaton(3, sequence);

    //LTL safety avoidance formula: never visit p1
    std::vector<unsigned int> toAvoid(1);
    toAvoid[0] = 1;
    oc::AutomatonPtr safety = oc::Automaton::AvoidanceAutomaton(3, toAvoid);

    //construct product graph (propDecomp x A_{cosafety} x A_{safety})
    oc::ProductGraphPtr product(new oc::ProductGraph(pd, cosafety, safety));

    // LTLSpaceInformation creates a hybrid space of robot state space x product graph.
    // It takes the validity checker from SpaceInformation and expands it to one that also
    // rejects any hybrid state containing rejecting automaton states.
    // It takes the state propagator from SpaceInformation and expands it to one that
    // follows continuous propagation with setting the next decomposition region
    // and automaton states accordingly.
    //
    // The robot state space, given by SpaceInformation, is referred to as the "lower space".
    oc::LTLSpaceInformationPtr ltlsi(new oc::LTLSpaceInformation(si, product));

    // LTLProblemDefinition creates a goal in hybrid space, corresponding to any
    // state in which both automata are accepting
    ob::LTLProblemDefinitionPtr pdef(new ob::LTLProblemDefinition(ltlsi));

    // create a start state
    ob::ScopedState<ob::SE2StateSpace> start(space);
    start->setX(0.2);
    start->setY(0.2);
    start->setYaw(0.0);

    // addLowerStartState accepts a state in lower space, expands it to its
    // corresponding hybrid state (decomposition region containing the state, and
    // starting states in both automata), and adds that as an official start state.
    pdef->addLowerStartState(start.get());

    //LTL planner (input: LTL space information, product automaton)
    oc::LTLPlanner* ltlPlanner = new oc::LTLPlanner(ltlsi, product);
    ltlPlanner->setProblemDefinition(pdef);

    // attempt to solve the problem within thirty seconds of planning time
    // considering the above cosafety/safety automata, a solution path is any
    // path that visits p2 followed by p0 while avoiding obstacles and avoiding p1.
    ob::PlannerStatus solved = ltlPlanner->as<ob::Planner>()->solve(30.0);

    if (solved)
    {
        std::cout << "Found solution:" << std::endl;
        // The path returned by LTLProblemDefinition is through hybrid space.
        // getLowerSolutionPath() projects it down into the original robot state space
        // that we handed to LTLSpaceInformation.
        pdef->getLowerSolutionPath()->print(std::cout);
    }
    else
        std::cout << "No solution found" << std::endl;
}

int main(int, char **)
{
    plan();
    return 0;
}
<|endoftext|>


<commit_before>// Copyright (c) 2003 Daniel Wallin and Arvid Norberg

// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
// OR OTHER DEALINGS IN THE SOFTWARE.

#define LUABIND_BUILDING

#include <luabind/detail/class_rep.hpp>
#include <luabind/detail/object_rep.hpp>
#include <luabind/detail/operator_id.hpp>

#include <cstring>

namespace luabind { namespace detail
{

    // dest is a function that is called to delete the c++ object this struct holds
    object_rep::object_rep(instance_holder* instance, class_rep* crep_)
        : m_instance(instance)
        , m_classrep(crep_)
        , m_dependency_cnt(0)
    {}

    object_rep::~object_rep()
    {
        if (!m_instance)
            return;
        m_instance->~instance_holder();
        deallocate(m_instance);
    }

    void object_rep::add_dependency(lua_State* L, int index)
    {
        assert(m_dependency_cnt < sizeof(object_rep));

        void* key = reinterpret_cast<char*>(this) + m_dependency_cnt;

        lua_pushlightuserdata(L, key);
        lua_pushvalue(L, index);
        lua_rawset(L, LUA_REGISTRYINDEX);

        ++m_dependency_cnt;
    }

    void object_rep::release_dependency_refs(lua_State* L)
    {
        for (std::size_t i = 0; i < m_dependency_cnt; ++i)
        {
            void* key = reinterpret_cast<char*>(this) + i;
            lua_pushlightuserdata(L, key);
            lua_pushnil(L);
            lua_rawset(L, LUA_REGISTRYINDEX);
        }
    }

    static int destroy_instance(lua_State* L)
    {
        object_rep* instance = static_cast<object_rep*>(lua_touserdata(L, 1));

        lua_pushliteral(L, "__finalize");
        lua_gettable(L, 1);

        if (lua_isnil(L, -1))
        {
            lua_pop(L, 1);
        }
        else
        {
            lua_pushvalue(L, 1);
            lua_call(L, 1, 0);
        }

        instance->release_dependency_refs(L);
        instance->~object_rep();

        lua_pushnil(L);
        lua_setmetatable(L, 1);
        return 0;
    }

    namespace
    {

      int set_instance_value(lua_State* L)
      {
          lua_getuservalue(L, 1);
          lua_pushvalue(L, 2);
          lua_rawget(L, -2);

          if (lua_isnil(L, -1) && lua_getmetatable(L, -2))
          {
              lua_pushvalue(L, 2);
              lua_rawget(L, -2);
              lua_replace(L, -3);
              lua_pop(L, 1);
          }

          if (lua_tocfunction(L, -1) == &property_tag && lua_tocfunction(L, 3) != &property_tag)
          {
              // this member is a property, extract the "set" function and call it.
              lua_getupvalue(L, -1, 2);

              if (lua_isnil(L, -1))
              {
                  lua_pushfstring(L, "property '%s' is read only", lua_tostring(L, 2));
                  lua_error(L);
              }

              lua_pushvalue(L, 1);
              lua_pushvalue(L, 3);
              lua_call(L, 2, 0);
              return 0;
          }

          lua_pop(L, 1);

          if (!lua_getmetatable(L, 4))
          {
              lua_newtable(L);
              lua_pushvalue(L, -1);
              lua_setuservalue(L, 1);
              lua_pushvalue(L, 4);
              lua_setmetatable(L, -2);
          }
          else
          {
              lua_pop(L, 1);
          }

          lua_pushvalue(L, 2);
          lua_pushvalue(L, 3);
          lua_rawset(L, -3);

          return 0;
      }

      int get_instance_value(lua_State* L)
      {
          lua_getuservalue(L, 1);
          lua_pushvalue(L, 2);
          lua_rawget(L, -2);

          if (lua_isnil(L, -1) && lua_getmetatable(L, -2))
          {
              lua_pushvalue(L, 2);
              lua_rawget(L, -2);
          }

          if (lua_tocfunction(L, -1) == &property_tag)
          {
              // this member is a property, extract the "get" function and call it.
              lua_getupvalue(L, -1, 1);
              lua_pushvalue(L, 1);
              lua_call(L, 1, 1);
          }

          return 1;
      }

      int dispatch_operator(lua_State* L)
      {
          int const name_upvalue = lua_upvalueindex(1);
          for (int i = 0; i < 2; ++i)
          {
              if (get_instance(L, 1 + i))
              {
                  int nargs = lua_gettop(L);

                  lua_pushvalue(L, name_upvalue); // operator name
                  // instance[operator name] (via get_instance_value / __index)
                  lua_gettable(L, 1 + i);

                  if (lua_isnil(L, -1))
                  {
                      lua_pop(L, 1);
                      continue;
                  }

                  lua_insert(L, 1); // move the function to the bottom

                  bool const is_unary = lua_toboolean(L, lua_upvalueindex(2)) ?
                      true : false; // Avoid MSVC "performance warning".

                  nargs = is_unary ? 1 : nargs;

                  if (is_unary) // remove trailing nil
                    lua_remove(L, 3);

                  lua_call(L, nargs, LUA_MULTRET);
                  return lua_gettop(L);
              }
          }
          object_rep* inst = get_instance(L, 1);
          char const* const_s = inst->is_const() ? "const " : "";
          char const* cls_name = inst->crep()->name();
          char const* op_name = lua_tostring(L, name_upvalue);

          if (std::strcmp(op_name, "__tostring") == 0) {
              lua_pushfstring(L, "%s%s object: %p",
                  const_s, cls_name, static_cast<void*>(inst));
              return 1;
          }
          lua_pushfstring(L, "%sclass %s: no %s operator defined.",
              const_s, cls_name, op_name);
          return lua_error(L);
      }

    } // namespace unnamed

    LUABIND_API void push_instance_metatable(lua_State* L)
    {
        // One sequence entry for the tag, 3 non-sequence entries for
        // __gc, __index and __newindex and one more for each operator.
        lua_createtable(L, 1, 4 + number_of_operators);

        // This is used as a tag to determine if a userdata is a luabind
        // instance. We use a numeric key and a cclosure for fast comparision.
        lua_pushcfunction(L, get_instance_value);
        lua_rawseti(L, -2, 1);

        lua_pushliteral(L, "__gc");
        lua_pushcfunction(L, destroy_instance);
        lua_rawset(L, -3);

        lua_pushliteral(L, "__index");
        lua_pushcfunction(L, get_instance_value);
        lua_rawset(L, -3);

        lua_pushliteral(L, "__newindex");
        lua_pushcfunction(L, set_instance_value);
        lua_rawset(L, -3);

        // Direct calls to metamethods cannot be allowed, because the
        // callee trusts the caller to pass arguments of the right type.
        lua_pushliteral(L, "__metatable");
        lua_pushboolean(L, true);
        lua_rawset(L, -3);

        for (int op = 0; op < number_of_operators; ++op)
        {
            lua_pushstring(L, get_operator_name(op));
            lua_pushvalue(L, -1);
            lua_pushboolean(L, op == op_unm || op == op_len); // Unary?
            lua_pushcclosure(L, &dispatch_operator, 2);
            lua_rawset(L, -3);
        }
    }

    LUABIND_API object_rep* get_instance(lua_State* L, int index)
    {
        object_rep* result = static_cast<object_rep*>(lua_touserdata(L, index));

        if (!result || !lua_getmetatable(L, index))
            return 0;

        lua_rawgeti(L, -1, 1);

        if (lua_tocfunction(L, -1) != &get_instance_value)
            result = 0;

        lua_pop(L, 2);

        return result;
    }

    LUABIND_API object_rep* push_new_instance(lua_State* L, class_rep* cls)
    {
        void* storage = lua_newuserdata(L, sizeof(object_rep));
        object_rep* result = new (storage) object_rep(0, cls);
        cls->get_table(L);
        lua_setuservalue(L, -2);
        lua_rawgeti(L, LUA_REGISTRYINDEX, cls->metatable_ref());
        lua_setmetatable(L, -2);
        return result;
    }

}}
<commit_msg>Correct wrong comment.<commit_after>// Copyright (c) 2003 Daniel Wallin and Arvid Norberg

// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
// OR OTHER DEALINGS IN THE SOFTWARE.

#define LUABIND_BUILDING

#include <luabind/detail/class_rep.hpp>
#include <luabind/detail/object_rep.hpp>
#include <luabind/detail/operator_id.hpp>

#include <cstring>

namespace luabind { namespace detail
{

    // dest is a function that is called to delete the c++ object this struct holds
    object_rep::object_rep(instance_holder* instance, class_rep* crep_)
        : m_instance(instance)
        , m_classrep(crep_)
        , m_dependency_cnt(0)
    {}

    object_rep::~object_rep()
    {
        if (!m_instance)
            return;
        m_instance->~instance_holder();
        deallocate(m_instance);
    }

    void object_rep::add_dependency(lua_State* L, int index)
    {
        assert(m_dependency_cnt < sizeof(object_rep));

        void* key = reinterpret_cast<char*>(this) + m_dependency_cnt;

        lua_pushlightuserdata(L, key);
        lua_pushvalue(L, index);
        lua_rawset(L, LUA_REGISTRYINDEX);

        ++m_dependency_cnt;
    }

    void object_rep::release_dependency_refs(lua_State* L)
    {
        for (std::size_t i = 0; i < m_dependency_cnt; ++i)
        {
            void* key = reinterpret_cast<char*>(this) + i;
            lua_pushlightuserdata(L, key);
            lua_pushnil(L);
            lua_rawset(L, LUA_REGISTRYINDEX);
        }
    }

    static int destroy_instance(lua_State* L)
    {
        object_rep* instance = static_cast<object_rep*>(lua_touserdata(L, 1));

        lua_pushliteral(L, "__finalize");
        lua_gettable(L, 1);

        if (lua_isnil(L, -1))
        {
            lua_pop(L, 1);
        }
        else
        {
            lua_pushvalue(L, 1);
            lua_call(L, 1, 0);
        }

        instance->release_dependency_refs(L);
        instance->~object_rep();

        lua_pushnil(L);
        lua_setmetatable(L, 1);
        return 0;
    }

    namespace
    {

      int set_instance_value(lua_State* L)
      {
          lua_getuservalue(L, 1);
          lua_pushvalue(L, 2);
          lua_rawget(L, -2);

          if (lua_isnil(L, -1) && lua_getmetatable(L, -2))
          {
              lua_pushvalue(L, 2);
              lua_rawget(L, -2);
              lua_replace(L, -3);
              lua_pop(L, 1);
          }

          if (lua_tocfunction(L, -1) == &property_tag && lua_tocfunction(L, 3) != &property_tag)
          {
              // this member is a property, extract the "set" function and call it.
              lua_getupvalue(L, -1, 2);

              if (lua_isnil(L, -1))
              {
                  lua_pushfstring(L, "property '%s' is read only", lua_tostring(L, 2));
                  lua_error(L);
              }

              lua_pushvalue(L, 1);
              lua_pushvalue(L, 3);
              lua_call(L, 2, 0);
              return 0;
          }

          lua_pop(L, 1);

          if (!lua_getmetatable(L, 4))
          {
              lua_newtable(L);
              lua_pushvalue(L, -1);
              lua_setuservalue(L, 1);
              lua_pushvalue(L, 4);
              lua_setmetatable(L, -2);
          }
          else
          {
              lua_pop(L, 1);
          }

          lua_pushvalue(L, 2);
          lua_pushvalue(L, 3);
          lua_rawset(L, -3);

          return 0;
      }

      int get_instance_value(lua_State* L)
      {
          lua_getuservalue(L, 1);
          lua_pushvalue(L, 2);
          lua_rawget(L, -2);

          if (lua_isnil(L, -1) && lua_getmetatable(L, -2))
          {
              lua_pushvalue(L, 2);
              lua_rawget(L, -2);
          }

          if (lua_tocfunction(L, -1) == &property_tag)
          {
              // this member is a property, extract the "get" function and call it.
              lua_getupvalue(L, -1, 1);
              lua_pushvalue(L, 1);
              lua_call(L, 1, 1);
          }

          return 1;
      }

      int dispatch_operator(lua_State* L)
      {
          int const name_upvalue = lua_upvalueindex(1);
          for (int i = 0; i < 2; ++i)
          {
              if (get_instance(L, 1 + i))
              {
                  int nargs = lua_gettop(L);

                  lua_pushvalue(L, name_upvalue); // operator name
                  // instance[operator name] (via get_instance_value / __index)
                  lua_gettable(L, 1 + i);

                  if (lua_isnil(L, -1))
                  {
                      lua_pop(L, 1);
                      continue;
                  }

                  lua_insert(L, 1); // move the function to the bottom

                  bool const is_unary = lua_toboolean(L, lua_upvalueindex(2)) ?
                      true : false; // Avoid MSVC "performance warning".

                  nargs = is_unary ? 1 : nargs;

                  if (is_unary) // remove trailing nil
                    lua_remove(L, 3);

                  lua_call(L, nargs, LUA_MULTRET);
                  return lua_gettop(L);
              }
          }
          object_rep* inst = get_instance(L, 1);
          char const* const_s = inst->is_const() ? "const " : "";
          char const* cls_name = inst->crep()->name();
          char const* op_name = lua_tostring(L, name_upvalue);

          if (std::strcmp(op_name, "__tostring") == 0) {
              lua_pushfstring(L, "%s%s object: %p",
                  const_s, cls_name, static_cast<void*>(inst));
              return 1;
          }
          lua_pushfstring(L, "%sclass %s: no %s operator defined.",
              const_s, cls_name, op_name);
          return lua_error(L);
      }

    } // namespace unnamed

    LUABIND_API void push_instance_metatable(lua_State* L)
    {
        // One sequence entry for the tag, 4 non-sequence entries for
        // __gc, __index, __newindex and __metatable and
        // one more for each operator.
        lua_createtable(L, 1, 4 + number_of_operators);

        // This is used as a tag to determine if a userdata is a luabind
        // instance. We use a numeric key and a cclosure for fast comparision.
        lua_pushcfunction(L, get_instance_value);
        lua_rawseti(L, -2, 1);

        lua_pushliteral(L, "__gc");
        lua_pushcfunction(L, destroy_instance);
        lua_rawset(L, -3);

        lua_pushliteral(L, "__index");
        lua_pushcfunction(L, get_instance_value);
        lua_rawset(L, -3);

        lua_pushliteral(L, "__newindex");
        lua_pushcfunction(L, set_instance_value);
        lua_rawset(L, -3);

        // Direct calls to metamethods cannot be allowed, because the
        // callee trusts the caller to pass arguments of the right type.
        lua_pushliteral(L, "__metatable");
        lua_pushboolean(L, true);
        lua_rawset(L, -3);

        for (int op = 0; op < number_of_operators; ++op)
        {
            lua_pushstring(L, get_operator_name(op));
            lua_pushvalue(L, -1);
            lua_pushboolean(L, op == op_unm || op == op_len); // Unary?
            lua_pushcclosure(L, &dispatch_operator, 2);
            lua_rawset(L, -3);
        }
    }

    LUABIND_API object_rep* get_instance(lua_State* L, int index)
    {
        object_rep* result = static_cast<object_rep*>(lua_touserdata(L, index));

        if (!result || !lua_getmetatable(L, index))
            return 0;

        lua_rawgeti(L, -1, 1);

        if (lua_tocfunction(L, -1) != &get_instance_value)
            result = 0;

        lua_pop(L, 2);

        return result;
    }

    LUABIND_API object_rep* push_new_instance(lua_State* L, class_rep* cls)
    {
        void* storage = lua_newuserdata(L, sizeof(object_rep));
        object_rep* result = new (storage) object_rep(0, cls);
        cls->get_table(L);
        lua_setuservalue(L, -2);
        lua_rawgeti(L, LUA_REGISTRYINDEX, cls->metatable_ref());
        lua_setmetatable(L, -2);
        return result;
    }

}}
<|endoftext|>


<commit_before>/**********************************************************************
 * $Id$
 *
 * GEOS - Geometry Engine Open Source
 * http://geos.refractions.net
 *
 * Copyright (C) 2001-2002 Vivid Solutions Inc.
 * Copyright (C) 2005 Refractions Research Inc.
 *
 * This is free software; you can redistribute and/or modify it under
 * the terms of the GNU Lesser General Public Licence as published
 * by the Free Software Foundation.
 * See the COPYING file for more information.
 *
 **********************************************************************
 *
 * Represents a homogeneous coordinate in a 2-D coordinate space.
 * HCoordinate are used as a clean way
 * of computing intersections between line segments.
 *
 **********************************************************************/

#include <geos/algorithm/HCoordinate.h>
#include <geos/algorithm/NotRepresentableException.h>
#include <geos/geom/Coordinate.h>
#include <geos/platform.h>

#include <memory>

using namespace std;
using namespace geos::geom;

namespace geos {
namespace algorithm { // geos.algorithm

/*
 * Computes the (approximate) intersection point between two line segments
 * using homogeneous coordinates.
 *
 * Note that this algorithm is
 * not numerically stable; i.e. it can produce intersection points which
 * lie outside the envelope of the line segments themselves.  In order
 * to increase the precision of the calculation input points should be
 * normalized before passing them to this routine.
 */
void
HCoordinate::intersection(const Coordinate &p1, const Coordinate &p2,
	const Coordinate &q1, const Coordinate &q2, Coordinate &ret)
{
#if 1
	auto_ptr<HCoordinate> intHCoord(new HCoordinate(
		HCoordinate(HCoordinate(p1),HCoordinate(p2)),
		HCoordinate(HCoordinate(q1),HCoordinate(q2))
	));
#else
	HCoordinate intHCoord(
		HCoordinate(HCoordinate(p1),HCoordinate(p2)),
		HCoordinate(HCoordinate(q1),HCoordinate(q2))
	);
#endif

	intHCoord->getCoordinate(ret);
}

HCoordinate::HCoordinate()
{
	x = 0.0;
	y = 0.0;
	w = 1.0;
}

HCoordinate::HCoordinate(double _x, double _y, double _w)
{
	x = _x;
	y = _y;
	w = _w;
}

HCoordinate::HCoordinate(const Coordinate& p)
{
	x = p.x;
	y = p.y;
	w = 1.0;
}

HCoordinate::HCoordinate(const HCoordinate &p1, const HCoordinate &p2)
{
	x = p1.y*p2.w - p2.y*p1.w;
	y = p2.x*p1.w - p1.x*p2.w;
	w = p1.x*p2.y - p2.x*p1.y;
}

double
HCoordinate::getX() const
{
	double a = x/w;
	if (!FINITE(a))
	{
		throw  NotRepresentableException();
	}
	return a;
}

double
HCoordinate::getY() const
{
	double a = y/w;
	if (!FINITE(a))
	{
		throw  NotRepresentableException();
	}
	return a;
}

void
HCoordinate::getCoordinate(Coordinate &ret) const
{
	ret=Coordinate(getX(),getY());
	//return new Coordinate(getX(),getY());
}

} // namespace geos.algorithm
} // namespace geos

/**********************************************************************
 * $Log$
 * Revision 1.18  2006/03/21 11:12:23  strk
 * Cleanups: headers inclusion and Log section
 *
 * Revision 1.17  2006/03/09 16:46:45  strk
 * geos::geom namespace definition, first pass at headers split
 **********************************************************************/

<commit_msg>NotRepresentable condition detected using finite() from <cmath> rather then using FINITE() macro. Made ::intersection() body more readable.<commit_after>/**********************************************************************
 * $Id$
 *
 * GEOS - Geometry Engine Open Source
 * http://geos.refractions.net
 *
 * Copyright (C) 2001-2002 Vivid Solutions Inc.
 * Copyright (C) 2005 Refractions Research Inc.
 *
 * This is free software; you can redistribute and/or modify it under
 * the terms of the GNU Lesser General Public Licence as published
 * by the Free Software Foundation.
 * See the COPYING file for more information.
 *
 **********************************************************************
 *
 * Represents a homogeneous coordinate in a 2-D coordinate space.
 * HCoordinate are used as a clean way
 * of computing intersections between line segments.
 *
 **********************************************************************/

#include <geos/algorithm/HCoordinate.h>
#include <geos/algorithm/NotRepresentableException.h>
#include <geos/geom/Coordinate.h>
#include <geos/platform.h>

#include <memory>
#include <cmath> // for finite()

using namespace std;
using namespace geos::geom;

namespace geos {
namespace algorithm { // geos.algorithm

/*
 * Computes the (approximate) intersection point between two line segments
 * using homogeneous coordinates.
 *
 * Note that this algorithm is
 * not numerically stable; i.e. it can produce intersection points which
 * lie outside the envelope of the line segments themselves.  In order
 * to increase the precision of the calculation input points should be
 * normalized before passing them to this routine.
 */
void
HCoordinate::intersection(const Coordinate &p1, const Coordinate &p2,
	const Coordinate &q1, const Coordinate &q2, Coordinate &ret)
{
        HCoordinate hc1p1(p1);
        HCoordinate hc1p2(p2);
        HCoordinate hc1(hc1p1, hc1p2);

        HCoordinate hc2q1(q1);
        HCoordinate hc2q2(q2);
        HCoordinate hc2(hc2q1, hc2q2);

        HCoordinate intHCoord(hc1,hc2);

        intHCoord.getCoordinate(ret);

}

HCoordinate::HCoordinate()
{
	x = 0.0;
	y = 0.0;
	w = 1.0;
}

HCoordinate::HCoordinate(double _x, double _y, double _w)
{
	x = _x;
	y = _y;
	w = _w;
}

HCoordinate::HCoordinate(const Coordinate& p)
{
	x = p.x;
	y = p.y;
	w = 1.0;
}

HCoordinate::HCoordinate(const HCoordinate &p1, const HCoordinate &p2)
{
	x = p1.y*p2.w - p2.y*p1.w;
	y = p2.x*p1.w - p1.x*p2.w;
	w = p1.x*p2.y - p2.x*p1.y;
}

double
HCoordinate::getX() const
{
	double a = x/w;

	// finite() also checks for NaN
	if ( ! finite(a) )
	{
		throw  NotRepresentableException();
	}
	return a;
}

double
HCoordinate::getY() const
{
	double a = y/w;

	// finite() also checks for NaN
	if ( ! finite(a) )
	{
		throw  NotRepresentableException();
	}
	return a;
}

void
HCoordinate::getCoordinate(Coordinate &ret) const
{
	ret=Coordinate(getX(),getY());
	//return new Coordinate(getX(),getY());
}

} // namespace geos.algorithm
} // namespace geos

/**********************************************************************
 * $Log$
 * Revision 1.19  2006/04/04 11:28:12  strk
 * NotRepresentable condition detected using finite() from <cmath>
 * rather then using FINITE() macro. Made ::intersection() body
 * more readable.
 *
 * Revision 1.18  2006/03/21 11:12:23  strk
 * Cleanups: headers inclusion and Log section
 *
 * Revision 1.17  2006/03/09 16:46:45  strk
 * geos::geom namespace definition, first pass at headers split
 **********************************************************************/

<|endoftext|>