text:
/* SPDX-License-Identifier: BSD-3-Clause */
/* Copyright © 2019 Fragcolor Pte. Ltd. */

// ASIO must go first!!
#include <boost/asio.hpp>

#include "../runtime.hpp"
#include "shared.hpp"
#include "utility.hpp"
#include <boost/lockfree/queue.hpp>
#include <thread>

using boost::asio::ip::udp;

namespace chainblocks {
namespace Network {
constexpr uint32_t SocketCC = 'netS';

struct SocketData {
  udp::socket *socket;
  udp::endpoint *endpoint;
};

struct NetworkBase {
  BlocksVar _blks{};

  static inline Type SocketInfo{
      {CBType::Object, {.object = {.vendorId = CoreCC, .typeId = SocketCC}}}};

  static inline boost::asio::io_context _io_context;
  static inline int64_t _io_context_refc = 0;

  ParamVar _addr{Var("localhost")};
  ParamVar _port{Var(9191)};

  // Every server/client will share same context, so sharing the same recv
  // buffer is possible and nice!
  ThreadShared<std::array<char, 0xFFFF>> _recv_buffer;

  CBVar *_socketVar = nullptr;
  SocketData _socket{};

  static inline ParamsInfo params = ParamsInfo(
      ParamsInfo::Param(
          "Address", CBCCSTR("The local bind address or the remote address."),
          CoreInfo::StringOrStringVar),
      ParamsInfo::Param(
          "Port",
          CBCCSTR("The port to bind if server or to connect to if client."),
          CoreInfo::IntOrIntVar),
      ParamsInfo::Param(
          "Receive", CBCCSTR("The flow to execute when a packet is received."),
          CoreInfo::BlocksOrNone));

  static CBParametersInfo parameters() { return CBParametersInfo(params); }

  static void setup() {
    if (_io_context_refc == 0) {
      auto worker = std::thread([] {
        // Force run to run even without work
        boost::asio::executor_work_guard<boost::asio::io_context::executor_type>
            g = boost::asio::make_work_guard(_io_context);
        try {
          // CBLOG_DEBUG("Boost asio context running...");
          _io_context.run();
        } catch (...) {
          CBLOG_ERROR("Boost asio context run failed.");
        }
        // CBLOG_DEBUG("Boost asio context exiting...");
      });
      worker.detach();
    }
    _io_context_refc++;
  }

  void destroy() {
    // defer all in the context or we will crash!
    if (_io_context_refc > 0) {
      boost::asio::post(_io_context, []() {
        _io_context_refc--;
        if (_io_context_refc == 0) {
          // allow end/thread exit
          _io_context.stop();
        }
      });
    }
  }

  void cleanup() {
    // defer all in the context or we will crash!
    if (_socket.socket) {
      auto socket = _socket.socket;
      boost::asio::post(_io_context, [socket]() {
        if (socket) {
          socket->close();
          delete socket;
        }
      });

      _socket.socket = nullptr;
      _socket.endpoint = nullptr;
    }

    // clean context vars
    if (_socketVar) {
      releaseVariable(_socketVar);
      _socketVar = nullptr;
    }

    _blks.cleanup();
    _addr.cleanup();
    _port.cleanup();
  }

  void warmup(CBContext *context) {
    _addr.warmup(context);
    _port.warmup(context);
    _blks.warmup(context);
  }

  static CBTypesInfo inputTypes() { return CoreInfo::AnyType; }

  static CBTypesInfo outputTypes() { return CoreInfo::AnyType; }

  CBTypeInfo compose(CBInstanceData &data) {
    // inject our special context vars
    auto endpointInfo =
        ExposedInfo::Variable("Network.Socket", CBCCSTR("The active socket."),
                              CBTypeInfo(SocketInfo));
    chainblocks::arrayPush(data.shared, endpointInfo);
    _blks.compose(data);
    return data.inputType;
  }

  void setParam(int index, const CBVar &value) {
    switch (index) {
    case 0:
      _addr = value;
      break;
    case 1:
      _port = value;
      break;
    case 2:
      _blks = value;
      break;
    default:
      break;
    }
  }

  CBVar getParam(int index) {
    switch (index) {
    case 0:
      return _addr;
    case 1:
      return _port;
    case 2:
      return _blks;
    default:
      return Var::Empty;
    }
  }

  struct Reader {
    char *buffer;
    size_t offset;
    size_t max;

    Reader(char *buf, size_t size) : buffer(buf), offset(0), max(size) {}

    void operator()(uint8_t *buf, size_t size) {
      auto newOffset = offset + size;
      if (newOffset > max) {
        throw ActivationError("Overflow requested");
      }
      memcpy(buf, buffer + offset, size);
      offset = newOffset;
    }
  };

  struct Writer {
    char *buffer;
    size_t offset;
    size_t max;

    Writer(char *buf, size_t size) : buffer(buf), offset(0), max(size) {}

    void operator()(const uint8_t *buf, size_t size) {
      auto newOffset = offset + size;
      if (newOffset > max) {
        throw ActivationError("Overflow requested");
      }
      memcpy(buffer + offset, buf, size);
      offset = newOffset;
    }
  };

  void setSocket(CBContext *context) {
    if (!_socketVar) {
      _socketVar = referenceVariable(context, "Network.Socket");
    }
    auto rc = _socketVar->refcount;
    auto rcflag = _socketVar->flags & CBVAR_FLAGS_REF_COUNTED;
    *_socketVar = Var::Object(&_socket, CoreCC, SocketCC);
    _socketVar->refcount = rc;
    _socketVar->flags |= rcflag;
  }
};

struct Server : public NetworkBase {
  struct ClientPkt {
    udp::endpoint *remote;
    CBVar payload;
  };

  boost::lockfree::queue<ClientPkt> _queue{16};
  boost::lockfree::queue<ClientPkt> _empty_queue{16};
  udp::endpoint _sender;

  void destroy() {
    // drain queues first
    while (!_queue.empty()) {
      ClientPkt pkt;
      if (_queue.pop(pkt)) {
        delete pkt.remote;
        Serialization::varFree(pkt.payload);
      }
    }

    while (!_empty_queue.empty()) {
      ClientPkt pkt;
      if (_empty_queue.pop(pkt)) {
        delete pkt.remote;
        Serialization::varFree(pkt.payload);
      }
    }

    NetworkBase::destroy();
  }

  Serialization deserial;

  void do_receive() {
    _socket.socket->async_receive_from(
        boost::asio::buffer(&_recv_buffer().front(), _recv_buffer().size()),
        _sender, [this](boost::system::error_code ec, std::size_t bytes_recvd) {
          if (!ec && bytes_recvd > 0) {
            ClientPkt pkt{};

            // try reuse vars internal memory smartly
            if (!_empty_queue.empty()) {
              _empty_queue.pop(pkt);
              *pkt.remote = _sender;
            } else {
              pkt.remote = new udp::endpoint(_sender);
            }

            // deserialize from buffer
            Reader r(&_recv_buffer().front(), bytes_recvd);
            deserial.reset();
            deserial.deserialize(r, pkt.payload);

            // add ready packet to queue
            _queue.push(pkt);

            // keep receiving
            do_receive();
          }
        });
  }

  CBVar activate(CBContext *context, const CBVar &input) {
    if (!_socket.socket) {
      // first activation, let's init
      _socket.socket = new udp::socket(
          _io_context, udp::endpoint(udp::v4(), _port.get().payload.intValue));

      // start receiving
      boost::asio::post(_io_context, [this]() { do_receive(); });
    }

    setSocket(context);

    // receive from ringbuffer and run chains
    while (!_queue.empty()) {
      ClientPkt pkt;
      if (_queue.pop(pkt)) {
        CBVar output{};
        // update remote as pops in context variable
        _socket.endpoint = pkt.remote;
        activateBlocks(CBVar(_blks).payload.seqValue, context, pkt.payload,
                       output);
        // release the var once done
        // will recycle internal buffers
        _empty_queue.push(pkt);
      }
    }

    return input;
  }
};

// Register
RUNTIME_BLOCK(Network, Server);
RUNTIME_BLOCK_setup(Server);
RUNTIME_BLOCK_cleanup(Server);
RUNTIME_BLOCK_warmup(Server);
RUNTIME_BLOCK_destroy(Server);
RUNTIME_BLOCK_inputTypes(Server);
RUNTIME_BLOCK_outputTypes(Server);
RUNTIME_BLOCK_parameters(Server);
RUNTIME_BLOCK_setParam(Server);
RUNTIME_BLOCK_getParam(Server);
RUNTIME_BLOCK_activate(Server);
RUNTIME_BLOCK_compose(Server);
RUNTIME_BLOCK_END(Server);

struct Client : public NetworkBase {
  ExposedInfo _exposedInfo{};

  boost::lockfree::queue<CBVar> _queue{16};
  boost::lockfree::queue<CBVar> _empty_queue{16};

  void destroy() {
    // drain queues first
    while (!_queue.empty()) {
      CBVar v;
      if (_queue.pop(v)) {
        Serialization::varFree(v);
      }
    }

    while (!_empty_queue.empty()) {
      CBVar v;
      if (_empty_queue.pop(v)) {
        Serialization::varFree(v);
      }
    }

    NetworkBase::destroy();
  }

  Serialization deserial;

  void do_receive() {
    _socket.socket->async_receive_from(
        boost::asio::buffer(&_recv_buffer().front(), _recv_buffer().size()),
        _server, [this](boost::system::error_code ec, std::size_t bytes_recvd) {
          if (!ec && bytes_recvd > 0) {
            CBVar v{};

            // try reuse vars internal memory smartly
            if (!_empty_queue.empty()) {
              _empty_queue.pop(v);
            }

            // deserialize from buffer
            Reader r(&_recv_buffer().front(), bytes_recvd);
            deserial.reset();
            deserial.deserialize(r, v);

            // process a packet
            _queue.push(v);

            // keep receiving
            do_receive();
          }
        });
  }

  CBVar activate(CBContext *context, const CBVar &input) {
    if (!_socket.socket) {
      // first activation, let's init
      _socket.socket =
          new udp::socket(_io_context, udp::endpoint(udp::v4(), 0));

      boost::asio::io_service io_service;
      udp::resolver resolver(io_service);
      auto sport = std::to_string(_port.get().payload.intValue);
      udp::resolver::query query(udp::v4(), _addr.get().payload.stringValue,
                                 sport);
      _server = *resolver.resolve(query);

      // start receiving
      boost::asio::post(_io_context, [this]() { do_receive(); });
    }

    setSocket(context);
    // in the case of client we actually set the remote here
    _socket.endpoint = &_server;

    // receive from ringbuffer and run chains
    while (!_queue.empty()) {
      CBVar v;
      if (_queue.pop(v)) {
        CBVar output{};
        activateBlocks(CBVar(_blks).payload.seqValue, context, v, output);
        // release the var once done
        // will recycle internal buffers
        _empty_queue.push(v);
      }
    }

    return input;
  }

  udp::endpoint _server;
};

// Register
RUNTIME_BLOCK(Network, Client);
RUNTIME_BLOCK_setup(Client);
RUNTIME_BLOCK_cleanup(Client);
RUNTIME_BLOCK_warmup(Client);
RUNTIME_BLOCK_destroy(Client);
RUNTIME_BLOCK_inputTypes(Client);
RUNTIME_BLOCK_outputTypes(Client);
RUNTIME_BLOCK_parameters(Client);
RUNTIME_BLOCK_setParam(Client);
RUNTIME_BLOCK_getParam(Client);
RUNTIME_BLOCK_activate(Client);
RUNTIME_BLOCK_compose(Client);
RUNTIME_BLOCK_END(Client);

struct Send {
  // Must take an optional seq of SocketData, to be used properly by server
  // This way we get also a easy and nice broadcast

  ThreadShared<std::array<char, 0xFFFF>> _send_buffer;

  CBVar *_socketVar = nullptr;

  void cleanup() {
    // clean context vars
    if (_socketVar) {
      releaseVariable(_socketVar);
      _socketVar = nullptr;
    }
  }

  SocketData *getSocket(CBContext *context) {
    if (!_socketVar) {
      _socketVar = referenceVariable(context, "Network.Socket");
    }
    assert(_socketVar->payload.objectVendorId == CoreCC);
    assert(_socketVar->payload.objectTypeId == SocketCC);
    return reinterpret_cast<SocketData *>(_socketVar->payload.objectValue);
  }

  static CBTypesInfo inputTypes() { return CoreInfo::AnyType; }
  static CBTypesInfo outputTypes() { return CoreInfo::AnyType; }

  Serialization serializer;

  CBVar activate(CBContext *context, const CBVar &input) {
    auto socket = getSocket(context);
    NetworkBase::Writer w(&_send_buffer().front(), _send_buffer().size());
    serializer.reset();
    auto size = serializer.serialize(input, w);
    // use async, avoid syscalls!
    socket->socket->send_to(boost::asio::buffer(&_send_buffer().front(), size),
                            *socket->endpoint);
    return input;
  }
};

// Register
RUNTIME_BLOCK(Network, Send);
RUNTIME_BLOCK_cleanup(Send);
RUNTIME_BLOCK_inputTypes(Send);
RUNTIME_BLOCK_outputTypes(Send);
RUNTIME_BLOCK_activate(Send);
RUNTIME_BLOCK_END(Send);
}; // namespace Network

void registerNetworkBlocks() {
  REGISTER_BLOCK(Network, Server);
  REGISTER_BLOCK(Network, Client);
  REGISTER_BLOCK(Network, Send);
}
}; // namespace chainblocks

ext: cpp

max_stars_repo_name: Kryptos-FR/chainblocks

max_issues_repo_name: Kryptos-FR/chainblocks

max_forks_repo_name: Kryptos-FR/chainblocks


text:
//==============================================================================
//         Copyright 2003 - 2013   LASMEA UMR 6602 CNRS/Univ. Clermont II
//         Copyright 2009 - 2013   LRI    UMR 8623 CNRS/Univ Paris Sud XI
//
//          Distributed under the Boost Software License, Version 1.0.
//                 See accompanying file LICENSE.txt or copy at
//                     http://www.boost.org/LICENSE_1_0.txt
//==============================================================================
#include <nt2/include/functions/log.hpp>

#include <boost/dispatch/functor/meta/call.hpp>
#include <nt2/sdk/functor/meta/call.hpp>
#include <nt2/sdk/unit/tests/relation.hpp>
#include <nt2/sdk/unit/tests/type_expr.hpp>
#include <complex>
#include <nt2/sdk/complex/complex.hpp>
#include <nt2/sdk/unit/tests/ulp.hpp>
#include <nt2/sdk/unit/tests/basic.hpp>
#include <nt2/sdk/meta/as_integer.hpp>
#include <nt2/sdk/unit/module.hpp>
#include <boost/simd/sdk/config.hpp>

#include <nt2/include/constants/mone.hpp>
#include <nt2/include/constants/mzero.hpp>
#include <nt2/include/constants/one.hpp>
#include <nt2/include/constants/pi.hpp>
#include <nt2/include/constants/pio_2.hpp>
#include <nt2/include/constants/zero.hpp>
#include <nt2/include/constants/inf.hpp>
#include <nt2/include/constants/minf.hpp>
#include <nt2/include/constants/nan.hpp>
#include <nt2/include/constants/i.hpp>

NT2_TEST_CASE_TPL ( log_real,  NT2_REAL_TYPES)
{
  using nt2::log;
  using nt2::tag::log_;
  typedef typename std::complex<T> cT;
  typedef typename nt2::meta::call<log_(cT)>::type r_t;

  // return type conformity test
  NT2_TEST_TYPE_IS(r_t, cT);

  // specific values tests
#ifndef BOOST_SIMD_NO_INVALIDS
  NT2_TEST_ULP_EQUAL(nt2::log(cT(nt2::Minf <T>(), nt2::Mone<T>())), cT(nt2::Inf<T>(), -nt2::Pi<T>()), 0.75);
  NT2_TEST_ULP_EQUAL(nt2::log(nt2::Inf<cT>()), cT(nt2::Inf<T>()), 0.5);
  NT2_TEST_ULP_EQUAL(nt2::log(nt2::Minf<cT>()), cT(nt2::Inf<T>(), nt2::Pi<T>()), 0.5);
  NT2_TEST_ULP_EQUAL(nt2::log(cT(nt2::Nan<T>(), nt2::Zero<T>())),  cT(nt2::Nan<T>()), 0.5);
  NT2_TEST_ULP_EQUAL(nt2::log(cT(nt2::Nan<T>(), nt2::Nan<T>())),  cT(nt2::Nan<T>(), nt2::Nan<T>()), 0.5);
  NT2_TEST_ULP_EQUAL(nt2::log(nt2::Zero<cT>()), cT(nt2::Minf<r_t>()), 0.5);
  NT2_TEST_ULP_EQUAL(nt2::log(nt2::Mzero<cT>()), cT(nt2::Minf<T>()), 0.5);
  NT2_TEST_ULP_EQUAL(nt2::log(cT(nt2::Zero<T>(),  nt2::Zero<T>())),  cT(nt2::Minf<T>(), nt2::Zero<T>()), 0.75);
  NT2_TEST_ULP_EQUAL(nt2::log(cT(nt2::Inf  <T>(), nt2::Zero<T>())),  cT(nt2::Inf<T>(), nt2::Zero<T>()), 0.75);
  NT2_TEST_ULP_EQUAL(nt2::log(cT(nt2::Minf <T>(), nt2::Zero<T>())),  cT(nt2::Inf<T>(), nt2::Pi<T>()), 0.75);
  NT2_TEST_ULP_EQUAL(nt2::log(cT(nt2::Inf  <T>(), nt2::Zero<T>())),  cT(nt2::Inf <T>(), nt2::Zero <T>()), 0.75);
  NT2_TEST_ULP_EQUAL(nt2::log(cT(nt2::One  <T>(), nt2::Inf <T>())), cT(nt2::Inf<T>(), nt2::Pio_2<T>()), 0.75);
  NT2_TEST_ULP_EQUAL(nt2::log(cT(nt2::One  <T>(), nt2::Nan <T>())), cT(nt2::Nan<T>(), nt2::Nan<T>()), 0.75);
  NT2_TEST_ULP_EQUAL(nt2::log(cT(nt2::Inf  <T>(), nt2::One <T>())), cT(nt2::Inf<T>(), nt2::Zero<T>()), 0.75);
  NT2_TEST_ULP_EQUAL(nt2::log(cT(nt2::Minf <T>(), nt2::One<T>())),  cT(nt2::Inf<T>(), nt2::Pi<T>()), 0.75);
  NT2_TEST_ULP_EQUAL(nt2::log(cT(nt2::Inf  <T>(), nt2::One <T>())), cT(nt2::Inf <T>(), nt2::Zero <T>()), 0.75);
  NT2_TEST_ULP_EQUAL(nt2::log(cT(nt2::Minf <T>(), nt2::Inf<T>())),  cT(nt2::Inf <T>(), 3*nt2::Pi<T>()/4), 0.75);
  NT2_TEST_ULP_EQUAL(nt2::log(cT(nt2::Inf  <T>(), nt2::Inf<T>())),  cT(nt2::Inf <T>(), nt2::Pi<T>()/4), 0.75);
  NT2_TEST_ULP_EQUAL(nt2::log(cT(nt2::Minf <T>(), nt2::Nan<T>())),  cT(nt2::Inf <T>(), nt2::Nan<T>()), 0.75);
  NT2_TEST_ULP_EQUAL(nt2::log(cT(nt2::Inf  <T>(), nt2::Nan<T>())),  cT(nt2::Inf <T>(), nt2::Nan<T>()), 0.75);
  NT2_TEST_ULP_EQUAL(nt2::log(cT(nt2::Nan  <T>(), nt2::One<T>())),  cT(nt2::Nan <T>(), nt2::Nan<T>()), 0.75);
  NT2_TEST_ULP_EQUAL(nt2::log(cT(nt2::Nan  <T>(), nt2::Mone<T>())), cT(nt2::Nan <T>(), nt2::Nan<T>()), 0.75);
  NT2_TEST_ULP_EQUAL(nt2::log(cT(nt2::Nan  <T>(), nt2::Inf<T>())),  cT(nt2::Inf <T>(), nt2::Nan<T>()), 0.75);
  NT2_TEST_ULP_EQUAL(nt2::log(cT(nt2::Nan  <T>(), nt2::Nan<T>())),  cT(nt2::Nan <T>(), nt2::Nan<T>()), 0.75);
  NT2_TEST_ULP_EQUAL(nt2::log(cT(nt2::One  <T>(), -nt2::Inf <T>())), cT(nt2::Inf<T>(), -nt2::Pio_2<T>()), 0.75);
  NT2_TEST_ULP_EQUAL(nt2::log(cT(nt2::One  <T>(), -nt2::Nan <T>())), cT(nt2::Nan<T>(), -nt2::Nan<T>()), 0.75);
  NT2_TEST_ULP_EQUAL(nt2::log(cT(nt2::Inf  <T>(), -nt2::One <T>())), cT(nt2::Inf<T>(), -nt2::Zero<T>()), 0.75);
  NT2_TEST_ULP_EQUAL(nt2::log(cT(nt2::Minf <T>(), -nt2::One<T>())),  cT(nt2::Inf<T>(), -nt2::Pi<T>()), 0.75);
  NT2_TEST_ULP_EQUAL(nt2::log(cT(nt2::Inf  <T>(), -nt2::One <T>())), cT(nt2::Inf <T>(), -nt2::Zero <T>()), 0.75);
  NT2_TEST_ULP_EQUAL(nt2::log(cT(nt2::Minf <T>(), -nt2::Inf<T>())),  cT(nt2::Inf <T>(), -3*nt2::Pi<T>()/4), 0.75);
  NT2_TEST_ULP_EQUAL(nt2::log(cT(nt2::Inf  <T>(), -nt2::Inf<T>())),  cT(nt2::Inf <T>(), -nt2::Pi<T>()/4), 0.75);
  NT2_TEST_ULP_EQUAL(nt2::log(cT(nt2::Minf <T>(), -nt2::Nan<T>())),  cT(nt2::Inf <T>(), -nt2::Nan<T>()), 0.75);
  NT2_TEST_ULP_EQUAL(nt2::log(cT(nt2::Inf  <T>(), -nt2::Nan<T>())),  cT(nt2::Inf <T>(), -nt2::Nan<T>()), 0.75);
  NT2_TEST_ULP_EQUAL(nt2::log(cT(nt2::Nan  <T>(), -nt2::One<T>())),  cT(nt2::Nan <T>(), -nt2::Nan<T>()), 0.75);
  NT2_TEST_ULP_EQUAL(nt2::log(cT(nt2::Nan  <T>(), -nt2::Mone<T>())), cT(nt2::Nan <T>(), -nt2::Nan<T>()), 0.75);
  NT2_TEST_ULP_EQUAL(nt2::log(cT(nt2::Nan  <T>(), -nt2::Inf<T>())),  cT(nt2::Inf <T>(), -nt2::Nan<T>()), 0.75);
  NT2_TEST_ULP_EQUAL(nt2::log(cT(nt2::Nan  <T>(), -nt2::Nan<T>())),  cT(nt2::Nan <T>(), -nt2::Nan<T>()), 0.75);
#endif
  NT2_TEST_ULP_EQUAL(nt2::log(nt2::Mone<cT>()), cT(nt2::Zero<T>(), nt2::Pi<T>()), 0.5);
  NT2_TEST_ULP_EQUAL(nt2::log(nt2::One<cT>()), cT(nt2::Zero<r_t>()), 0.5);
  NT2_TEST_ULP_EQUAL(nt2::log(cT(nt2::Zero<T>(), nt2::One<T>())),cT(nt2::Zero<T>(), nt2::Pio_2<T>()), 0.5);
}


text:
#include <NTL/HNF.h>

#include <NTL/new.h>

NTL_START_IMPL

// This implements a variation of an algorithm in
// [P. Domich, R. Kannan and L. Trotter, Math. Oper. Research 12:50-59, 1987].
// I started with the description in Henri Cohen's book, but had to modify
// that because Cohen does not actually keep the numbers reduced modulo
// the determinant, which leads to larger than necessary numbers.
// This modifiaction was put in place in v3.9b.

static
void EuclUpdate(vec_ZZ& u, vec_ZZ& v,
                const ZZ& a, const ZZ& b, const ZZ& c, const ZZ& d,
                const ZZ& M)

{
   long m = u.length();
   long i;

   ZZ M1;
   RightShift(M1, M, 1);

   ZZ t1, t2, t3;

   for (i = 1; i <= m; i++) {
      mul(t1, u(i), a);
      mul(t2, v(i), b);
      add(t1, t1, t2);
      rem(t1, t1, M);
      if (t1 > M1)
         sub(t1, t1, M);

      t3 = t1;

      mul(t1, u(i), c);
      mul(t2, v(i), d);
      add(t1, t1, t2);
      rem(t1, t1, M);
      if (t1 > M1)
         sub(t1, t1, M);

      u(i) = t3;
      v(i) = t1;
   }
}

static
void FixDiag(vec_ZZ& u, const ZZ& a, const vec_ZZ& v, const ZZ& M, long m)
{
   long i;
   ZZ t1;

   for (i = 1; i <= m; i++) {
      mul(t1, a, v(i));
      rem(u(i), t1, M);
   }
}

static
void ReduceW(vec_ZZ& u, const ZZ& a, const vec_ZZ& v, const ZZ& M, long m)
{
   long i;
   ZZ t1, t2;

   for (i = 1; i <= m; i++) {
      mul(t1, a, v(i));
      sub(t2, u(i), t1);
      rem(u(i), t2, M);
   }
}

void HNF(mat_ZZ& W, const mat_ZZ& A_in, const ZZ& D_in)
{
   mat_ZZ A = A_in;

   long n = A.NumRows();
   long m = A.NumCols();

   ZZ D = D_in;
   if (D < 0)
      negate(D, D);

   if (n == 0 || m == 0 || D == 0)
      LogicError("HNF: bad input");

   W.SetDims(m, m);
   clear(W);

   long i, j, k;
   ZZ d, u, v, c1, c2;

   k = n;

   for (i = m; i >= 1; i--) {
      for (j = k-1; j >= 1; j--) {
         if (A(j, i) != 0) {
            XGCD(d, u, v, A(k, i), A(j, i));
            div(c1, A(k, i), d);
            div(c2, A(j, i), d);
            negate(c2, c2);
            EuclUpdate(A(j), A(k), c1, c2, v, u, D);
         }
      }

      XGCD(d, u, v, A(k, i), D);
      FixDiag(W(i), u, A(k), D, i);
      if (W(i, i) == 0) W(i, i) = D;

      for (j = i+1; j <= m; j++) {
         div(c1, W(j, i), W(i, i));
         ReduceW(W(j), c1, W(i), D, i);
      }

      div(D, D, d);
      k--;
   }
}

NTL_END_IMPL

max_stars_repo_name: Brainloop-Security/secret-sharing

max_issues_repo_name: Brainloop-Security/secret-sharing

max_forks_repo_name: Brainloop-Security/secret-sharing


text:
/*=============================================================================
    Copyright (c) 2006-2007 Tobias Schwinger

    Use modification and distribution are subject to the Boost Software
    License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
    http://www.boost.org/LICENSE_1_0.txt).
==============================================================================*/

#include <boost/fusion/functional/adapter/unfused_typed.hpp>
#include <boost/detail/lightweight_test.hpp>

#include <boost/noncopyable.hpp>

#include <boost/mpl/empty_base.hpp>
#include <boost/mpl/identity.hpp>
#include <boost/mpl/placeholders.hpp>

#include <boost/utility/result_of.hpp>

#include <boost/fusion/algorithm/iteration/fold.hpp>

namespace fusion = boost::fusion;
namespace mpl = boost::mpl;
using mpl::placeholders::_;

using boost::noncopyable;

typedef fusion::vector<> types0;
typedef fusion::vector<long &> types1;
typedef fusion::vector<long &,int,char> types3;

template <class Base = boost::mpl::empty_base>
struct test_func
    : Base
{
    template<typename T>
    struct result;

    template <class Self, class Seq>
    struct result< Self(Seq) >
        : mpl::identity<long>
    { };

    template <typename Seq>
    long operator()(Seq const & seq) const
    {
        long state = 0;
        return fusion::fold(seq, state, fold_op());
    }

    template < typename Seq >
    long operator()(Seq const & seq)
    {
        long state = 100;
        return fusion::fold(seq, state, fold_op());
    }

  private:

    struct fold_op
    {
        typedef long result_type;

        template <typename T>
        long operator()(long value, T const & elem) const
        {
          return value + sizeof(T) * elem;
        }

        template <typename T>
        long operator()(long value, T & elem) const
        {
          elem += sizeof(T);
          return value;
        }
    };
};

void result_type_tests()
{
    using boost::is_same;

    typedef fusion::unfused_typed< test_func<>, types0 > t0;
    BOOST_TEST(( is_same< boost::result_of< t0 () >::type, long >::value ));
    typedef fusion::unfused_typed< test_func<>, types1 > t1;
    BOOST_TEST(( is_same< boost::result_of< t1 (long &) >::type, long >::value ));
}

#if defined(BOOST_MSVC) && BOOST_MSVC < 1400
#   define BOOST_TEST_NO_VC71(cond) (void)((cond)?0:1)
#else
#   define BOOST_TEST_NO_VC71(cond) BOOST_TEST(cond)
#endif

void nullary_tests()
{
    test_func<noncopyable> f;
    fusion::unfused_typed< test_func<>, types0 > unfused_func;
    fusion::unfused_typed< test_func<noncopyable> &, types0 > unfused_func_ref(f);
    fusion::unfused_typed< test_func<> const, types0 > unfused_func_c;
    fusion::unfused_typed< test_func<>, types0 > const unfused_func_c2;
    fusion::unfused_typed< test_func<noncopyable> const &, types0 > unfused_func_c_ref(f);

    BOOST_TEST(unfused_func() == 100);
    BOOST_TEST(unfused_func_ref() == 100);
    BOOST_TEST(unfused_func_c() == 0);
    BOOST_TEST(unfused_func_c2() == 0);
    BOOST_TEST(unfused_func_c_ref() == 0);
}

void unary_tests()
{
    test_func<noncopyable> f;
    fusion::unfused_typed< test_func<>, types1 > unfused_func;
    fusion::unfused_typed< test_func<noncopyable> &, types1 > unfused_func_ref(f);
    fusion::unfused_typed< test_func<> const, types1 > unfused_func_c;
    fusion::unfused_typed< test_func<>, types1 > const unfused_func_c2;
    fusion::unfused_typed< test_func<noncopyable> const &, types1 > unfused_func_c_ref(f);

    long lvalue = 1;
    BOOST_TEST_NO_VC71(unfused_func(lvalue) == 100);
    BOOST_TEST(lvalue == 1 + 1*sizeof(lvalue));
    BOOST_TEST(unfused_func_ref(lvalue) == 100);
    BOOST_TEST(lvalue == 1 + 2*sizeof(lvalue));
    BOOST_TEST(unfused_func_c(lvalue) == 0);
    BOOST_TEST(lvalue == 1 + 3*sizeof(lvalue));
    BOOST_TEST(unfused_func_c2(lvalue) == 0);
    BOOST_TEST(lvalue == 1 + 4*sizeof(lvalue));
    BOOST_TEST(unfused_func_c_ref(lvalue) == 0);
    BOOST_TEST(lvalue == 1 + 5*sizeof(lvalue));
}

void ternary_tests()
{
    test_func<noncopyable> f;
    fusion::unfused_typed< test_func<>, types3 > unfused_func;
    fusion::unfused_typed< test_func<noncopyable> &, types3 > unfused_func_ref(f);
    fusion::unfused_typed< test_func<> const, types3 > unfused_func_c;
    fusion::unfused_typed< test_func<>, types3 > const unfused_func_c2;
    fusion::unfused_typed< test_func<noncopyable> const &, types3 > unfused_func_c_ref(f);

    long lvalue = 1;
    static const long expected = 2*sizeof(int) + 7*sizeof(char);
    BOOST_TEST_NO_VC71(unfused_func(lvalue,2,'\007') == 100 + expected);
    BOOST_TEST(lvalue == 1 + 1*sizeof(lvalue));
    BOOST_TEST(unfused_func_ref(lvalue,2,'\007') == 100 + expected);
    BOOST_TEST(lvalue == 1 + 2*sizeof(lvalue));
    BOOST_TEST(unfused_func_c(lvalue,2,'\007') == 0 + expected);
    BOOST_TEST(lvalue == 1 + 3*sizeof(lvalue));
    BOOST_TEST(unfused_func_c2(lvalue,2,'\007') == 0 + expected);
    BOOST_TEST(lvalue == 1 + 4*sizeof(lvalue));
    BOOST_TEST(unfused_func_c_ref(lvalue,2,'\007') == 0 + expected);
    BOOST_TEST(lvalue == 1 + 5*sizeof(lvalue));
}

int main()
{
    result_type_tests();
    nullary_tests();
    unary_tests();
    ternary_tests();

    return boost::report_errors();
}


text:
#ifndef __GENERATE_STATISTICS_HPP__
#define __GENERATE_STATISTICS_HPP__

#include <ostream>
#include <vector>
#include <string>

#include <boost/filesystem.hpp>

#include "settings_t.hpp"

bool generate_statistics(
    std::ostream& out,
    std::ostream& out_log,
    std::ostream& error,
    settings_t &s,
    std::vector<std::string>& hints,
    boost::filesystem::path& world_path,
    boost::filesystem::path& output_path);

#endif /*__GENERATE_STATISTICS_HPP__*/

ext: hpp


text:
#include "cinderjsApp.hpp"
#include "ArrayBufferAllocator.h"
#include "cinder/app/RendererGl.h"

#include <boost/bind.hpp>
#include <boost/thread/thread.hpp>

#include <string.h>
#include <fstream>
#include <sstream>
#include <cerrno>
#include <chrono>
#include <thread>

#ifdef __APPLE__
#include <OpenGL/OpenGL.h>
#endif

// Modules
#include "modules/app.hpp"
#include "modules/gl.hpp"
#include "modules/console.hpp"
#include "modules/text.hpp"
#include "modules/fs.hpp"
#include "modules/vm.hpp"
#include "modules/ray.hpp"
#include "modules/camera.hpp"
#include "modules/shader.hpp"
#include "modules/batch.hpp"
#include "modules/texture.hpp"
#include "modules/glm.hpp"
#include "modules/fbo.hpp"
#include "modules/vbo.hpp"
#include "modules/vao.hpp"
#include "modules/color.hpp"

#include <assert.h>

using namespace ci;
using namespace ci::app;
using namespace std;
using namespace v8;

namespace cjs {

#ifdef DEBUG
volatile bool CinderjsApp::_consoleActive = true;
volatile bool CinderjsApp::_v8StatsActive = true;
volatile bool CinderjsApp::_fpsActive = true;
#else
volatile bool CinderjsApp::_consoleActive = false;
volatile bool CinderjsApp::_v8StatsActive = false;
volatile bool CinderjsApp::_fpsActive = true;
#endif

bool CinderjsApp::sQuitRequested = false;
bool CinderAppBase::shutdownInProgress = false;

v8::Persistent<v8::Object> CinderjsApp::sModuleCache;
v8::Persistent<v8::Array> CinderjsApp::sModuleList;

v8::Persistent<v8::Function> CinderjsApp::sDrawCallback;
v8::Local<v8::Function> CinderjsApp::_fnDrawCallback;
v8::Persistent<v8::Function> CinderjsApp::sEventCallback;

v8::Persistent<v8::Object> CinderjsApp::sEmptyObject;

ConcurrentCircularBuffer<NextFrameFn> CinderjsApp::sExecutionQueue(1024);

Timer CinderjsApp::_mainTimer;
std::function<void(boost::any passOn)> CinderjsApp::_timerCallback;

int CinderjsApp::sGCRuns = 0;
void CinderjsApp::gcPrologueCb(Isolate *isolate, GCType type, GCCallbackFlags flags) {
  sGCRuns++;
  //AppConsole::log("GC Prologue " + std::to_string(sGCRuns));
  std::cout << "GC Prologue " << std::to_string(sGCRuns) << std::endl;
}

/**
 * Handling v8 errors in native land
 * TODO: can be vastly improved
 */
void CinderjsApp::handleV8TryCatch( v8::TryCatch &tryCatch, std::string info ) {
  std::string msg;
  if(tryCatch.StackTrace().IsEmpty()){
    v8::String::Utf8Value except(tryCatch.Exception());
    msg = *except;
  } else {
    v8::String::Utf8Value trace(tryCatch.StackTrace());
    msg = *trace;
  }
  std::string ex = "Uncaught Exception";
  ex.append(" (" + info + "):");
  ex.append(msg);
  #ifdef DEBUG
  std::cout << ex << std::endl;
  #endif
  AppConsole::log( ex );
}

/**
 * Cleanup
 */
void CinderjsApp::cleanup()
{
  shutdownInProgress = true;
  _consoleActive = false;
  mShouldQuit = true;

  std::this_thread::sleep_for(std::chrono::milliseconds(1));

  _eventRun = true;
  cvEventThread.notify_all();

  mEventQueue.cancel();
  sExecutionQueue.cancel();

  // Shutdown v8EventThread
  if( mV8EventThread ) {
    mV8EventThread->join();
    mV8EventThread.reset();
  }

  v8::V8::Dispose();
}

/**
 * Setup
 * If given a *.js file in the command line arguments, it will be run in the main context
 * and can be used to setup things for other scripts or to mockup the main app.
 */
void CinderjsApp::setup()
{
  // Init Console
  AppConsole::initialize();

  mLastEscPressed = getElapsedSeconds();

  // Command line arguments
  vector<std::string> args = getCommandLineArgs();

  mCwd = boost::filesystem::current_path();

  // Check argv arguments
  // TODO: Check for debug flag
  int pos = 0;
  for(std::vector<std::string>::iterator it = args.begin(); it != args.end(); ++it) {
    pos++;
  }

  // clear out the window with black
  gl::clear( Color( 0, 0, 0 ) );

  glRenderer = getRenderer();

  // Get cinder.js main native
  if(cinder_native && sizeof(cinder_native) > 0) {
    std::string mainJS(cinder_native);
    v8Setup(mainJS);
  } else {
    // FATAL: No main entry source
    quit();
  }

}

/**
 * Runs a JS string and prints eventual errors to the AppConsole
 */
v8::Local<v8::Value> CinderjsApp::executeScriptString( std::string scriptStr, Isolate* isolate, v8::Local<v8::Context> context, Handle<String> filename ){
  EscapableHandleScope scope(isolate);

  v8::TryCatch try_catch;

  // Enter the context for compiling and running
  Context::Scope context_scope(context);

  // Create a string containing the JavaScript source code.
  Local<String> source = String::NewFromUtf8( isolate, scriptStr.c_str() );

  // Compile the source code.
  Local<Script> script = Script::Compile( source, filename );

  // Run the script to get the result.
  Local<Value> result = script->Run();

  // Check for script errors
  if(try_catch.HasCaught()){
    String::Utf8Value str(filename);
    handleV8TryCatch(try_catch, "executeScriptString/" + std::string(*str));
  }

  return scope.Escape(result);
}

/**
 * Setup V8
 */
void CinderjsApp::v8Setup( std::string mainJS ){

  // Initialize V8 (implicit initialization was removed in an earlier revision)
  v8::V8::InitializeICU();
  v8::Platform* platform = v8::platform::CreateDefaultPlatform(4);
  v8::V8::InitializePlatform(platform);
  V8::Initialize();

  // Create a new Isolate and make it the current one.
  v8::Isolate::CreateParams create_params;
  create_params.array_buffer_allocator = &ArrayBufferAllocator::the_singleton;
  mIsolate = Isolate::New(create_params);
  v8::Locker lock(mIsolate);
  Isolate::Scope isolate_scope(mIsolate);

  //mIsolate->AddGCPrologueCallback(gcPrologueCb);

  // Setup timer callback
  _timerCallback = [=](boost::any passOn){
    NextFrameFn next = boost::any_cast<NextFrameFn>(passOn);
    sExecutionQueue.pushFront(next);
  };

  // Create a stack-allocated handle scope.
  HandleScope handle_scope(mIsolate);

  // Set general globals for JS
  mGlobal = ObjectTemplate::New();
  mGlobal->Set(v8::String::NewFromUtf8(mIsolate, "__draw__"), v8::FunctionTemplate::New(mIsolate, setDrawCallback));
  mGlobal->Set(v8::String::NewFromUtf8(mIsolate, "__event__"), v8::FunctionTemplate::New(mIsolate, setEventCallback));
  mGlobal->Set(v8::String::NewFromUtf8(mIsolate, "toggleAppConsole"), v8::FunctionTemplate::New(mIsolate, toggleAppConsole));
  mGlobal->Set(v8::String::NewFromUtf8(mIsolate, "toggleV8Stats"), v8::FunctionTemplate::New(mIsolate, toggleV8Stats));
  mGlobal->Set(v8::String::NewFromUtf8(mIsolate, "quit"), v8::FunctionTemplate::New(mIsolate, requestQuit));

  // Timer
  mGlobal->Set(v8::String::NewFromUtf8(mIsolate, "setTimer"), v8::FunctionTemplate::New(mIsolate, setTimer));

  // Setup process object
  v8::Local<v8::ObjectTemplate> processObj = ObjectTemplate::New();
  processObj->Set(v8::String::NewFromUtf8(mIsolate, "nextFrame"), v8::FunctionTemplate::New(mIsolate, nextFrameJS));
  processObj->Set(v8::String::NewFromUtf8(mIsolate, "nativeBinding"), v8::FunctionTemplate::New(mIsolate, NativeBinding));
  // TODO: export process.platform
  // TODO: export process.noDeprecation
  // TODO: export process.throwDeprecation
  // TODO: export process.traceDeprecation
  // TODO: export process.pid
  // TODO: export process.env (environment vars etc.)
  //       -> Empty object for now (placeholer)
  // TODO:
  processObj->Set(v8::String::NewFromUtf8(mIsolate, "env"), ObjectTemplate::New());
  //process.execPath
  processObj->Set(v8::String::NewFromUtf8(mIsolate, "execPath"), v8::String::NewFromUtf8(mIsolate, getAppPath().c_str()));
  processObj->Set(v8::String::NewFromUtf8(mIsolate, "cwd"), v8::String::NewFromUtf8(mIsolate, mCwd.c_str()));
  mGlobal->Set(v8::String::NewFromUtf8(mIsolate, "process"), processObj);

  // TODO: export console[log, error, trace, etc.]

  //
  // Load Modules
  addModule(std::shared_ptr<AppModule>( new AppModule() ));
  addModule(std::shared_ptr<GLModule>( new GLModule() ));
  addModule(std::shared_ptr<ConsoleModule>( new ConsoleModule() ));
  addModule(std::shared_ptr<TextModule>( new TextModule() ));
  addModule(std::shared_ptr<FSModule>( new FSModule() ));
  addModule(std::shared_ptr<VMModule>( new VMModule() ));
  addModule(std::shared_ptr<RayModule>( new RayModule() ));
  addModule(std::shared_ptr<CameraModule>( new CameraModule() ));
  addModule(std::shared_ptr<ShaderModule>( new ShaderModule() ));
  addModule(std::shared_ptr<BatchModule>( new BatchModule() ));
  addModule(std::shared_ptr<TextureModule>( new TextureModule() ));
  addModule(std::shared_ptr<GlmModule>( new GlmModule() ));
  addModule(std::shared_ptr<FBOModule>( new FBOModule() ));
  addModule(std::shared_ptr<VBOModule>( new VBOModule() ));
  addModule(std::shared_ptr<VAOModule>( new VAOModule() ));
  addModule(std::shared_ptr<ColorModule>( new ColorModule() ));

  // Create a new context.
  v8::Local<v8::Context> mMainContext = Context::New(mIsolate, NULL, mGlobal);
  Context::Scope scope(mMainContext);
  pContext.Reset(mIsolate, mMainContext);

  // Get process object instance and set additional values
  Local<Value> processObjInstance = mMainContext->Global()->Get(v8::String::NewFromUtf8(mIsolate, "process"));

  // Initialize module list and set on process
  Local<Array> list = Array::New(mIsolate);
  sModuleList.Reset(mIsolate, list);
  processObjInstance.As<Object>()->Set(v8::String::NewFromUtf8(mIsolate, "modules"), list);

  // Initialize module cache
  Local<Object> obj = Object::New(mIsolate);
  sModuleCache.Reset(mIsolate, obj);
  processObjInstance.As<Object>()->Set(v8::String::NewFromUtf8(mIsolate, "_moduleCache"), obj);

  // add process.argv
  vector<std::string> argv = getCommandLineArgs();

  #ifdef DEBUG
  // For development loading...
  //argv.push_back("/Users/sebastian/Dropbox/+Projects/cinderjs/examples/test.js");
  //argv.push_back("/Users/sebastian/Dropbox/+Projects/cinderjs/examples/particle.js");
  //argv.push_back("/Users/sebastian/Dropbox/+Projects/cinderjs/examples/lines.js");
  //argv.push_back("/Users/sebastian/Dropbox/+Projects/cinderjs/examples/cube/cubes.js");
  //argv.push_back("/Users/sebastian/Dropbox/+Projects/cinderjs/examples/geometry_shader/index.js");
  //argv.push_back("/Users/sebastian/Dropbox/+Projects/cinderjs/examples/ParticleSphereGPU/index.js");
  //argv.push_back("/Users/sebastian/Dropbox/+Projects/cinderjs/examples/physics.js");
  //argv.push_back("/Users/sebastian/Dropbox/+Projects/cinderjs/examples/ray.js");
  //argv.push_back("/Users/sebastian/Dropbox/+Projects/cinderjs/examples/fbo_basic.js");
  //argv.push_back("/Users/sebastian/Dropbox/+Projects/cinderjs/test/weak_callback.js");
  //argv.push_back("/Users/sebastian/Dropbox/+Projects/cinderjs/test/lib/jasmine/runner.js");
  #endif

  // Forward command line arguments to process object, available from js context
  Local<Array> argvArr = Array::New(mIsolate);
  for (int i = 0; i < argv.size(); ++i) {
    argvArr->Set(i, String::NewFromUtf8(mIsolate, argv[i].c_str()));
  }
  processObjInstance.As<Object>()->Set(v8::String::NewFromUtf8(mIsolate, "argv"), argvArr);

  // Setup global empty object for function callbacks
  Local<ObjectTemplate> emptyObj = ObjectTemplate::New();
  Handle<Object> emptyObjInstance = emptyObj->NewInstance();
  sEmptyObject.Reset(mIsolate, emptyObjInstance);

  // Grab GL context to execute the entry script and allow gl setup
  // @todo: deprecated as setup has context to draw with glNext already?
  glRenderer->startDraw();

  // Execute entry script
  Local<Value> mainResult = executeScriptString( mainJS, mIsolate,
    mMainContext, v8::String::NewFromUtf8(mIsolate, "cinder.js") );

  // Call wrapper function with process object
  if(mainResult->IsFunction()){
    Local<Function> mainFn = mainResult.As<Function>();

    v8::TryCatch tryCatch;

    mainFn->Call(mMainContext->Global(), 1, &processObjInstance);

    if(tryCatch.HasCaught()){
      handleV8TryCatch(tryCatch, "mainFn");
    }

    // TODO: Get Global()->global object and use in new context for external js modules

  } else {
    // FATAL: Main script not a function
    quit();
  }

  // Get rid of gl context again
  // @todo: deprecated as setup has context to draw with glNext already?
  glRenderer->finishDraw();

  gl::ContextRef backgroundCtx = gl::Context::create( gl::context() );

  // Start sub threads
  mV8EventThread = make_shared<std::thread>( boost::bind( &CinderjsApp::v8EventThread, this, backgroundCtx ) );
}

/**
 *
 */
v8::Handle<v8::Value> drawCallbackArgs[3];
void CinderjsApp::v8Draw(){

  // Gather some info...
  double now = getElapsedSeconds() * 1000;
  double timePassed = now - lastFrameTime;
  lastFrameTime = now;
  double elapsed = now - mLastUpdate;
  if(elapsed > mUpdateInterval) {
    v8FPS = v8Frames;
    v8Frames = 0;
    mLastUpdate = now;
    if(_v8StatsActive) mIsolate->GetHeapStatistics(&_mHeapStats);
  }

  v8::Locker lock(mIsolate);

  // JS Draw callback

  // Isolate
  v8::Isolate::Scope isolate_scope(mIsolate);
  v8::HandleScope handleScope(mIsolate);

  // Callback
  _fnDrawCallback = v8::Local<v8::Function>::New(mIsolate, sDrawCallback);

  v8::TryCatch try_catch;

  gl::pushMatrices();

  // Handle execution queue
  // TODO: Use a buffer queue and reuse event/frame buffer "packets" instead of instantiation at each creation time
  while(sExecutionQueue.isNotEmpty()){
    NextFrameFn nffn(new NextFrameFnHolder());
    sExecutionQueue.popBack(&nffn);
    v8::Local<v8::Function> callback = v8::Local<v8::Function>::New(mIsolate, nffn->v8Fn);
    if(!nffn->repeat){
      nffn->v8Fn.Reset(); // Get rid of persistent
    }
    v8::Handle<v8::Value> exArgv[0] = {};
    callback->Call(callback->CreationContext()->Global(), 0, exArgv);
  }

  if( !_fnDrawCallback.IsEmpty() ){

    drawCallbackArgs[0] = v8::Number::New(mIsolate, timePassed);
    drawCallbackArgs[1] = v8::Number::New(mIsolate, mousePosBuf.x);
    drawCallbackArgs[2] = v8::Number::New(mIsolate, mousePosBuf.y);

    _fnDrawCallback->Call(_fnDrawCallback->CreationContext()->Global(), 3, drawCallbackArgs);

    // TODO: Check if an FBO buffer was bound and not unbound.
    //       -> Unbind it to show console correctly and show eventual errors.
    //       -> Same goes for pushed matrices which were not popped after an error
  }

  gl::popMatrices();

  // Check for errors
  if(try_catch.HasCaught()){
    handleV8TryCatch(try_catch, "v8Draw");
  }

  v8::Unlocker unlock(mIsolate);

  // FPS (TODO: if active)
  cinder::TextLayout fpsText;
  fpsText.setColor( cinder::ColorA( 1, 1, 1, 1 ) );

  if(_fpsActive){
    fpsText.addLine( "Ci FPS: " + std::to_string( cinder::app::App::getAverageFps() ) );
    fpsText.addLine( "V8 FPS: " + std::to_string( v8FPS ) );
  }

  if(_v8StatsActive){
    fpsText.addLine( "V8 Heap limit: " + std::to_string( _mHeapStats.heap_size_limit() ) );
    fpsText.addLine( "V8 Heap total: " + std::to_string( _mHeapStats.total_heap_size() ) );
    fpsText.addLine( "V8 Heap Used: " + std::to_string( _mHeapStats.used_heap_size() ) );
  }

  if(_fpsActive || _v8StatsActive) {
    try {
      cinder::gl::draw( cinder::gl::Texture::create( fpsText.render() ) );
    } catch ( std::exception &e ){
      // don't draw if window not available
    }
  }

  // Draw console (if active)
  if(_consoleActive){
    vec2 cPos;
    // TODO: this still fails sometimes on shutdown
    try {
      cPos.y = getWindowHeight();
      AppConsole::draw( cPos );
    } catch ( std::exception &e ){
      // don't draw console if window is not available
    }
  }

  v8Frames++;

}

/**
 *
 */
void CinderjsApp::v8EventThread( gl::ContextRef context ){
  ThreadSetup threadSetup;
  context->makeCurrent();

  // TODO: Work around v8 blocking...

  // Thread loop
  while( !mShouldQuit ) {

    // Wait for data to be processed...
    {
        std::unique_lock<std::mutex> lck( mMainMutex );
        cvEventThread.wait(lck, [this]{ return _eventRun; });
    }

    if(!mShouldQuit && mEventQueue.isNotEmpty()){

      // TODO: If available, push mouse/key/resize events to v8
      v8::Locker lock(mIsolate);

      // Isolate
      v8::Isolate::Scope isolate_scope(mIsolate);
      v8::HandleScope handleScope(mIsolate);

      v8::Local<v8::Context> context = v8::Local<v8::Context>::New(mIsolate, pContext);

      if(context.IsEmpty()) return;

      Context::Scope ctxScope(context);
      context->Enter();

      // TODO: do not treat events further if shutdown was requested (quit from js)
      // TODO: Get rid of if/else statements
      while(mEventQueue.isNotEmpty()){
        BufferedEvent evt(new BufferedEventHolder());
        mEventQueue.popBack(&evt);

        // Callback
        v8::Local<v8::Function> callback = v8::Local<v8::Function>::New(mIsolate, sEventCallback);

        if(callback.IsEmpty()) continue;

        // Resize Event
        if(evt->type == CJS_RESIZE){
          v8::Handle<v8::Value> argv[3] = {
            v8::Number::New(mIsolate, CJS_RESIZE),
            v8::Number::New(mIsolate, getWindowWidth()),
            v8::Number::New(mIsolate, getWindowHeight())
          };
          callback->Call(context->Global(), 3, argv);
        }

        // Mouse down
        else if(evt->type == CJS_MOUSE_DOWN){
          v8::Handle<v8::Value> argv[1] = {
            v8::Number::New(mIsolate, CJS_MOUSE_DOWN)
            // ... TODO: Push more event info
          };
          callback->Call(context->Global(), 1, argv);
        }

        // Mouse up
        else if(evt->type == CJS_MOUSE_UP){
          v8::Handle<v8::Value> argv[1] = {
            v8::Number::New(mIsolate, CJS_MOUSE_UP)
            // ... TODO: Push more event info
          };
          callback->Call(context->Global(), 1, argv);
        }

        // Key down
        else if(evt->type == CJS_KEY_DOWN){
          v8::Handle<v8::Value> argv[3] = {
            v8::Number::New(mIsolate, CJS_KEY_DOWN),
            v8::Number::New(mIsolate, evt->kEvt.getCode()),
            v8::Number::New(mIsolate, evt->kEvt.getChar())
            // ... TODO: Push more event info
          };
          callback->Call(context->Global(), 3, argv);
        }

        // Key up
        else if(evt->type == CJS_KEY_UP){
          v8::Handle<v8::Value> argv[3] = {
            v8::Number::New(mIsolate, CJS_KEY_UP),
            v8::Number::New(mIsolate, evt->kEvt.getCode()),
            v8::Number::New(mIsolate, evt->kEvt.getChar())
            // ... TODO: Push more event info
          };
          callback->Call(context->Global(), 3, argv);
        }

        // File Drop
        else if(evt->type == CJS_FILE_DROP){

          Local<Array> files = Array::New(mIsolate);
          for(int i = 0; i < evt->fdFiles.size(); i++){
            files->Set(i, v8::String::NewFromUtf8(mIsolate, evt->fdFiles[i].c_str()));
          }

          v8::Handle<v8::Value> argv[2] = {
            v8::Number::New(mIsolate, CJS_FILE_DROP),
            files
          };
          callback->Call(context->Global(), 2, argv);
        }

        // Shutdown (gracefully)
        else if(evt->type == CJS_SHUTDOWN_REQUEST){
          quit();
        }
      }

      context->Exit();
      v8::Unlocker unlock(mIsolate);
    }

    _eventRun = false;
  }

  //@debug
  //std::cout << "V8 Event thread ending" << std::endl;
}

/**
 *
 */
void CinderjsApp::fileDrop( FileDropEvent event )
{
  BufferedEvent evt(new BufferedEventHolder());
  evt->type = CJS_FILE_DROP;
  evt->fdFiles = event.getFiles();
  mEventQueue.pushFront(evt);
  _eventRun = true;
  cvEventThread.notify_one();
}

/**
 *
 */
void CinderjsApp::resize()
{
  BufferedEvent evt(new BufferedEventHolder());
  evt->type = CJS_RESIZE;
  mEventQueue.pushFront(evt);
  _eventRun = true;
  cvEventThread.notify_one();
}

/**
 *
 */
void CinderjsApp::mouseMove( MouseEvent event )
{
  // Update mouse position (pushed to v8 with draw callback)
  mousePosBuf.x = event.getX();
  mousePosBuf.y = event.getY();
}

/**
 *
 */
void CinderjsApp::mouseDown( MouseEvent event )
{
  BufferedEvent evt(new BufferedEventHolder());
  evt->type = CJS_MOUSE_DOWN;
  evt->mEvt = event;
  mEventQueue.pushFront(evt);
  _eventRun = true;
  cvEventThread.notify_one();
}

/**
 *
 */
void CinderjsApp::mouseUp( MouseEvent event )
{
  BufferedEvent evt(new BufferedEventHolder());
  evt->type = CJS_MOUSE_UP;
  evt->mEvt = event;
  mEventQueue.pushFront(evt);
  _eventRun = true;
  cvEventThread.notify_one();
}

/**
 * Key down
 */
void CinderjsApp::keyDown( KeyEvent event )
{
  // Add default failsafe keys (ESC1x exit fullscreen, ESC2x exit app)
  if(getElapsedSeconds() - mLastEscPressed < 0.5){
    if(isFullScreen()){
      setFullScreen(false);
    } else {
      sQuitRequested = true;
    }
    return;
  }

  // Default Hotkeys
  if(event.getCode() == 27){
    mLastEscPressed = getElapsedSeconds();
  }
  // F1 - toggle fps text
  else if(event.getCode() == 282){
    _fpsActive = !_fpsActive;
  }
  // F2 - toggle v8 stats text
  else if(event.getCode() == 283){
    _v8StatsActive = !_v8StatsActive;
  }
  // F3 - toggle Console
  else if(event.getCode() == 284){
    _consoleActive = !_consoleActive;
  }

  BufferedEvent evt(new BufferedEventHolder());
  evt->type = CJS_KEY_DOWN;
  evt->kEvt = event;
  mEventQueue.pushFront(evt);
  _eventRun = true;
  cvEventThread.notify_one();
}

/**
 * Key up
 */
void CinderjsApp::keyUp( KeyEvent event )
{
  BufferedEvent evt(new BufferedEventHolder());
  evt->type = CJS_KEY_UP;
  evt->kEvt = event;
  mEventQueue.pushFront(evt);
  _eventRun = true;
  cvEventThread.notify_one();
}

/**
 *
 */
void CinderjsApp::update()
{

}

/**
 * Cinder draw loop (tick)
 * - Triggers v8 rendering
 */
void CinderjsApp::draw()
{
  // Quit if requested
  // Push to event queue and execute there (not check every frame, duh)
  if(sQuitRequested) {
    BufferedEvent evt(new BufferedEventHolder());
    evt->type = CJS_SHUTDOWN_REQUEST;
    mEventQueue.pushFront(evt);
    return;
  }

  v8Draw();
}

/**
 * Set the draw callback from javascript
 */
void CinderjsApp::setDrawCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
  v8::Isolate* isolate = args.GetIsolate();
  v8::Locker lock(isolate);
  v8::HandleScope handleScope(isolate);

  if(!args[0]->IsFunction()){
    // throw js exception
    isolate->ThrowException(v8::String::NewFromUtf8(isolate, "draw callback expects one argument of type function."));
    return;
  }
  AppConsole::log("draw callback set.");

  sDrawCallback.Reset(isolate, args[0].As<v8::Function>());

  return;
}

/**
 * Set event callback from javascript to push mouse/key events to
 */
void CinderjsApp::setEventCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
  v8::Isolate* isolate = args.GetIsolate();
  v8::Locker lock(isolate);
  v8::HandleScope handleScope(isolate);

  if(!args[0]->IsFunction()){
    // throw js exception
    isolate->ThrowException(v8::String::NewFromUtf8(isolate, "event callback expects one argument of type function."));
    return;
  }
  AppConsole::log("event callback set.");

  sEventCallback.Reset(isolate, args[0].As<v8::Function>());

  return;
}

/**
 * Toggle the AppConsole view on/off
 */
void CinderjsApp::toggleAppConsole(const v8::FunctionCallbackInfo<v8::Value>& args) {
  if(args.Length() > 0) {
    bool active = args[0]->ToBoolean()->Value();
    _consoleActive = active;
    return;
  }

  _consoleActive = !_consoleActive;
  return;
}

/**
 * Toggle v8 stats on/off
 */
void CinderjsApp::toggleV8Stats(const v8::FunctionCallbackInfo<v8::Value>& args) {
  _v8StatsActive = !_v8StatsActive;
  return;
}

/**
 * Toggle fps on/off
 */
void CinderjsApp::toggleFPS(const v8::FunctionCallbackInfo<v8::Value>& args) {
  _fpsActive = !_fpsActive;
  return;
}

/**
 * Allow JS to quit the App
 *
 * Tries to shutdown the application process gracefully,
 * meaning everything scheduled up until this point will still be executed,
 * shutdown will happen only after the scheduled tasks finish.
 *
 */
void CinderjsApp::requestQuit(const v8::FunctionCallbackInfo<v8::Value>& args) {
  // TODO: emit process exit event for js to react on and shutdown stuff if necessary
  //       Will at this point be pushed to event queue before the shutdown request,
  //       so it will be executed before shutdown.
  sQuitRequested = true;
  return;
}

/**
 * Async function execution in the next frame (executed in v8 event thread)
 *
 * Function callbacks scheduled for the next frame will be executed in a separate thread,
 * not the main render thread. The event thread they are executed in has a separate GL context,
 * with shared resources, so GL objects can be setup there and be used in the main render loop.
 * Drawing directly to the canvas however is not possible within the event thread.
 *
 */
void CinderjsApp::nextFrameJS(const v8::FunctionCallbackInfo<v8::Value>& args) {
  Isolate* isolate = args.GetIsolate();
  HandleScope scope(isolate);

  // TODO: check next frame execution queue and warn (fail) if full

  if(args[0]->IsFunction()){
    NextFrameFn nffn(new NextFrameFnHolder());
    nffn->v8Fn.Reset(isolate, args[0].As<Function>());
    sExecutionQueue.pushFront(nffn);
  }
}

/**
 * Set a timeout from JS
 * args: id, fn, timeout, repeat
 */
void CinderjsApp::setTimer(const v8::FunctionCallbackInfo<v8::Value>& args) {
  Isolate* isolate = args.GetIsolate();
  HandleScope scope(isolate);

  if(args[0]->IsFunction()){

    double timeout = args[1]->ToNumber()->Value();

    // If timeout is too little to be executed in time, run directly next frame;
    if(timeout <= 1){
      nextFrameJS(args);
      return;
    }

    NextFrameFn nffn(new NextFrameFnHolder());
    nffn->v8Fn.Reset(isolate, args[0].As<v8::Function>());
    nffn->repeat = args[2]->ToBoolean()->Value();

    uint32_t id = _mainTimer.set( timeout, _timerCallback, nffn->repeat, nffn );

    args.GetReturnValue().Set(id);
  }
  else if(args[0]->IsNumber()){
    _mainTimer.clear(args[0]->ToNumber()->Value());
  }

}

/**
 * Load a native js module (lib)
 */
void CinderjsApp::NativeBinding(const FunctionCallbackInfo<Value>& args) {
  Isolate* isolate = args.GetIsolate();
  HandleScope handle_scope(isolate);

  Locker lock(isolate);

  Local<String> moduleName = args[0]->ToString();

  if (moduleName.IsEmpty()) {
    std::string except = "NativeBinding needs a module name. fail.";
    isolate->ThrowException(String::NewFromUtf8(isolate, except.c_str()));
    return;
  }

  // if we have a second argument and it is a boolean true,
  // check for module existence only and return a boolean that can be checked with === operator
  bool checkExistence = false;
  if( args.Length() == 2 && args[1]->ToBoolean()->Value() ) {
    checkExistence = true;
  }

  Local<Object> cache = Local<Object>::New(isolate, sModuleCache);
  Local<Object> exports;
  Local<Object> moduleObj;

  if (!checkExistence && cache->Has(moduleName)) {
    exports = cache->Get(moduleName)->ToObject();
    args.GetReturnValue().Set(exports);
    return;
  }

  v8::String::Utf8Value strModuleName(moduleName);
  std::string cmpModName(*strModuleName);

  // Add to list
  std::string buf = "Native ";
  buf.append(*strModuleName);

  Local<Array> moduleList = Local<Array>::New(isolate, sModuleList);
  uint32_t len = moduleList->Length();
  moduleList->Set(len, String::NewFromUtf8(isolate, buf.c_str()));

  // Lookup native modules
  _native mod;
  bool found = false;
  for(int i = 0; i < sizeof(natives); i++) {
    if(natives[i].name == NULL) break;
    std::string cmp(natives[i].name);
    if(cmp == "cinder") continue;
    if(cmp == cmpModName){
      mod = natives[i];
      found = true;
      break;
    }
  }

  // If we only have to check existence, we return here
  if( checkExistence ) {
    args.GetReturnValue().Set(v8::Boolean::New(isolate, found));
    return;
  }

  if (found) {

    exports = Object::New(isolate);
    moduleObj = Object::New(isolate);

    v8::TryCatch tryCatch;

    // Use wrappers and wrap method set in cinder.js
    Local<Function> wrap = isolate
      ->GetCurrentContext()
      ->Global()
      ->Get(v8::String::NewFromUtf8(isolate, "process"))
      .As<Object>()
      ->Get(v8::String::NewFromUtf8(isolate, "wrap"))
      .As<Function>()
    ; // wtf v8...

    // Check v8 in sanity
    if(!wrap->IsFunction()) {
      std::string except = "Native module loading failed: No wrap method on the process object.";
      isolate->ThrowException(String::NewFromUtf8(isolate, except.c_str()));
      return;
    }

    // Try: v8::Local<Context>::New(isolate, pContext)
    std::shared_ptr<PipeModule> nativeMod = CinderjsApp::NAMED_MODULES[cmpModName];
    Local<Object> modObj = isolate->GetCurrentContext()->Global();
    if(nativeMod) {
      Local<ObjectTemplate> ctxGlb = ObjectTemplate::New(isolate);
      nativeMod->loadGlobalJS(ctxGlb);
      modObj = ctxGlb->NewInstance();
    }

    // Wrap it
    Local<Value> modSource = String::NewFromUtf8(isolate, mod.source);
    v8::String::Utf8Value wrappedSource( wrap->Call(Local<Object>::New(isolate, sEmptyObject), 1, &modSource) );
    std::string filename = cmpModName;
    filename.append(".js");
    Local<Value> modResult = executeScriptString(*wrappedSource, isolate, isolate->GetCurrentContext(),
      v8::String::NewFromUtf8(isolate, filename.c_str()) );

    // Check native module validity
    if(modResult.IsEmpty() || !modResult->IsFunction()){
      std::string except = "Native module not a function: ";
      except.append(*strModuleName);

      isolate->ThrowException(String::NewFromUtf8(isolate, except.c_str()));
      // TODO: remove from module list again
      return;
    }

    Local<Function> modFn = modResult.As<Function>();

    // Call
    Local<Value> argv[3] = {
      exports,
      // use this method as require as native modules won't require external ones(?)
      v8::Local<v8::Value>::Cast(v8::FunctionTemplate::New(isolate, NativeBinding)->GetFunction()),
      moduleObj
    };

    modFn->Call(modObj, 3, argv);

    if(tryCatch.HasCaught()){
      isolate->ThrowException( tryCatch.Exception() );
      //handleV8TryCatch(tryCatch);
      // TODO: remove from module list again
      return;
    }

    // check if module.exports exists,
    // if so, cache and return module.exports
    if( moduleObj->Has(v8::String::NewFromUtf8(isolate, "exports"))){
      exports = moduleObj->Get(v8::String::NewFromUtf8(isolate, "exports")).As<Object>();
    }

    cache->Set(moduleName, exports);
  } else {
    std::string except = "No such native module: ";
    except.append(*strModuleName);

    isolate->ThrowException(String::NewFromUtf8(isolate, except.c_str()));
    // TODO: remove from module list again
    return;
  }

  args.GetReturnValue().Set(exports);
}

} // namespace cjs

CINDER_APP( cjs::CinderjsApp, RendererGl )

max_stars_repo_name: kommander/cinderjs

max_issues_repo_name: kommander/cinderjs

max_forks_repo_name: kommander/cinderjs


text:
#include <iostream>
#include <utility>
#include <array>

#include <boost_ut/ut.hpp>

#include <PainPerdu/parser/Patterns/PatternMatchHelper.hpp>

using namespace boost::ut;

using namespace PainPerdu::parser::patterns::helper;

void basic_success()
{
	auto list = {1, 2, 3, 4, 5};
	bool res = match(list.begin(), list.end(), 1, 2, 3);
	expect(res) << "basic_success";
}

void fit_success()
{
	auto list = {1, 2, 3};
	bool res = match(list.begin(), list.end(), 1, 2, 3);
	expect(res) << "fit_success";
}

void basic_failure()
{
	auto list = {1, 2, 3, 4, 5};
	bool res = match(list.begin(), list.end(), 1, 2, 4);
	expect(!res) << "basic_failure";
}

void pattern_too_big()
{
	auto list = {1, 2, 3};
	bool res = match(list.begin(), list.end(), 1, 2, 3, 4);
	expect(!res) << "pattern_too_big";
}

void failure_empty_range()
{
	std::array<int, 0> list;
	bool res = match(list.begin(), list.end(), 1, 2);
	expect(!res) << "failure_empty_range";
}

int main()
{
	"basic_success"_test = basic_success;
	"fit_success"_test = fit_success;
	"basic_failure"_test = basic_failure;
	"pattern_too_big"_test = pattern_too_big;
	"failure_empty_range"_test = failure_empty_range;
}

max_stars_repo_name: Baduit/PainPerdu

max_issues_repo_name: Baduit/PainPerdu

max_forks_repo_name: Baduit/PainPerdu


text:
///////////////////////////////////////////////////////////////////////////////
// weighted_p_square_quantile.hpp
//
//  Copyright 2005 Daniel Egloff. Distributed under the Boost
//  Software License, Version 1.0. (See accompanying file
//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

#ifndef BOOST_ACCUMULATORS_STATISTICS_WEIGHTED_P_SQUARE_QUANTILE_HPP_DE_01_01_2006
#define BOOST_ACCUMULATORS_STATISTICS_WEIGHTED_P_SQUARE_QUANTILE_HPP_DE_01_01_2006

#include <cmath>
#include <functional>
#include <boost/array.hpp>
#include <boost/parameter/keyword.hpp>
#include <boost/mpl/placeholders.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/accumulators/framework/accumulator_base.hpp>
#include <boost/accumulators/framework/extractor.hpp>
#include <boost/accumulators/numeric/functional.hpp>
#include <boost/accumulators/framework/parameters/sample.hpp>
#include <boost/accumulators/statistics_fwd.hpp>
#include <boost/accumulators/statistics/count.hpp>
#include <boost/accumulators/statistics/sum.hpp>
#include <boost/accumulators/statistics/parameters/quantile_probability.hpp>

namespace boost { namespace accumulators
{

namespace impl {
    ///////////////////////////////////////////////////////////////////////////////
    // weighted_p_square_quantile_impl
    //  single quantile estimation with weighted samples
    /**
        @brief Single quantile estimation with the \f$P^2\f$ algorithm for weighted samples

        This version of the \f$P^2\f$ algorithm extends the \f$P^2\f$ algorithm to support weighted samples.
        The \f$P^2\f$ algorithm estimates a quantile dynamically without storing samples. Instead of
        storing the whole sample cumulative distribution, only five points (markers) are stored. The heights
        of these markers are the minimum and the maximum of the samples and the current estimates of the
        \f$(p/2)\f$-, \f$p\f$ - and \f$(1+p)/2\f$ -quantiles. Their positions are equal to the number
        of samples that are smaller or equal to the markers. Each time a new sample is added, the
        positions of the markers are updated and if necessary their heights are adjusted using a piecewise-
        parabolic formula.

        For further details, see

        R. Jain and I. Chlamtac, The P^2 algorithm for dynamic calculation of quantiles and
        histograms without storing observations, Communications of the ACM,
        Volume 28 (October), Number 10, 1985, p. 1076-1085.

        @param quantile_probability
    */
    template<typename Sample, typename Weight, typename Impl>
    struct weighted_p_square_quantile_impl
      : accumulator_base
    {
        typedef typename numeric::functional::multiplies<Sample, Weight>::result_type weighted_sample;
        typedef typename numeric::functional::average<weighted_sample, std::size_t>::result_type float_type;
        typedef array<float_type, 5> array_type;
        // for boost::result_of
        typedef float_type result_type;

        template<typename Args>
        weighted_p_square_quantile_impl(Args const &args)
          : p(is_same<Impl, for_median>::value ? 0.5 : args[quantile_probability | 0.5])
          , heights()
          , actual_positions()
          , desired_positions()
        {
        }

        template<typename Args>
        void operator ()(Args const &args)
        {
            std::size_t cnt = count(args);

            // accumulate 5 first samples
            if (cnt <= 5)
            {
                this->heights[cnt - 1] = args[sample];

                // In this initialization phase, actual_positions stores the weights of the
                // initial samples that are needed at the end of the initialization phase to
                // compute the correct initial positions of the markers.
                this->actual_positions[cnt - 1] = args[weight];

                // complete the initialization of heights and actual_positions by sorting
                if (cnt == 5)
                {
                    // TODO: we need to sort the initial samples (in heights) in ascending order and
                    // sort their weights (in actual_positions) the same way. The following lines do
                    // it, but there must be a better and more efficient way of doing this.
                    typename array_type::iterator it_begin, it_end, it_min;

                    it_begin = this->heights.begin();
                    it_end   = this->heights.end();

                    std::size_t pos = 0;

                    while (it_begin != it_end)
                    {
                        it_min = std::min_element(it_begin, it_end);
                        std::size_t d = std::distance(it_begin, it_min);
                        std::swap(*it_begin, *it_min);
                        std::swap(this->actual_positions[pos], this->actual_positions[pos + d]);
                        ++it_begin;
                        ++pos;
                    }

                    // calculate correct initial actual positions
                    for (std::size_t i = 1; i < 5; ++i)
                    {
                        this->actual_positions[i] += this->actual_positions[i - 1];
                    }
                }
            }
            else
            {
                std::size_t sample_cell = 1; // k

                // find cell k such that heights[k-1] <= args[sample] < heights[k] and adjust extreme values
                if (args[sample] < this->heights[0])
                {
                    this->heights[0] = args[sample];
                    this->actual_positions[0] = args[weight];
                    sample_cell = 1;
                }
                else if (this->heights[4] <= args[sample])
                {
                    this->heights[4] = args[sample];
                    sample_cell = 4;
                }
                else
                {
                    typedef typename array_type::iterator iterator;
                    iterator it = std::upper_bound(
                        this->heights.begin()
                      , this->heights.end()
                      , args[sample]
                    );

                    sample_cell = std::distance(this->heights.begin(), it);
                }

                // increment positions of markers above sample_cell
                for (std::size_t i = sample_cell; i < 5; ++i)
                {
                    this->actual_positions[i] += args[weight];
                }

                // update desired positions for all markers
                this->desired_positions[0] = this->actual_positions[0];
                this->desired_positions[1] = (sum_of_weights(args) - this->actual_positions[0])
                                           * this->p/2. + this->actual_positions[0];
                this->desired_positions[2] = (sum_of_weights(args) - this->actual_positions[0])
                                           * this->p + this->actual_positions[0];
                this->desired_positions[3] = (sum_of_weights(args) - this->actual_positions[0])
                                           * (1. + this->p)/2. + this->actual_positions[0];
                this->desired_positions[4] = sum_of_weights(args);

                // adjust height and actual positions of markers 1 to 3 if necessary
                for (std::size_t i = 1; i <= 3; ++i)
                {
                    // offset to desired positions
                    float_type d = this->desired_positions[i] - this->actual_positions[i];

                    // offset to next position
                    float_type dp = this->actual_positions[i + 1] - this->actual_positions[i];

                    // offset to previous position
                    float_type dm = this->actual_positions[i - 1] - this->actual_positions[i];

                    // height ds
                    float_type hp = (this->heights[i + 1] - this->heights[i]) / dp;
                    float_type hm = (this->heights[i - 1] - this->heights[i]) / dm;

                    if ( ( d >= 1. && dp > 1. ) || ( d <= -1. && dm < -1. ) )
                    {
                        short sign_d = static_cast<short>(d / std::abs(d));

                        // try adjusting heights[i] using p-squared formula
                        float_type h = this->heights[i] + sign_d / (dp - dm) * ( (sign_d - dm) * hp + (dp - sign_d) * hm );

                        if ( this->heights[i - 1] < h && h < this->heights[i + 1] )
                        {
                            this->heights[i] = h;
                        }
                        else
                        {
                            // use linear formula
                            if (d>0)
                            {
                                this->heights[i] += hp;
                            }
                            if (d<0)
                            {
                                this->heights[i] -= hm;
                            }
                        }
                        this->actual_positions[i] += sign_d;
                    }
                }
            }
        }

        result_type result(dont_care) const
        {
            return this->heights[2];
        }

    private:
        float_type p;                    // the quantile probability p
        array_type heights;              // q_i
        array_type actual_positions;     // n_i
        array_type desired_positions;    // n'_i
    };

} // namespace impl

///////////////////////////////////////////////////////////////////////////////
// tag::weighted_p_square_quantile
//
namespace tag
{
    struct weighted_p_square_quantile
      : depends_on<count, sum_of_weights>
    {
        typedef accumulators::impl::weighted_p_square_quantile_impl<mpl::_1, mpl::_2, regular> impl;
    };
    struct weighted_p_square_quantile_for_median
      : depends_on<count, sum_of_weights>
    {
        typedef accumulators::impl::weighted_p_square_quantile_impl<mpl::_1, mpl::_2, for_median> impl;
    };
}

///////////////////////////////////////////////////////////////////////////////
// extract::weighted_p_square_quantile
// extract::weighted_p_square_quantile_for_median
//
namespace extract
{
    extractor<tag::weighted_p_square_quantile> const weighted_p_square_quantile = {};
    extractor<tag::weighted_p_square_quantile_for_median> const weighted_p_square_quantile_for_median = {};

    BOOST_ACCUMULATORS_IGNORE_GLOBAL(weighted_p_square_quantile)
    BOOST_ACCUMULATORS_IGNORE_GLOBAL(weighted_p_square_quantile_for_median)
}

using extract::weighted_p_square_quantile;
using extract::weighted_p_square_quantile_for_median;

}} // namespace boost::accumulators

#endif

max_stars_repo_name: Icenium/BoostSharp


text:
/** @file csvparser.hpp
 *  @brief Custom Parser csv operator for data accessing and structring
 *
 *  This file contains the refacto's customparser
 *  includes id search and variable insertion
 *
 *
 *  @author Oguzhan San
 *  @bug No known bugs.
 *
 */

#ifndef __CUSTOMPARSER_HPP
#define __CUSTOMPARSER_HPP

#include <glob.h>
#include <sys/stat.h>

#include <algorithm>
#include <boost/log/trivial.hpp>
#include <cctype>
#include <deque>
#include <filesystem>
#include <fstream>
#include <iostream>
#include <map>
#include <regex>
#include <string>
#include <utility>
#include <vector>

#include "parser.hpp"
#include "table.hpp"

#define NAV "/"

using namespace std;
using namespace aria;
using namespace table;

using u_vector = const std::vector<u_int32_t>;
using s_matrix = const std::vector<std::vector<string>>;

using std::deque;
using std::map;
using std::shared_ptr;
using std::string;
using std::vector;

/**
 * @brief Entity struct for paramaterization of variables
 *
 * Entity Struct
 *
 *  Variable search object, used to locate variables
 *
 * Used for
 *  - ID Search-create
 *  - Variable seach
 *  - Vector Search
 *  - Single value search
 *
 */

struct Entity {
    string key;  // meta info ( example: inverter)
    string name;
    string orient;
    string eType;
    int value_begin;
    vector<map<string, string>> conditions;

    int row;
    int column;
    int vFrom;
    int vTo;

    string keyword;  // multi or filename

    // For single value insertion (entity)
    Entity(string key, string name, string eType, string keyword)
        : key{key}, name{name}, eType{eType}, keyword{keyword} {}

    // For Vector Insertation
    Entity(string key, string name, string orient, string eType, string keyword,
           int column, int vFrom, int vTo)
        : key{key},
          name{name},
          orient{orient},
          eType{eType},
          keyword{keyword},
          column{column},
          vFrom{vFrom},
          vTo{vTo} {}

    // For id initilization
    Entity(string key, string name, string orient, string eType, int row,
           int column, int value_begin, string keyword = "multi")
        : key{key},
          name{name},
          orient{orient},
          eType{eType},
          row{row},
          column{column},
          value_begin{value_begin},
          keyword{keyword} {}

    // Series initilization
    Entity(string key, string name, string orient, string eType, int row,
           int value_begin = 0)
        : key{key},
          name{name},
          orient{orient},
          eType{eType},
          row{row},
          value_begin{value_begin} {}
    // Series initilization with condition
    Entity(string key, string name, string orient, string eType,
           vector<map<string, string>> conditions, int value_begin = 0)
        : key{key},
          name{name},
          orient{orient},
          eType{eType},
          value_begin{value_begin},
          conditions{conditions} {}

    friend bool operator>(const Entity &right, const Entity &left);
    friend bool operator<=(const Entity &right, const Entity &left);
    friend bool operator<(const Entity &right, const Entity &left);
    friend bool operator>=(const Entity &right, const Entity &left);
};

inline bool is_path_exist(const std::string &s) {
    struct stat buffer;
    return (stat(s.c_str(), &buffer) == 0);
}

void find_ids(s_matrix &, vector<u_int32_t> &, const Entity &);
void find_ids(s_matrix &, vector<u_int32_t> &, map<string, string>,
              const Entity &);

/**
 * @brief Get the flist object
 *
 * @param pattern "file extension"
 * @return deque<string>
 */
deque<string> get_flist(string pattern);

/**
 * @brief CustomParser Class for CSV Data Search
 *  CSVParser Class
 *      Opens file
 *      Search given data
 */
class CustomParser {
   private:
    vector<Entity> meta;

   public:
    /**
     * @brief resulting data of the parsing composed of 2D array with 1th axis
     * as row and 2nd as column
     *
     */
    std::vector<std::vector<string>> data;
    std::map<string, shared_ptr<Table>> tables;

    template <typename... T>
    CustomParser(T... lst) : meta{lst...} {}

   private:
    string id_iter, id_type;
    vector<string> id_iter_vector;
    std::string file_name;

   public:
    /**
     * @brief Overload ()operator for hyperparameters
     *
     * @param dir_path
     * @param delimeter
     * @param skip
     */
    void operator()(string dir_path, string delimeter, int skip);

    /**
     * @brief Insert series to tables
     *
     *  Parse values to series
     *  insert series to table
     *  flush series for each entity
     *
     *
     * @param tb (shared_ptr<Table>)
     * @param entity_lst (const vector<Entity> &) conditional search
     * @param series (Series &) series to be inserted
     * @param vec_values (vector<string> &) vector values to be inserted
     */
    void in_insert(shared_ptr<Table> tb, const vector<Entity> &entity_lst,
                   Series &series, vector<string> &vec_values);

    /**
     * @brief Insert values to vector
     *
     *  Parse values vec_values
     * @param item ( Entity&) conditional search
     * @param vec_values (vector<string> &) vector values to be inserted
     */
    void from_vector(vector<string> &vec_values, Entity &item) const;

    /**
     * @brief Get the variable name object
     *  - Search key name with regex
     * @return (string) found id
     */
    string get_variable_name(const Entity &) const;

    /**
     * @brief Insert group ids with regex search
     *  - Custom search for id as vairable
     *
     * @param series (Series &) series to be inserted
     * @param item ( Entity&) conditional search
     * @param tb (shared_pr<Table>) table which data will be inserted
     */
    void from_group_series(Series &series, const Entity &item,
                           shared_ptr<Table> tb);

    /**
     * @brief writes to csv
     *
     * @param dir (string) directory path
     */
    inline void to_csv(string dir) {
        string save_path;
        for (const auto &p : tables) {
            save_path = dir + "/" + p.first + ".csv";
            p.second->save(save_path);
        }
    }

   private:
    /**
     * @brief Creates series with entity condition
     *
     * @param series (Series) series which will be filled
     * @param item (Entity) condition for series construction
     * @param tb (shared_pr<Table>) table which data will be inserted
     */
    void from_series(Series &series, const Entity &item, shared_ptr<Table> tb);

    /**
     * @brief Create a ids and initilize map keys
     *
     * @param series (Series&) series for id initilization
     * @param item (Entity) id search condition
     */
    void create_ids(Series &series, const Entity &item);
    /**
     * @brief Checks if id exists
     *
     * @param series (Series&) Series id will be checked
     * @param check_id (string) id to be checked
     * @return true if exists
     * @return false if not
     */
    inline bool id_exist(Series &series, string check_id) {
        if (series.values.find(check_id) == series.values.end()) return false;
        return true;
    }

    /**
     * @brief Construct series for insertion
     *
     * @param series (Series&) series for construction
     * @param item (Entity&) Search conditions
     * @param tb (shared_ptr<Table>) tables for insertion
     */
    void construct_series(Series &series, const Entity &item,
                          shared_ptr<Table> tb);

    void inline clean_series(Series &series) const {
        for (auto &p : series.values) {
            series.values.find(p.first)->second.clear();
        }
    }

    /**
     * @brief Construct series for insertion with condition
     *
     *  - Conditional id search
     *
     * @param series (Series&) series for construction
     * @param item (Entity&) Search conditions
     * @param target (map<string, string>) condition
     * @param tb (shared_ptr<Table>) tables for insertion
     */
    void construct_series(Series &series, const Entity &item,
                          map<string, string> target,
                          shared_ptr<Table> tb) const;

    /**
     * @brief reads file and pushes data
     *
     * @param path (string) directory path
     * @param delim (string) delimeter
     * @param skip_rows (int) rows to be skipped
     */
    inline void in_read(const string &path, string delim, int skip_rows) {
        std::ifstream file(path);
        csv::CsvParser p{file};

        p.delimiter(delim[0]);
        int to_skip = 0;

        for (auto iter_row = p.begin(); iter_row != p.end(); iter_row++) {
            if (to_skip < skip_rows) {
                to_skip++;
                continue;
            }
            data.push_back(*iter_row);
        }
    }

    /**
     * @brief Group entities for each unique key
     *
     * @param keys (map<string, vector<Entity>> &) key and each entities
     */
    void transform_keys(map<string, vector<Entity>> &keys);

    /**
     * @brief Get the substring object
     *
     * @param delimiter (string)
     * @param extention (string) file extension
     * @param s
     * @return std::string
     */
    string get_substring(std::string delimiter, std::string extention,
                         std::string s) const;
};

inline bool operator>(const Entity &right, const Entity &left) {
    return right.key > left.key;
}
inline bool operator<=(const Entity &right, const Entity &left) {
    return right.key <= left.key;
}
inline bool operator<(const Entity &right, const Entity &left) {
    return right.key < left.key;
}

inline bool operator>=(const Entity &right, const Entity &left) {
    return right.key >= left.key;
}

#endif

max_stars_repo_name: sanoguzhan/refacto

max_issues_repo_name: sanoguzhan/refacto

max_forks_repo_name: sanoguzhan/refacto


text:
#pragma once
#include <sophiatx/chain/sophiatx_object_types.hpp>
#include <boost/multi_index/composite_key.hpp>

namespace sophiatx { namespace plugins { namespace template_plugin {

using namespace std;
using namespace sophiatx::chain;

//
// Plugins should #define their SPACE_ID's so plugins with
// conflicting SPACE_ID assignments can be compiled into the
// same binary (by simply re-assigning some of the conflicting #defined
// SPACE_ID's in a build script).
//
// Assignment of SPACE_ID's cannot be done at run-time because
// various template automagic depends on them being known at compile
// time.
//
#ifndef SOPHIATX_TEMPLATE_SPACE_ID
#define SOPHIATX_TEMPLATE_SPACE_ID 31
#endif

enum template_object_types
{
   template_lookup_object_type = ( SOPHIATX_TEMPLATE_SPACE_ID << 8 )
};

class template_lookup_object : public object< template_lookup_object_type, template_lookup_object >
{
   public:
      template< typename Constructor, typename Allocator >
      template_lookup_object( Constructor&& c, allocator< Allocator > a )
      {
         c( *this );
      }

      id_type           id;

};

typedef template_lookup_object::id_type template_lookup_id_type;

using namespace boost::multi_index;

struct by_key;

typedef multi_index_container<
   template_lookup_object,
   indexed_by<
      ordered_unique< tag< by_id >, member< template_lookup_object, template_lookup_id_type, &template_lookup_object::id > >
   >,
   allocator< template_lookup_object >
> template_lookup_index;

} } } // sophiatx::plugins::template

FC_REFLECT( sophiatx::plugins::template_plugin::template_lookup_object, (id) )
CHAINBASE_SET_INDEX_TYPE( sophiatx::plugins::template_plugin::template_lookup_object, sophiatx::plugins::template_plugin::template_lookup_index )

max_stars_repo_name: SophiaTX/SophiaTx-Blockchain

max_issues_repo_name: SophiaTX/SophiaTx-Blockchain

max_forks_repo_name: SophiaTX/SophiaTx-Blockchain


text:
/*
 Copyright (C) 2016 Quaternion Risk Management Ltd
 All rights reserved.

 This file is part of ORE, a free-software/open-source library
 for transparent pricing and risk analysis - http://opensourcerisk.org

 ORE is free software: you can redistribute it and/or modify it
 under the terms of the Modified BSD License.  You should have received a
 copy of the license along with this program.
 The license is also available online at <http://opensourcerisk.org>

 This program is distributed on the basis that it will form a useful
 contribution to risk analytics and model standardisation, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE. See the license for more details.
*/

#include <boost/make_shared.hpp>
#include <boost/test/unit_test.hpp>
#include <ored/marketdata/marketimpl.hpp>
#include <ored/portfolio/builders/equityforward.hpp>
#include <ored/portfolio/builders/equityoption.hpp>
#include <ored/portfolio/builders/equityfuturesoption.hpp>
#include <ored/portfolio/enginedata.hpp>
#include <ored/portfolio/equityforward.hpp>
#include <ored/portfolio/equityoption.hpp>
#include <ored/portfolio/equityfuturesoption.hpp>
#include <oret/toplevelfixture.hpp>
#include <ql/math/distributions/normaldistribution.hpp>
#include <ql/termstructures/volatility/equityfx/blackconstantvol.hpp>
#include <ql/termstructures/yield/flatforward.hpp>
#include <ql/time/daycounters/actualactual.hpp>
#include <qle/indexes/equityindex.hpp>

using namespace QuantLib;
using namespace QuantExt;
using namespace boost::unit_test_framework;
using namespace std;
using namespace ore::data;

namespace {

class TestMarket : public MarketImpl {
public:
    TestMarket() {
        asof_ = Date(3, Feb, 2016);

        // build discount
        yieldCurves_[make_tuple(Market::defaultConfiguration, YieldCurveType::Discount, "EUR")] = flatRateYts(0.1);
        yieldCurves_[make_tuple(Market::defaultConfiguration, YieldCurveType::Discount, "USD")] = flatRateYts(0.075);

        // add fx rates
        fxSpots_[Market::defaultConfiguration].addQuote("EURUSD", Handle<Quote>(boost::make_shared<SimpleQuote>(1.2)));

        // build fx vols
        fxVols_[make_pair(Market::defaultConfiguration, "EURUSD")] = flatRateFxv(0.10);

        // add equity spots
        equitySpots_[make_pair(Market::defaultConfiguration, "zzzCorp")] =
            Handle<Quote>(boost::make_shared<SimpleQuote>(100));

        // add dividend yield
        yieldCurves_[make_tuple(Market::defaultConfiguration, YieldCurveType::EquityDividend, "zzzCorp")] =
            flatRateYts(0.05);

        // add equity curve
        equityCurves_[make_pair(Market::defaultConfiguration, "zzzCorp")] =
            Handle<EquityIndex>(boost::make_shared<EquityIndex>(
                "zzzCorp", TARGET(), parseCurrency("EUR"), equitySpot("zzzCorp"),
                yieldCurve(YieldCurveType::Discount, "EUR"), yieldCurve(YieldCurveType::EquityDividend, "zzzCorp")));

        // build equity vols
        equityVols_[make_pair(Market::defaultConfiguration, "zzzCorp")] = flatRateFxv(0.20);
    }

private:
    Handle<YieldTermStructure> flatRateYts(Real forward) {
        boost::shared_ptr<YieldTermStructure> yts(new FlatForward(0, NullCalendar(), forward, ActualActual()));
        return Handle<YieldTermStructure>(yts);
    }
    Handle<BlackVolTermStructure> flatRateFxv(Volatility forward) {
        boost::shared_ptr<BlackVolTermStructure> fxv(new BlackConstantVol(0, NullCalendar(), forward, ActualActual()));
        return Handle<BlackVolTermStructure>(fxv);
    }
};
} // namespace

BOOST_FIXTURE_TEST_SUITE(OREDataTestSuite, ore::test::TopLevelFixture)

BOOST_AUTO_TEST_SUITE(EquityTradesTests)

// Equity option/forward test, example from Haug, Chapter 1
BOOST_AUTO_TEST_CASE(testEquityTradePrices) {

    BOOST_TEST_MESSAGE("Testing EquityOption Price...");

    Date today = Settings::instance().evaluationDate();

    // build market
    boost::shared_ptr<Market> market = boost::make_shared<TestMarket>();
    Settings::instance().evaluationDate() = market->asofDate();
    Date expiry = market->asofDate() + 6 * Months + 1 * Days;
    ostringstream o;
    o << QuantLib::io::iso_date(expiry);
    string exp_str = o.str();

    // build EquityOption - expiry in 1 Year
    OptionData callData("Long", "Call", "European", true, vector<string>(1, exp_str));
    OptionData callDataPremium("Long", "Call", "European", true, vector<string>(1, exp_str), "Cash", "",
                               PremiumData{1.0, "EUR", expiry});
    OptionData putData("Short", "Put", "European", true, vector<string>(1, exp_str));
    OptionData putDataPremium("Short", "Put", "European", true, vector<string>(1, exp_str), "Cash", "",
                              PremiumData{1.0, "EUR", expiry});
    Envelope env("CP1");
    EquityOption eqCall(env, callData, EquityUnderlying("zzzCorp"), "EUR", 95.0, 1.0);
    EquityOption eqCallPremium(env, callDataPremium, EquityUnderlying("zzzCorp"), "EUR", 95.0, 1.0);
    EquityOption eqPut(env, putData, EquityUnderlying("zzzCorp"), "EUR", 95.0, 1.0);
    EquityOption eqPutPremium(env, putDataPremium, EquityUnderlying("zzzCorp"), "EUR", 95.0, 1.0);
    ore::data::EquityForward eqFwd(env, "Long", EquityUnderlying("zzzCorp"), "EUR", 1.0, exp_str, 95.0);

    Real expectedNPV_Put = -2.4648;           // negative for sold option
    Real expectedNPV_Put_Premium = -1.513558; // less negative due to received premium of 1 EUR at expiry

    // Build and price
    boost::shared_ptr<EngineData> engineData = boost::make_shared<EngineData>();
    engineData->model("EquityOption") = "BlackScholesMerton";
    engineData->engine("EquityOption") = "AnalyticEuropeanEngine";
    engineData->model("EquityForward") = "DiscountedCashflows";
    engineData->engine("EquityForward") = "DiscountingEquityForwardEngine";
    boost::shared_ptr<EngineFactory> engineFactory = boost::make_shared<EngineFactory>(engineData, market);
    engineFactory->registerBuilder(boost::make_shared<EquityEuropeanOptionEngineBuilder>());
    engineFactory->registerBuilder(boost::make_shared<EquityForwardEngineBuilder>());

    eqCall.build(engineFactory);
    eqCallPremium.build(engineFactory);
    eqPut.build(engineFactory);
    eqPutPremium.build(engineFactory);
    eqFwd.build(engineFactory);

    Real npv_call = eqCall.instrument()->NPV();
    Real npv_call_premium = eqCallPremium.instrument()->NPV();
    Real npv_put = eqPut.instrument()->NPV();
    Real npv_put_premium = eqPutPremium.instrument()->NPV();
    Real npv_fwd = eqFwd.instrument()->NPV();

    Real put_call_sum = npv_call + npv_put;
    Real put_call_premium_sum = npv_call_premium + npv_put_premium;

    BOOST_CHECK_CLOSE(expectedNPV_Put, npv_put, 0.001);
    BOOST_CHECK_CLOSE(expectedNPV_Put_Premium, npv_put_premium, 0.001);
    BOOST_CHECK_CLOSE(npv_fwd, put_call_sum, 0.001);         // put-call parity check
    BOOST_CHECK_CLOSE(npv_fwd, put_call_premium_sum, 0.001); // put-call parity check

    Settings::instance().evaluationDate() = today; // reset
}

// when futureExpiryDate == optionExpiryDate then the trade should behave like an EquityOption
BOOST_AUTO_TEST_CASE(testEquityFutureOptionPrices) {

    BOOST_TEST_MESSAGE("Testing EquityFutureOption Price...");

    Date today = Settings::instance().evaluationDate();

    // build market
    boost::shared_ptr<Market> market = boost::make_shared<TestMarket>();
    Settings::instance().evaluationDate() = market->asofDate();
    Date expiry = market->asofDate() + 6 * Months + 1 * Days;
    ostringstream o;
    o << QuantLib::io::iso_date(expiry);
    string exp_str = o.str();

    boost::shared_ptr<ore::data::Underlying> underlying = boost::make_shared<ore::data::EquityUnderlying>("zzzCorp");
    // build EquityOption - expiry in 1 Year
    OptionData callData("Long", "Call", "European", true, vector<string>(1, exp_str));
    OptionData callDataPremium("Long", "Call", "European", true, vector<string>(1, exp_str), "Physical", "",
                               PremiumData(1.0, "EUR", expiry));
    OptionData putData("Short", "Put", "European", true, vector<string>(1, exp_str));
    OptionData putDataPremium("Short", "Put", "European", true, vector<string>(1, exp_str), "Physical", "",
                              PremiumData(1.0, "EUR", expiry));
    Envelope env("CP1");
    EquityFutureOption eqFwdCall(env, callData, "EUR", 1.0, underlying, 95.0, expiry);
    EquityFutureOption eqFwdCallPremium(env, callDataPremium, "EUR", 1.0, underlying, 95.0, expiry);
    EquityFutureOption eqFwdPut(env, putData, "EUR", 1.0, underlying, 95.0, expiry);
    EquityFutureOption eqFwdPutPremium(env, putDataPremium, "EUR", 1.0, underlying, 95.0, expiry);

    EquityOption eqCall(env, callData, EquityUnderlying("zzzCorp"), "EUR", 95.0, 1.0);
    EquityOption eqCallPremium(env, callDataPremium, EquityUnderlying("zzzCorp"), "EUR", 95.0, 1.0);
    EquityOption eqPut(env, putData, EquityUnderlying("zzzCorp"), "EUR", 95.0, 1.0);
    EquityOption eqPutPremium(env, putDataPremium, EquityUnderlying("zzzCorp"), "EUR", 95.0, 1.0);

    // Build and price
    boost::shared_ptr<EngineData> engineData = boost::make_shared<EngineData>();
    engineData->model("EquityOption") = "BlackScholesMerton";
    engineData->engine("EquityOption") = "AnalyticEuropeanEngine";
    engineData->model("EquityFutureOption") = "BlackScholes";
    engineData->engine("EquityFutureOption") = "AnalyticEuropeanForwardEngine";
    boost::shared_ptr<EngineFactory> engineFactory = boost::make_shared<EngineFactory>(engineData, market);
    engineFactory->registerBuilder(boost::make_shared<EquityEuropeanOptionEngineBuilder>());
    engineFactory->registerBuilder(boost::make_shared<EquityFutureEuropeanOptionEngineBuilder>());
    engineFactory->registerBuilder(boost::make_shared<EquityForwardEngineBuilder>());

    eqFwdCall.build(engineFactory);
    eqFwdCallPremium.build(engineFactory);
    eqFwdPut.build(engineFactory);
    eqFwdPutPremium.build(engineFactory);

    eqCall.build(engineFactory);
    eqCallPremium.build(engineFactory);
    eqPut.build(engineFactory);
    eqPutPremium.build(engineFactory);

    BOOST_CHECK_CLOSE(eqCall.instrument()->NPV(), eqFwdCall.instrument()->NPV(), 0.001);
    BOOST_CHECK_CLOSE(eqCallPremium.instrument()->NPV(), eqFwdCallPremium.instrument()->NPV(), 0.001);
    BOOST_CHECK_CLOSE(eqPut.instrument()->NPV(), eqFwdPut.instrument()->NPV(), 0.001);
    BOOST_CHECK_CLOSE(eqPutPremium.instrument()->NPV(), eqFwdPutPremium.instrument()->NPV(), 0.001);

    Settings::instance().evaluationDate() = today; // reset
}

BOOST_AUTO_TEST_CASE(testEquityFutureParity) {

    BOOST_TEST_MESSAGE("Testing EquityFutureOption Put-Call parity...");

    Date today = Settings::instance().evaluationDate();

    // build market
    boost::shared_ptr<Market> market = boost::make_shared<TestMarket>();
    Settings::instance().evaluationDate() = market->asofDate();
    Date expiry = market->asofDate() + 6 * Months + 1 * Days;
    ostringstream o;
    o << QuantLib::io::iso_date(expiry);
    string exp_str = o.str();

    Date futureExpiry = market->asofDate() + 12 * Months + 1 * Days;
    ostringstream o_2;
    o_2 << QuantLib::io::iso_date(futureExpiry);
    string f_exp_str = o_2.str();

    boost::shared_ptr<ore::data::Underlying> underlying = boost::make_shared<ore::data::EquityUnderlying>("zzzCorp");
    double strike = 95.0;
    double spot = 100;
    // build EquityOption - expiry in 1 Year
    OptionData callData("Long", "Call", "European", true, vector<string>(1, exp_str));
    OptionData callDataPremium("Long", "Call", "European", true, vector<string>(1, exp_str), "Physical", "",
                               PremiumData(1.0, "EUR", expiry));
    OptionData putData("Long", "Put", "European", true, vector<string>(1, exp_str));
    OptionData putDataPremium("Long", "Put", "European", true, vector<string>(1, exp_str), "Physical", "",
                              PremiumData(1.0, "EUR", expiry));
    Envelope env("CP1");
    EquityFutureOption eqCall(env, callData, "EUR", 1.0, underlying, strike, futureExpiry);
    EquityFutureOption eqCallPremium(env, callDataPremium, "EUR", 1.0, underlying, strike, futureExpiry);
    EquityFutureOption eqPut(env, putData, "EUR", 1.0, underlying, strike, futureExpiry);
    EquityFutureOption eqPutPremium(env, putDataPremium, "EUR", 1.0, underlying, strike, futureExpiry);
    ore::data::EquityForward eqFwd(env, "Long", EquityUnderlying("zzzCorp"), "EUR", 1.0, f_exp_str, 0);

    // Build and price
    boost::shared_ptr<EngineData> engineData = boost::make_shared<EngineData>();
    engineData->model("EquityFutureOption") = "BlackScholes";
    engineData->engine("EquityFutureOption") = "AnalyticEuropeanForwardEngine";
    engineData->model("EquityOption") = "BlackScholesMerton";
    engineData->engine("EquityOption") = "AnalyticEuropeanEngine";
    engineData->model("EquityForward") = "DiscountedCashflows";
    engineData->engine("EquityForward") = "DiscountingEquityForwardEngine";
    boost::shared_ptr<EngineFactory> engineFactory = boost::make_shared<EngineFactory>(engineData, market);
    engineFactory->registerBuilder(boost::make_shared<EquityEuropeanOptionEngineBuilder>());
    engineFactory->registerBuilder(boost::make_shared<EquityFutureEuropeanOptionEngineBuilder>());
    engineFactory->registerBuilder(boost::make_shared<EquityForwardEngineBuilder>());

    eqCall.build(engineFactory);
    eqCallPremium.build(engineFactory);
    eqPut.build(engineFactory);
    eqPutPremium.build(engineFactory);
    eqFwd.build(engineFactory);

    Handle<YieldTermStructure> discountCurve =
            market->discountCurve("EUR", Market::defaultConfiguration);

    Handle<YieldTermStructure> dividend = market->equityDividendCurve("zzzCorp", Market::defaultConfiguration);
    Handle<YieldTermStructure> forecast = market->equityForecastCurve("zzzCorp", Market::defaultConfiguration);

    Real npv_call = eqCall.instrument()->NPV();
    Real npv_call_premium = eqCallPremium.instrument()->NPV();
    Real npv_put = eqPut.instrument()->NPV();
    Real npv_put_premium = eqPutPremium.instrument()->NPV();

    Real npv_fwd = spot * dividend->discount(futureExpiry) / forecast->discount(futureExpiry);;

    Real put_sum = npv_put + ( npv_fwd - strike ) * discountCurve->discount(expiry);
    Real put_premium_sum = npv_put_premium + ( npv_fwd - strike ) * discountCurve->discount(expiry);

    BOOST_CHECK_CLOSE(npv_call, put_sum, 0.001);         // put-call parity check
    BOOST_CHECK_CLOSE(npv_call_premium, put_premium_sum, 0.001); // put-call parity check

    Settings::instance().evaluationDate() = today; // reset
}
BOOST_AUTO_TEST_SUITE_END()

BOOST_AUTO_TEST_SUITE_END()

max_stars_repo_name: mrslezak/Engine

max_issues_repo_name: mrslezak/Engine

max_forks_repo_name: mrslezak/Engine


text:
//          Copyright Camille Gillot 2012 - 2015.
// Distributed under the Boost Software License, Version 1.0.
//    (See accompanying file LICENSE_1_0.txt or copy at
//          http://www.boost.org/LICENSE_1_0.txt)

#ifndef RTTI_MMETHOD_DECLARE_HELPER_HPP
#define RTTI_MMETHOD_DECLARE_HELPER_HPP

#include "mmethod/config.hpp"
#include "mmethod/declare/call.hpp"
#include "mmethod/declare/traits.hpp"

#include <boost/function_types/result_type.hpp>
#include <boost/function_types/parameter_types.hpp>

namespace rtti {
namespace mmethod {
namespace detail {

// detail/access.hpp
struct access;

template<typename Tag, typename Policy, typename Ret, typename Args>
struct make_declare_helper
: protected make_declare_call<Tag, Policy, Ret, Args>
{
private:
  typedef make_declare_call<Tag, Policy, Ret, Args> call_helper;

protected:
  typedef typename call_helper::traits_type traits_type;
  typedef typename call_helper::trampoline_type trampoline_type;

private:
  friend struct rtti::mmethod::detail::access;

protected:
  typedef make_declare_helper decl_maker;
  typedef Ret result_type;
  typedef typename call_helper::func_t func_t;

  using call_helper::fast_fetch;
  using call_helper::fast_call;

  using call_helper::fetch;
  using call_helper::call;

  using call_helper::operator();

  using call_helper::insert;
  using call_helper::generate;
};

template<typename Tag, typename Policy, typename Sig>
struct make_declare {
private:
  typedef typename boost::function_types::result_type<Sig>::type result;
  typedef typename boost::function_types::parameter_types<Sig>::type args;

public:
  typedef make_declare_helper<Tag, Policy, result, args> type;
};

} // namespace detail
} // namespace mmethod
} // namespace rtti

#endif

max_stars_repo_name: cjgillot/rtti

max_issues_repo_name: cjgillot/rtti

max_forks_repo_name: cjgillot/rtti