<commit_before>#include "loss.h"
#include "layer.h"
#include "model.h"
#include "version.h"
#include "trainer.h"
#include "enhancer.h"
#include "text/table.h"
#include "text/cmdline.h"
#include "solver_batch.h"
#include "solver_stoch.h"
#include <iostream>

using namespace nano;

namespace
{
        template <typename tobject>
        void print(const string_t& name, const factory_t<tobject>& manager)
        {
                const auto ids = manager.ids();
                const auto descriptions = manager.descriptions();
                const auto configurations = manager.configs();

                table_t table;
                table.header() << name << "description" << "configuration";
                table.delim();
                for (size_t i = 0; i < ids.size(); ++ i)
                {
                        table.append() << ids[i] << descriptions[i] << configurations[i];
                }
                std::cout << table;
        }
}

int main(int argc, const char* argv[])
{
        // parse the command line
        cmdline_t cmdline("display the registered objects");
        cmdline.add("", "loss",                 "loss functions");
        cmdline.add("", "task",                 "tasks");
        cmdline.add("", "layer",                "layers to built models");
        cmdline.add("", "enhancer",             "task enhancers");
        cmdline.add("", "trainer",              "training methods");
        cmdline.add("", "batch",                "batch optimization algorithms");
        cmdline.add("", "stoch",                "stochastic optimization algorithms");
        cmdline.add("", "version",              "library version");
        cmdline.add("", "git-hash",             "git commit hash");
        cmdline.add("", "system",               "system: all available information");
        cmdline.add("", "sys-logical-cpus",     "system: number of logical cpus");
        cmdline.add("", "sys-physical-cpus",    "system: number of physical cpus");
        cmdline.add("", "sys-memsize",          "system: memory size in GB");

        cmdline.process(argc, argv);

        const bool has_loss = cmdline.has("loss");
        const bool has_task = cmdline.has("task");
        const bool has_layer = cmdline.has("layer");
        const bool has_enhancer = cmdline.has("enhancer");
        const bool has_trainer = cmdline.has("trainer");
        const bool has_batch = cmdline.has("batch");
        const bool has_stoch = cmdline.has("stoch");
        const bool has_system = cmdline.has("system");
        const bool has_sys_logical = cmdline.has("sys-logical-cpus");
        const bool has_sys_physical = cmdline.has("sys-physical-cpus");
        const bool has_sys_memsize = cmdline.has("sys-memsize");
        const bool has_version = cmdline.has("version");
        const bool has_git_hash = cmdline.has("git-hash");

        if (    !has_loss &&
                !has_task &&
                !has_layer &&
                !has_enhancer &&
                !has_trainer &&
                !has_batch &&
                !has_stoch &&
                !has_system &&
                !has_sys_logical &&
                !has_sys_physical &&
                !has_sys_memsize &&
                !has_version &&
                !has_git_hash)
        {
                cmdline.usage();
                return EXIT_FAILURE;
        }

        // check arguments and options
        if (has_loss)
        {
                print("loss", get_losses());
        }
        if (has_task)
        {
                print("task", get_tasks());
        }
        if (has_layer)
        {
                print("layer", get_layers());
        }
        if (has_enhancer)
        {
                print("enhancer", get_enhancers());
        }
        if (has_trainer)
        {
                print("trainer", get_trainers());
        }
        if (has_batch)
        {
                print("batch solvers", get_batch_solvers());
        }
        if (has_stoch)
        {
                print("stochastic solvers", get_stoch_solvers());
        }
        if (has_system || has_sys_physical)
        {
                std::cout << "physical CPUs..." << nano::physical_cpus() << std::endl;
        }
        if (has_system || has_sys_logical)
        {
                std::cout << "logical CPUs...." << nano::logical_cpus() << std::endl;
        }
        if (has_system || has_sys_memsize)
        {
                std::cout << "memsize........." << nano::memsize_gb() << "GB" << std::endl;
        }
        if (has_version)
        {
                std::cout << nano::major_version << "." << nano::minor_version << std::endl;
        }
        if (has_git_hash)
        {
                std::cout << nano::git_commit_hash << std::endl;
        }

        // OK
        return EXIT_SUCCESS;
}
<commit_msg>update apps/info<commit_after>#include "loss.h"
#include "layer.h"
#include "model.h"
#include "version.h"
#include "trainer.h"
#include "enhancer.h"
#include "text/table.h"
#include "text/cmdline.h"
#include "solver_batch.h"
#include "solver_stoch.h"
#include <iostream>

using namespace nano;

namespace
{
        template <typename tobject>
        void print(const string_t& name, const factory_t<tobject>& factory)
        {
                table_t table;
                table.header() << name << "description" << "configuration";
                table.delim();
                for (const auto& id : factory.ids())
                {
                        json_writer_t writer;
                        factory.get(id)->config(writer);
                        table.append() << id << factory.description(id) << writer.str();
                }
                std::cout << table;
        }
}

int main(int argc, const char* argv[])
{
        // parse the command line
        cmdline_t cmdline("display the registered objects");
        cmdline.add("", "loss",                 "loss functions");
        cmdline.add("", "task",                 "tasks");
        cmdline.add("", "layer",                "layers to built models");
        cmdline.add("", "enhancer",             "task enhancers");
        cmdline.add("", "trainer",              "training methods");
        cmdline.add("", "batch",                "batch optimization algorithms");
        cmdline.add("", "stoch",                "stochastic optimization algorithms");
        cmdline.add("", "version",              "library version");
        cmdline.add("", "git-hash",             "git commit hash");
        cmdline.add("", "system",               "system: all available information");
        cmdline.add("", "sys-logical-cpus",     "system: number of logical cpus");
        cmdline.add("", "sys-physical-cpus",    "system: number of physical cpus");
        cmdline.add("", "sys-memsize",          "system: memory size in GB");

        cmdline.process(argc, argv);

        const bool has_loss = cmdline.has("loss");
        const bool has_task = cmdline.has("task");
        const bool has_layer = cmdline.has("layer");
        const bool has_enhancer = cmdline.has("enhancer");
        const bool has_trainer = cmdline.has("trainer");
        const bool has_batch = cmdline.has("batch");
        const bool has_stoch = cmdline.has("stoch");
        const bool has_system = cmdline.has("system");
        const bool has_sys_logical = cmdline.has("sys-logical-cpus");
        const bool has_sys_physical = cmdline.has("sys-physical-cpus");
        const bool has_sys_memsize = cmdline.has("sys-memsize");
        const bool has_version = cmdline.has("version");
        const bool has_git_hash = cmdline.has("git-hash");

        if (    !has_loss &&
                !has_task &&
                !has_layer &&
                !has_enhancer &&
                !has_trainer &&
                !has_batch &&
                !has_stoch &&
                !has_system &&
                !has_sys_logical &&
                !has_sys_physical &&
                !has_sys_memsize &&
                !has_version &&
                !has_git_hash)
        {
                cmdline.usage();
                return EXIT_FAILURE;
        }

        // check arguments and options
        if (has_loss)
        {
                print("loss", get_losses());
        }
        if (has_task)
        {
                print("task", get_tasks());
        }
        if (has_layer)
        {
                print("layer", get_layers());
        }
        if (has_enhancer)
        {
                print("enhancer", get_enhancers());
        }
        if (has_trainer)
        {
                print("trainer", get_trainers());
        }
        if (has_batch)
        {
                print("batch solvers", get_batch_solvers());
        }
        if (has_stoch)
        {
                print("stochastic solvers", get_stoch_solvers());
        }
        if (has_system || has_sys_physical)
        {
                std::cout << "physical CPUs..." << nano::physical_cpus() << std::endl;
        }
        if (has_system || has_sys_logical)
        {
                std::cout << "logical CPUs...." << nano::logical_cpus() << std::endl;
        }
        if (has_system || has_sys_memsize)
        {
                std::cout << "memsize........." << nano::memsize_gb() << "GB" << std::endl;
        }
        if (has_version)
        {
                std::cout << nano::major_version << "." << nano::minor_version << std::endl;
        }
        if (has_git_hash)
        {
                std::cout << nano::git_commit_hash << std::endl;
        }

        // OK
        return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>#include "common.h"
#include "Ruby.h"
#include "RubyObject.h"
#include <node.h>
#include <cassert>
#include <limits>

#include <iostream>
using namespace std;

using namespace v8;

const int32_t MIN_INT32 = std::numeric_limits<int32_t>::min();
const int32_t MAX_INT32 = std::numeric_limits<int32_t>::max();

Handle<Value> rubyToV8(VALUE val)
{
  NanEscapableScope();

  log("Converting " << RSTRING_PTR(rb_funcall2(val, rb_intern("to_s"), 0, NULL)) << " to v8" << endl);

  int type = TYPE(val);
  switch (type) {
  case T_NONE:
  case T_NIL: // TODO: Is this right?
     return NanEscapeScope(NanUndefined());
  case T_FLOAT:
     return NanEscapeScope(NanNew<Number>(RFLOAT_VALUE(val)));
  case T_STRING:
     return NanEscapeScope(NanNew<String>(RSTRING_PTR(val), RSTRING_LEN(val)));
  case T_ARRAY: {
    int len = RARRAY_LEN(val);
    Local<Array> array = NanNew<Array>(len);
    for (int i = 0; i < len; i++) {
      array->Set(i, rubyToV8(rb_ary_entry(val, i)));
    }

    return NanEscapeScope(array);
  }
  case T_FIXNUM: {
    long longVal = FIX2LONG(val);
    if (longVal >= MIN_INT32 && longVal <= MAX_INT32) {
      return NanEscapeScope(NanNew<Integer>(longVal));
    }
    else
      return NanEscapeScope(NanNew<Number>(longVal));
  }
  case T_BIGNUM:
    return NanEscapeScope(NanNew<Number>(rb_num2long(val)));
  case T_TRUE:
    return NanEscapeScope(NanTrue());
  case T_FALSE:
    return NanEscapeScope(NanFalse());
  case T_OBJECT:
  case T_DATA: {
    Local<Object> owner = RubyObject::RubyUnwrap(val);
    if (owner.IsEmpty()) {
      VALUE klass = rb_class_of(val);
      Local<Function> rubyClass = RubyObject::GetClass(klass);

      Local<Function> ctor = Ruby::GetCtor(rubyClass);
      Handle<Value> argv[] = { External::New((void*)val) };
      return NanEscapeScope(ctor->NewInstance(1, argv));
    }
    else
      return NanEscapeScope(owner);
  }
  default:
    cerr << "Unknown ruby type(" << type << "): " << rb_obj_classname(val) << endl;
    return NanEscapeScope(NanUndefined());
  }
}

VALUE v8ToRuby(Handle<Value> val)
{
  NanScope();

  log("Converting " << *String::Utf8Value(val) << " to ruby" << endl);

  if (val->IsUndefined())
    return Qnil; // TODO: Is this right?
  else if (val->IsNull())
    return Qnil; // TODO: Is this right?
  else if (val->IsTrue())
    return Qtrue;
  else if (val->IsFalse())
    return Qfalse;
  else if (val->IsString()) {
    // TODO: Is there any way to Write the string directly into the rb string?
    String::Utf8Value str(val);
    return rb_str_new(*str, str.length());
  }
  else if (val->IsArray()) {
    Handle<Array> v8Arr = val.As<Array>();
    VALUE rbArr = rb_ary_new2(v8Arr->Length());
    for (uint32_t i = 0; i < v8Arr->Length(); i++) {
      rb_ary_store(rbArr, i, v8ToRuby(v8Arr->Get(i)));
    }

    return rbArr;
  }
  else if (val->IsInt32())
    return INT2NUM(val->Int32Value());
  else if (val->IsUint32())
    return UINT2NUM(val->Uint32Value());
  else if (val->IsNumber())
    return rb_float_new(val->NumberValue());
  else if (val->IsObject()) {
    // TODO: Is this the best way to do this? Should we add the hidden prop to
    // the owner object?
    Local<Value> wrappedVal = val.As<Object>()->Get(NanNew<String>("_rubyObj"));
    if (wrappedVal->IsObject()) {
      Local<Object> wrappedObj = wrappedVal.As<Object>();
      Local<Value> hidden =
        wrappedObj->GetHiddenValue(NanNew<String>(RubyObject::RUBY_OBJECT_TAG));
      if (!hidden.IsEmpty() && hidden->IsTrue()) {
        RubyObject* rubyObj = node::ObjectWrap::Unwrap<RubyObject>(wrappedObj);
        return rubyObj->GetObject();
      }
    }
  }

  // TODO: Should we wrap objects here?
  String::Utf8Value str(val->ToDetailString());
  cerr << "Unknown v8 type: " << *str << endl;
  return Qnil;
}

Handle<Value> rubyExToV8(VALUE ex)
{
  NanEscapableScope();

  assert(rb_obj_is_kind_of(ex, rb_eException) == Qtrue);

  VALUE msg = rb_funcall(ex, rb_intern("message"), 0);
  Local<String> msgStr = NanNew<String>(RSTRING_PTR(msg), RSTRING_LEN(msg));

  // TODO: Do these error constructions work in all node versions?
  VALUE klass = rb_class_of(ex);
  if (klass == rb_eArgError ||
      klass == rb_eLoadError)
    return NanEscapeScope(Exception::Error(msgStr));
  else if (klass == rb_eNameError ||
           klass == rb_eNoMethodError)
    return NanEscapeScope(Exception::ReferenceError(msgStr));
  else if (klass == rb_eTypeError)
    return NanEscapeScope(Exception::TypeError(msgStr));
  else if (klass == rb_eSyntaxError)
    return NanEscapeScope(Exception::SyntaxError(msgStr));
  else {
    cerr << "Unknown ruby exception: " << rb_obj_classname(ex) << endl;
    return NanEscapeScope(Exception::Error(msgStr));
  }
}

VALUE RescueCB(VALUE data, VALUE ex)
{
  VALUE *storedEx = reinterpret_cast<VALUE*>(data);
  *storedEx = ex;

  return Qnil;
}

VALUE CallV8FromRuby(const Handle<Object> recv,
                     const Handle<Function> callback,
                     int argc, const VALUE* argv)
{
  NanScope();

  std::vector<Handle<Value> > v8Args(argc);
  for (int i = 0; i < argc; i++) {
    v8Args[i] = rubyToV8(argv[i]);
  }

  Handle<Value> ret = NanMakeCallback(recv, callback, argc, &v8Args[0]);

  return v8ToRuby(ret);
}

struct MethodCaller
{
  inline
  MethodCaller(VALUE o, _NAN_METHOD_ARGS_TYPE args):
    obj(o), methodID(ID(EXTERNAL_UNWRAP(args.Data()))), rubyArgs(args.Length())
  {
    // TODO: Is this right? Is there a way to determine if a block is expected?
    if (args.Length() > 0 && args[args.Length()-1]->IsFunction()) {
      block = args[args.Length()-1].As<Function>();
      rubyArgs.resize(args.Length()-1);
    }

    for (size_t i = 0; i < rubyArgs.size(); i++) {
      rubyArgs[i] = v8ToRuby(args[i]);
    }
  }

  VALUE operator()() const
  {
    log("Calling method: " << rb_obj_classname(obj) << "." <<
        rb_id2name(methodID) << " with " << rubyArgs.size() << " args");

    if (block.IsEmpty()) {
      log(endl);

      return rb_funcall2(obj, methodID, rubyArgs.size(), (VALUE*)&rubyArgs[0]);
    }
    else {
      log(" and a block" << endl);

      // TODO: Probably not available in Ruby < 1.9
      return rb_block_call(obj, methodID, rubyArgs.size(), (VALUE*)&rubyArgs[0],
                           RUBY_METHOD_FUNC(BlockFunc), (VALUE)this);
    }
  }

  static VALUE BlockFunc(VALUE, VALUE data, int argc, const VALUE* rbArgv)
  {
    MethodCaller* self = reinterpret_cast<MethodCaller*>(data);

    return CallV8FromRuby(NanGetCurrentContext()->Global(), self->block,
                          argc, rbArgv);
  }

  VALUE obj;
  VALUE methodID;
  std::vector<VALUE> rubyArgs;
  // TODO: Should this be persistent?
  Local<Function> block;
};

Handle<Value> CallRubyFromV8(VALUE recv, _NAN_METHOD_ARGS_TYPE args)
{
  NanEscapableScope();

  VALUE ex;
  VALUE res = SafeRubyCall(MethodCaller(recv, args), ex);
  if (ex != Qnil) {
    NanThrowError(rubyExToV8(ex));
    return NanEscapeScope(NanUndefined());
  }

  return NanEscapeScope(rubyToV8(res));
}

void DumpRubyArgs(int argc, VALUE* argv)
{
#ifdef _DEBUG
  for (int i = 0; i < argc; i++) {
    VALUE str = rb_funcall2(argv[i], rb_intern("to_s"), 0, NULL);
    cout << i << ": " << StringValueCStr(str) << endl;
  }
#endif
}

void DumpV8Props(Handle<Object> obj)
{
#ifdef _DEBUG
  NanScope();

  Local<Array> propNames = obj->GetPropertyNames();
  for (uint32_t i = 0; i < propNames->Length(); i++) {
    Local<Value> key = propNames->Get(i);

    cout << *String::Utf8Value(key) << endl;
  }
#endif
}

void DumpV8Args(_NAN_METHOD_ARGS_TYPE args)
{
#ifdef _DEBUG
  NanScope();

  for (int i = 0; i < args.Length(); i++) {
    cout << i << ": " << *String::Utf8Value(args[i]) << endl;
  }
#endif
}
<commit_msg>Converting strings from v8 to ruby no longer requires temp buffer<commit_after>#include "common.h"
#include "Ruby.h"
#include "RubyObject.h"
#include <node.h>
#include <cassert>
#include <limits>

#include <iostream>
using namespace std;

using namespace v8;

const int32_t MIN_INT32 = std::numeric_limits<int32_t>::min();
const int32_t MAX_INT32 = std::numeric_limits<int32_t>::max();

Handle<Value> rubyToV8(VALUE val)
{
  NanEscapableScope();

  log("Converting " << RSTRING_PTR(rb_funcall2(val, rb_intern("to_s"), 0, NULL)) << " to v8" << endl);

  int type = TYPE(val);
  switch (type) {
  case T_NONE:
  case T_NIL: // TODO: Is this right?
     return NanEscapeScope(NanUndefined());
  case T_FLOAT:
     return NanEscapeScope(NanNew<Number>(RFLOAT_VALUE(val)));
  case T_STRING:
     return NanEscapeScope(NanNew<String>(RSTRING_PTR(val), RSTRING_LEN(val)));
  case T_ARRAY: {
    int len = RARRAY_LEN(val);
    Local<Array> array = NanNew<Array>(len);
    for (int i = 0; i < len; i++) {
      array->Set(i, rubyToV8(rb_ary_entry(val, i)));
    }

    return NanEscapeScope(array);
  }
  case T_FIXNUM: {
    long longVal = FIX2LONG(val);
    if (longVal >= MIN_INT32 && longVal <= MAX_INT32) {
      return NanEscapeScope(NanNew<Integer>(longVal));
    }
    else
      return NanEscapeScope(NanNew<Number>(longVal));
  }
  case T_BIGNUM:
    return NanEscapeScope(NanNew<Number>(rb_num2long(val)));
  case T_TRUE:
    return NanEscapeScope(NanTrue());
  case T_FALSE:
    return NanEscapeScope(NanFalse());
  case T_OBJECT:
  case T_DATA: {
    Local<Object> owner = RubyObject::RubyUnwrap(val);
    if (owner.IsEmpty()) {
      VALUE klass = rb_class_of(val);
      Local<Function> rubyClass = RubyObject::GetClass(klass);

      Local<Function> ctor = Ruby::GetCtor(rubyClass);
      Handle<Value> argv[] = { External::New((void*)val) };
      return NanEscapeScope(ctor->NewInstance(1, argv));
    }
    else
      return NanEscapeScope(owner);
  }
  default:
    cerr << "Unknown ruby type(" << type << "): " << rb_obj_classname(val) << endl;
    return NanEscapeScope(NanUndefined());
  }
}

VALUE v8ToRuby(Handle<Value> val)
{
  NanScope();

  log("Converting " << *String::Utf8Value(val) << " to ruby" << endl);

  if (val->IsUndefined())
    return Qnil; // TODO: Is this right?
  else if (val->IsNull())
    return Qnil; // TODO: Is this right?
  else if (val->IsTrue())
    return Qtrue;
  else if (val->IsFalse())
    return Qfalse;
  else if (val->IsString()) {
    // TODO: We should handle encoding here
    Handle<String> str = val.As<String>();
    VALUE rbStr = rb_str_new(NULL, str->Utf8Length());
    str->WriteUtf8(RSTRING_PTR(rbStr));
    return rbStr;
  }
  else if (val->IsArray()) {
    Handle<Array> v8Arr = val.As<Array>();
    VALUE rbArr = rb_ary_new2(v8Arr->Length());
    for (uint32_t i = 0; i < v8Arr->Length(); i++) {
      rb_ary_store(rbArr, i, v8ToRuby(v8Arr->Get(i)));
    }

    return rbArr;
  }
  else if (val->IsInt32())
    return INT2NUM(val->Int32Value());
  else if (val->IsUint32())
    return UINT2NUM(val->Uint32Value());
  else if (val->IsNumber())
    return rb_float_new(val->NumberValue());
  else if (val->IsObject()) {
    // TODO: Is this the best way to do this? Should we add the hidden prop to
    // the owner object?
    Local<Value> wrappedVal = val.As<Object>()->Get(NanNew<String>("_rubyObj"));
    if (wrappedVal->IsObject()) {
      Local<Object> wrappedObj = wrappedVal.As<Object>();
      Local<Value> hidden =
        wrappedObj->GetHiddenValue(NanNew<String>(RubyObject::RUBY_OBJECT_TAG));
      if (!hidden.IsEmpty() && hidden->IsTrue()) {
        RubyObject* rubyObj = node::ObjectWrap::Unwrap<RubyObject>(wrappedObj);
        return rubyObj->GetObject();
      }
    }
  }

  // TODO: Should we wrap objects here?
  String::Utf8Value str(val->ToDetailString());
  cerr << "Unknown v8 type: " << *str << endl;
  return Qnil;
}

Handle<Value> rubyExToV8(VALUE ex)
{
  NanEscapableScope();

  assert(rb_obj_is_kind_of(ex, rb_eException) == Qtrue);

  VALUE msg = rb_funcall(ex, rb_intern("message"), 0);
  Local<String> msgStr = NanNew<String>(RSTRING_PTR(msg), RSTRING_LEN(msg));

  // TODO: Do these error constructions work in all node versions?
  VALUE klass = rb_class_of(ex);
  if (klass == rb_eArgError ||
      klass == rb_eLoadError)
    return NanEscapeScope(Exception::Error(msgStr));
  else if (klass == rb_eNameError ||
           klass == rb_eNoMethodError)
    return NanEscapeScope(Exception::ReferenceError(msgStr));
  else if (klass == rb_eTypeError)
    return NanEscapeScope(Exception::TypeError(msgStr));
  else if (klass == rb_eSyntaxError)
    return NanEscapeScope(Exception::SyntaxError(msgStr));
  else {
    cerr << "Unknown ruby exception: " << rb_obj_classname(ex) << endl;
    return NanEscapeScope(Exception::Error(msgStr));
  }
}

VALUE RescueCB(VALUE data, VALUE ex)
{
  VALUE *storedEx = reinterpret_cast<VALUE*>(data);
  *storedEx = ex;

  return Qnil;
}

VALUE CallV8FromRuby(const Handle<Object> recv,
                     const Handle<Function> callback,
                     int argc, const VALUE* argv)
{
  NanScope();

  std::vector<Handle<Value> > v8Args(argc);
  for (int i = 0; i < argc; i++) {
    v8Args[i] = rubyToV8(argv[i]);
  }

  Handle<Value> ret = NanMakeCallback(recv, callback, argc, &v8Args[0]);

  return v8ToRuby(ret);
}

struct MethodCaller
{
  inline
  MethodCaller(VALUE o, _NAN_METHOD_ARGS_TYPE args):
    obj(o), methodID(ID(EXTERNAL_UNWRAP(args.Data()))), rubyArgs(args.Length())
  {
    // TODO: Is this right? Is there a way to determine if a block is expected?
    if (args.Length() > 0 && args[args.Length()-1]->IsFunction()) {
      block = args[args.Length()-1].As<Function>();
      rubyArgs.resize(args.Length()-1);
    }

    for (size_t i = 0; i < rubyArgs.size(); i++) {
      rubyArgs[i] = v8ToRuby(args[i]);
    }
  }

  VALUE operator()() const
  {
    log("Calling method: " << rb_obj_classname(obj) << "." <<
        rb_id2name(methodID) << " with " << rubyArgs.size() << " args");

    if (block.IsEmpty()) {
      log(endl);

      return rb_funcall2(obj, methodID, rubyArgs.size(), (VALUE*)&rubyArgs[0]);
    }
    else {
      log(" and a block" << endl);

      // TODO: Probably not available in Ruby < 1.9
      return rb_block_call(obj, methodID, rubyArgs.size(), (VALUE*)&rubyArgs[0],
                           RUBY_METHOD_FUNC(BlockFunc), (VALUE)this);
    }
  }

  static VALUE BlockFunc(VALUE, VALUE data, int argc, const VALUE* rbArgv)
  {
    MethodCaller* self = reinterpret_cast<MethodCaller*>(data);

    return CallV8FromRuby(NanGetCurrentContext()->Global(), self->block,
                          argc, rbArgv);
  }

  VALUE obj;
  VALUE methodID;
  std::vector<VALUE> rubyArgs;
  // TODO: Should this be persistent?
  Local<Function> block;
};

Handle<Value> CallRubyFromV8(VALUE recv, _NAN_METHOD_ARGS_TYPE args)
{
  NanEscapableScope();

  VALUE ex;
  VALUE res = SafeRubyCall(MethodCaller(recv, args), ex);
  if (ex != Qnil) {
    NanThrowError(rubyExToV8(ex));
    return NanEscapeScope(NanUndefined());
  }

  return NanEscapeScope(rubyToV8(res));
}

void DumpRubyArgs(int argc, VALUE* argv)
{
#ifdef _DEBUG
  for (int i = 0; i < argc; i++) {
    VALUE str = rb_funcall2(argv[i], rb_intern("to_s"), 0, NULL);
    cout << i << ": " << StringValueCStr(str) << endl;
  }
#endif
}

void DumpV8Props(Handle<Object> obj)
{
#ifdef _DEBUG
  NanScope();

  Local<Array> propNames = obj->GetPropertyNames();
  for (uint32_t i = 0; i < propNames->Length(); i++) {
    Local<Value> key = propNames->Get(i);

    cout << *String::Utf8Value(key) << endl;
  }
#endif
}

void DumpV8Args(_NAN_METHOD_ARGS_TYPE args)
{
#ifdef _DEBUG
  NanScope();

  for (int i = 0; i < args.Length(); i++) {
    cout << i << ": " << *String::Utf8Value(args[i]) << endl;
  }
#endif
}
<|endoftext|>


<commit_before>#ifndef DUNE_DETAILED_DISCRETIZATIONS_ASSEMBLER_SYSTEM_HH
#define DUNE_DETAILED_DISCRETIZATIONS_ASSEMBLER_SYSTEM_HH

#include <vector>

#include <dune/common/dynmatrix.hh>
#include <dune/common/dynvector.hh>
#include <dune/common/shared_ptr.hh>

namespace Dune {
namespace Detailed {
namespace Discretizations {
namespace Assembler {

template <class TestFunctionSpaceImp, class AnsatzFunctionSpaceImp = TestFunctionSpaceImp>
class System
{
public:
  typedef TestFunctionSpaceImp TestFunctionSpaceType;

  typedef AnsatzFunctionSpaceImp AnsatzFunctionSpaceType;

  typedef System<TestFunctionSpaceImp, AnsatzFunctionSpaceImp> ThisType;

private:
  typedef typename TestFunctionSpaceType::GridViewType GridViewType;

  typedef typename GridViewType::template Codim<0>::Entity EntityType;

  typedef typename TestFunctionSpaceType::FunctionSpaceType::RangeFieldType RangeFieldType;

  typedef Dune::DynamicMatrix<RangeFieldType> LocalMatrixType;

  typedef Dune::DynamicVector<RangeFieldType> LocalVectorType;

  typedef std::vector<std::vector<LocalMatrixType>> LocalMatricesContainerType;

  typedef std::vector<std::vector<LocalVectorType>> LocalVectorsContainerType;

  class LocalMatrixAssemblerApplication
  {
  public:
    virtual void apply(const TestFunctionSpaceType& /*_testSpace*/, const AnsatzFunctionSpaceType& /*_ansatzSpace*/,
                       const EntityType& /*_entity*/,
                       LocalMatricesContainerType& /*_localMatricesContainer*/) const = 0;

    virtual std::vector<unsigned int> numTmpObjectsRequired() const = 0;
  }; // class LocalOperatorApplication

  template <class LocalMatrixAssemblerType, class MatrixType>
  class LocalMatrixAssemblerApplicationWrapper : public LocalMatrixAssemblerApplication
  {
  public:
    LocalMatrixAssemblerApplicationWrapper(const Dune::shared_ptr<const LocalMatrixAssemblerType> _localMatrixAssembler,
                                           Dune::shared_ptr<MatrixType> _matrix)
      : localMatrixAssembler_(_localMatrixAssembler)
      , matrix_(_matrix)
    {
    }

    virtual void apply(const TestFunctionSpaceType& _testSpace, const AnsatzFunctionSpaceType& _ansatzSpace,
                       const EntityType& _entity, LocalMatricesContainerType& _localMatricesContainer) const
    {
      localMatrixAssembler_->assembleLocal(_testSpace, _ansatzSpace, _entity, *matrix_, _localMatricesContainer);
    } // virtual void applyLocal(...) const

    virtual std::vector<unsigned int> numTmpObjectsRequired() const
    {
      return localMatrixAssembler_->numTmpObjectsRequired();
    } // virtual std::vector< unsigned int > numTmpObjectsRequired() const

  private:
    const Dune::shared_ptr<const LocalMatrixAssemblerType> localMatrixAssembler_;
    Dune::shared_ptr<MatrixType> matrix_;
  }; // class LocalMatrixAssemblerApplicationWrapper

  class LocalVectorAssemblerApplication
  {
  public:
    virtual void apply(const TestFunctionSpaceType& /*_testSpace*/, const EntityType& /*_entity*/,
                       LocalVectorsContainerType& /*_localMatricesContainer*/) const = 0;

    virtual std::vector<unsigned int> numTmpObjectsRequired() const = 0;
  }; // class LocalOperatorApplication

  template <class LocalVectorAssemblerType, class VectorType>
  class LocalVectorAssemblerApplicationWrapper : public LocalVectorAssemblerApplication
  {
  public:
    LocalVectorAssemblerApplicationWrapper(const Dune::shared_ptr<const LocalVectorAssemblerType> _localVectorAssembler,
                                           Dune::shared_ptr<VectorType> _vector)
      : localVectorAssembler_(_localVectorAssembler)
      , vector_(_vector)
    {
    }

    virtual void apply(const TestFunctionSpaceType& _testSpace, const EntityType& _entity,
                       LocalVectorsContainerType& _localVectorsContainer) const
    {
      localVectorAssembler_->assembleLocal(_testSpace, _entity, *vector_, _localVectorsContainer);
    } // virtual void applyLocal(...) const

    virtual std::vector<unsigned int> numTmpObjectsRequired() const
    {
      return localVectorAssembler_->numTmpObjectsRequired();
    } // virtual std::vector< unsigned int > numTmpObjectsRequired() const

  private:
    const Dune::shared_ptr<const LocalVectorAssemblerType> localVectorAssembler_;
    Dune::shared_ptr<VectorType> vector_;
  }; // class LocalMatrixAssemblerApplicationWrapper

public:
  System(const TestFunctionSpaceType& _testSpace, const AnsatzFunctionSpaceType& _ansatzSpace)
    : testSpace_(_testSpace)
    , ansatzSpace_(_ansatzSpace)
  {
  }

  System(const TestFunctionSpaceType& _testSpace)
    : testSpace_(_testSpace)
    , ansatzSpace_(_testSpace)
  {
  }

  const TestFunctionSpaceType& testSpace()
  {
    return testSpace_;
  }

  const AnsatzFunctionSpaceType& ansatzSpace()
  {
    return ansatzSpace_;
  }

  template <class LocalMatrixAssemblerType, class MatrixType>
  void addLocalMatrixAssembler(const Dune::shared_ptr<const LocalMatrixAssemblerType> _localMatrixAssembler,
                               Dune::shared_ptr<MatrixType> _matrix)
  {
    typedef LocalMatrixAssemblerApplicationWrapper<LocalMatrixAssemblerType, MatrixType> WrapperType;
    WrapperType* wrapper = new WrapperType(_localMatrixAssembler, _matrix);
    localMatrixAssemblers_.push_back(wrapper);
  }

  template <class LocalVectorAssemblerType, class VectorType>
  void addLocalVectorAssembler(const Dune::shared_ptr<const LocalVectorAssemblerType> _localVectorAssembler,
                               Dune::shared_ptr<VectorType> _vector)
  {
    typedef LocalVectorAssemblerApplicationWrapper<LocalVectorAssemblerType, VectorType> WrapperType;
    WrapperType* wrapper = new WrapperType(_localVectorAssembler, _vector);
    localVectorAssemblers_.push_back(wrapper);
  }

  void assemble() const
  {
    // common tmp storage for all entities
    // * for the matrix assemblers
    std::vector<unsigned int> numberOfTmpMatricesNeeded(2, 0);
    for (unsigned int ii = 0; ii < localMatrixAssemblers_.size(); ++ii) {
      const std::vector<unsigned int> tmp = localMatrixAssemblers_[ii]->numTmpObjectsRequired();
      numberOfTmpMatricesNeeded[0]        = std::max(numberOfTmpMatricesNeeded[0], tmp[0]);
      numberOfTmpMatricesNeeded[1]        = std::max(numberOfTmpMatricesNeeded[1], tmp[1]);
    }
    std::vector<LocalMatrixType> tmpLocalAssemblerMatrices(
        numberOfTmpMatricesNeeded[0],
        LocalMatrixType(testSpace_.map().maxLocalSize(), ansatzSpace_.map().maxLocalSize(), RangeFieldType(0)));
    std::vector<LocalMatrixType> tmpLocalOperatorMatrices(
        numberOfTmpMatricesNeeded[1],
        LocalMatrixType(testSpace_.map().maxLocalSize(), ansatzSpace_.map().maxLocalSize(), RangeFieldType(0)));
    std::vector<std::vector<LocalMatrixType>> tmpLocalMatricesContainer;
    tmpLocalMatricesContainer.push_back(tmpLocalAssemblerMatrices);
    tmpLocalMatricesContainer.push_back(tmpLocalOperatorMatrices);
    // * for the vector assemblers
    std::vector<unsigned int> numberOfTmpVectorsNeeded(2, 0);
    for (unsigned int ii = 0; ii < localVectorAssemblers_.size(); ++ii) {
      const std::vector<unsigned int> tmp = localVectorAssemblers_[ii]->numTmpObjectsRequired();
      numberOfTmpVectorsNeeded[0]         = std::max(numberOfTmpVectorsNeeded[0], tmp[0]);
      numberOfTmpVectorsNeeded[1]         = std::max(numberOfTmpVectorsNeeded[1], tmp[1]);
    }
    std::vector<LocalVectorType> tmpLocalAssemblerVectors(
        numberOfTmpVectorsNeeded[0], LocalVectorType(testSpace_.map().maxLocalSize(), RangeFieldType(0)));
    std::vector<LocalVectorType> tmpLocalFunctionalVectors(
        numberOfTmpVectorsNeeded[1], LocalVectorType(testSpace_.map().maxLocalSize(), RangeFieldType(0)));
    std::vector<std::vector<LocalVectorType>> tmpLocalVectorsContainer;
    tmpLocalVectorsContainer.push_back(tmpLocalAssemblerVectors);
    tmpLocalVectorsContainer.push_back(tmpLocalFunctionalVectors);

    // walk the grid
    typedef typename GridViewType::template Codim<0>::Iterator EntityIteratorType;
    for (EntityIteratorType entityIt = ansatzSpace_.gridView().template begin<0>();
         entityIt != ansatzSpace_.gridView().template end<0>();
         ++entityIt) {
      const EntityType& entity = *entityIt;
      // assemble local matrices
      for (unsigned int ii = 0; ii < localMatrixAssemblers_.size(); ++ii)
        localMatrixAssemblers_[ii]->apply(testSpace_, ansatzSpace_, entity, tmpLocalMatricesContainer);
      // assemble local vectors
      for (unsigned int ii = 0; ii < localVectorAssemblers_.size(); ++ii)
        localVectorAssemblers_[ii]->apply(testSpace_, entity, tmpLocalVectorsContainer);
    } // walk the grid
  } // void assemble() const

  template <class MatrixType, class VectorType>
  void applyConstraints(MatrixType& matrix, VectorType& vector) const
  {
    typedef typename AnsatzFunctionSpaceType::GridPartType GridPartType;
    typedef typename GridPartType::template Codim<0>::IteratorType EntityIteratorType;
    typedef typename GridPartType::template Codim<0>::EntityType EntityType;
    typedef typename AnsatzFunctionSpaceType::ConstraintsType ConstraintsType;
    typedef typename ConstraintsType::LocalConstraintsType LocalConstraintsType;
    // walk the grid to apply constraints
    const ConstraintsType& constraints = testSpace_.constraints();
    for (EntityIteratorType entityIterator = testSpace_.gridPart().template begin<0>();
         entityIterator != testSpace_.gridPart().template end<0>();
         ++entityIterator) {
      const EntityType& entity                     = *entityIterator;
      const LocalConstraintsType& localConstraints = constraints.local(entity);
      applyLocalMatrixConstraints(localConstraints, matrix);
      applyLocalVectorConstraints(localConstraints, vector);
    } // walk the grid to apply constraints
  } // void applyConstraints()

private:
  System(const ThisType&);
  ThisType& operator=(const ThisType&);

  template <class LocalConstraintsType, class MatrixType>
  void applyLocalMatrixConstraints(const LocalConstraintsType& localConstraints, MatrixType& matrix) const
  {
    for (unsigned int i = 0; i < localConstraints.rowDofsSize(); ++i) {
      const unsigned int rowDof = localConstraints.rowDofs(i);
      for (unsigned int j = 0; j < localConstraints.columnDofsSize(); ++j) {
        matrix.set(rowDof, localConstraints.columnDofs(j), localConstraints.localMatrix(i, j));
      }
    }
  } // void applyLocalMatrixConstraints(...)

  template <class LocalConstraintsType, class VectorType>
  void applyLocalVectorConstraints(const LocalConstraintsType& localConstraints, VectorType& vector) const
  {
    for (unsigned int i = 0; i < localConstraints.rowDofsSize(); ++i) {
      vector.set(localConstraints.rowDofs(i), 0.0);
    }
  } // void applyLocalVectorConstraints(...)

  const TestFunctionSpaceType& testSpace_;
  const AnsatzFunctionSpaceType& ansatzSpace_;
  std::vector<LocalMatrixAssemblerApplication*> localMatrixAssemblers_; //! TODO leaks
  std::vector<LocalVectorAssemblerApplication*> localVectorAssemblers_; //! TODO leaks
}; // class System

} // namespace Assembler
} // namespace Discretizations
} // namespace Detailed
} // namespace Dune

#endif // DUNE_DETAILED_DISCRETIZATIONS_ASSEMBLER_SYSTEM_HH
<commit_msg>[assembler.system] added applyMatrixConstraints() and applyVectorConstraints()<commit_after>#ifndef DUNE_DETAILED_DISCRETIZATIONS_ASSEMBLER_SYSTEM_HH
#define DUNE_DETAILED_DISCRETIZATIONS_ASSEMBLER_SYSTEM_HH

#include <vector>

#include <dune/common/dynmatrix.hh>
#include <dune/common/dynvector.hh>
#include <dune/common/shared_ptr.hh>

namespace Dune {
namespace Detailed {
namespace Discretizations {
namespace Assembler {

template <class TestFunctionSpaceImp, class AnsatzFunctionSpaceImp = TestFunctionSpaceImp>
class System
{
public:
  typedef TestFunctionSpaceImp TestFunctionSpaceType;

  typedef AnsatzFunctionSpaceImp AnsatzFunctionSpaceType;

  typedef System<TestFunctionSpaceImp, AnsatzFunctionSpaceImp> ThisType;

private:
  typedef typename TestFunctionSpaceType::GridViewType GridViewType;

  typedef typename GridViewType::template Codim<0>::Entity EntityType;

  typedef typename TestFunctionSpaceType::FunctionSpaceType::RangeFieldType RangeFieldType;

  typedef Dune::DynamicMatrix<RangeFieldType> LocalMatrixType;

  typedef Dune::DynamicVector<RangeFieldType> LocalVectorType;

  typedef std::vector<std::vector<LocalMatrixType>> LocalMatricesContainerType;

  typedef std::vector<std::vector<LocalVectorType>> LocalVectorsContainerType;

  class LocalMatrixAssemblerApplication
  {
  public:
    virtual void apply(const TestFunctionSpaceType& /*_testSpace*/, const AnsatzFunctionSpaceType& /*_ansatzSpace*/,
                       const EntityType& /*_entity*/,
                       LocalMatricesContainerType& /*_localMatricesContainer*/) const = 0;

    virtual std::vector<unsigned int> numTmpObjectsRequired() const = 0;
  }; // class LocalOperatorApplication

  template <class LocalMatrixAssemblerType, class MatrixType>
  class LocalMatrixAssemblerApplicationWrapper : public LocalMatrixAssemblerApplication
  {
  public:
    LocalMatrixAssemblerApplicationWrapper(const Dune::shared_ptr<const LocalMatrixAssemblerType> _localMatrixAssembler,
                                           Dune::shared_ptr<MatrixType> _matrix)
      : localMatrixAssembler_(_localMatrixAssembler)
      , matrix_(_matrix)
    {
    }

    virtual void apply(const TestFunctionSpaceType& _testSpace, const AnsatzFunctionSpaceType& _ansatzSpace,
                       const EntityType& _entity, LocalMatricesContainerType& _localMatricesContainer) const
    {
      localMatrixAssembler_->assembleLocal(_testSpace, _ansatzSpace, _entity, *matrix_, _localMatricesContainer);
    } // virtual void applyLocal(...) const

    virtual std::vector<unsigned int> numTmpObjectsRequired() const
    {
      return localMatrixAssembler_->numTmpObjectsRequired();
    } // virtual std::vector< unsigned int > numTmpObjectsRequired() const

  private:
    const Dune::shared_ptr<const LocalMatrixAssemblerType> localMatrixAssembler_;
    Dune::shared_ptr<MatrixType> matrix_;
  }; // class LocalMatrixAssemblerApplicationWrapper

  class LocalVectorAssemblerApplication
  {
  public:
    virtual void apply(const TestFunctionSpaceType& /*_testSpace*/, const EntityType& /*_entity*/,
                       LocalVectorsContainerType& /*_localMatricesContainer*/) const = 0;

    virtual std::vector<unsigned int> numTmpObjectsRequired() const = 0;
  }; // class LocalOperatorApplication

  template <class LocalVectorAssemblerType, class VectorType>
  class LocalVectorAssemblerApplicationWrapper : public LocalVectorAssemblerApplication
  {
  public:
    LocalVectorAssemblerApplicationWrapper(const Dune::shared_ptr<const LocalVectorAssemblerType> _localVectorAssembler,
                                           Dune::shared_ptr<VectorType> _vector)
      : localVectorAssembler_(_localVectorAssembler)
      , vector_(_vector)
    {
    }

    virtual void apply(const TestFunctionSpaceType& _testSpace, const EntityType& _entity,
                       LocalVectorsContainerType& _localVectorsContainer) const
    {
      localVectorAssembler_->assembleLocal(_testSpace, _entity, *vector_, _localVectorsContainer);
    } // virtual void applyLocal(...) const

    virtual std::vector<unsigned int> numTmpObjectsRequired() const
    {
      return localVectorAssembler_->numTmpObjectsRequired();
    } // virtual std::vector< unsigned int > numTmpObjectsRequired() const

  private:
    const Dune::shared_ptr<const LocalVectorAssemblerType> localVectorAssembler_;
    Dune::shared_ptr<VectorType> vector_;
  }; // class LocalMatrixAssemblerApplicationWrapper

public:
  System(const TestFunctionSpaceType& _testSpace, const AnsatzFunctionSpaceType& _ansatzSpace)
    : testSpace_(_testSpace)
    , ansatzSpace_(_ansatzSpace)
  {
  }

  System(const TestFunctionSpaceType& _testSpace)
    : testSpace_(_testSpace)
    , ansatzSpace_(_testSpace)
  {
  }

  const TestFunctionSpaceType& testSpace()
  {
    return testSpace_;
  }

  const AnsatzFunctionSpaceType& ansatzSpace()
  {
    return ansatzSpace_;
  }

  template <class LocalMatrixAssemblerType, class MatrixType>
  void addLocalMatrixAssembler(const Dune::shared_ptr<const LocalMatrixAssemblerType> _localMatrixAssembler,
                               Dune::shared_ptr<MatrixType> _matrix)
  {
    typedef LocalMatrixAssemblerApplicationWrapper<LocalMatrixAssemblerType, MatrixType> WrapperType;
    WrapperType* wrapper = new WrapperType(_localMatrixAssembler, _matrix);
    localMatrixAssemblers_.push_back(wrapper);
  }

  template <class LocalVectorAssemblerType, class VectorType>
  void addLocalVectorAssembler(const Dune::shared_ptr<const LocalVectorAssemblerType> _localVectorAssembler,
                               Dune::shared_ptr<VectorType> _vector)
  {
    typedef LocalVectorAssemblerApplicationWrapper<LocalVectorAssemblerType, VectorType> WrapperType;
    WrapperType* wrapper = new WrapperType(_localVectorAssembler, _vector);
    localVectorAssemblers_.push_back(wrapper);
  }

  void assemble() const
  {
    // common tmp storage for all entities
    // * for the matrix assemblers
    std::vector<unsigned int> numberOfTmpMatricesNeeded(2, 0);
    for (unsigned int ii = 0; ii < localMatrixAssemblers_.size(); ++ii) {
      const std::vector<unsigned int> tmp = localMatrixAssemblers_[ii]->numTmpObjectsRequired();
      numberOfTmpMatricesNeeded[0]        = std::max(numberOfTmpMatricesNeeded[0], tmp[0]);
      numberOfTmpMatricesNeeded[1]        = std::max(numberOfTmpMatricesNeeded[1], tmp[1]);
    }
    std::vector<LocalMatrixType> tmpLocalAssemblerMatrices(
        numberOfTmpMatricesNeeded[0],
        LocalMatrixType(testSpace_.map().maxLocalSize(), ansatzSpace_.map().maxLocalSize(), RangeFieldType(0)));
    std::vector<LocalMatrixType> tmpLocalOperatorMatrices(
        numberOfTmpMatricesNeeded[1],
        LocalMatrixType(testSpace_.map().maxLocalSize(), ansatzSpace_.map().maxLocalSize(), RangeFieldType(0)));
    std::vector<std::vector<LocalMatrixType>> tmpLocalMatricesContainer;
    tmpLocalMatricesContainer.push_back(tmpLocalAssemblerMatrices);
    tmpLocalMatricesContainer.push_back(tmpLocalOperatorMatrices);
    // * for the vector assemblers
    std::vector<unsigned int> numberOfTmpVectorsNeeded(2, 0);
    for (unsigned int ii = 0; ii < localVectorAssemblers_.size(); ++ii) {
      const std::vector<unsigned int> tmp = localVectorAssemblers_[ii]->numTmpObjectsRequired();
      numberOfTmpVectorsNeeded[0]         = std::max(numberOfTmpVectorsNeeded[0], tmp[0]);
      numberOfTmpVectorsNeeded[1]         = std::max(numberOfTmpVectorsNeeded[1], tmp[1]);
    }
    std::vector<LocalVectorType> tmpLocalAssemblerVectors(
        numberOfTmpVectorsNeeded[0], LocalVectorType(testSpace_.map().maxLocalSize(), RangeFieldType(0)));
    std::vector<LocalVectorType> tmpLocalFunctionalVectors(
        numberOfTmpVectorsNeeded[1], LocalVectorType(testSpace_.map().maxLocalSize(), RangeFieldType(0)));
    std::vector<std::vector<LocalVectorType>> tmpLocalVectorsContainer;
    tmpLocalVectorsContainer.push_back(tmpLocalAssemblerVectors);
    tmpLocalVectorsContainer.push_back(tmpLocalFunctionalVectors);

    // walk the grid
    typedef typename GridViewType::template Codim<0>::Iterator EntityIteratorType;
    for (EntityIteratorType entityIt = ansatzSpace_.gridView().template begin<0>();
         entityIt != ansatzSpace_.gridView().template end<0>();
         ++entityIt) {
      const EntityType& entity = *entityIt;
      // assemble local matrices
      for (unsigned int ii = 0; ii < localMatrixAssemblers_.size(); ++ii)
        localMatrixAssemblers_[ii]->apply(testSpace_, ansatzSpace_, entity, tmpLocalMatricesContainer);
      // assemble local vectors
      for (unsigned int ii = 0; ii < localVectorAssemblers_.size(); ++ii)
        localVectorAssemblers_[ii]->apply(testSpace_, entity, tmpLocalVectorsContainer);
    } // walk the grid
  } // void assemble() const

  template <class MatrixType, class VectorType>
  void applyConstraints(MatrixType& matrix, VectorType& vector) const
  {
    typedef typename AnsatzFunctionSpaceType::GridPartType GridPartType;
    typedef typename GridPartType::template Codim<0>::IteratorType EntityIteratorType;
    typedef typename GridPartType::template Codim<0>::EntityType EntityType;
    typedef typename AnsatzFunctionSpaceType::ConstraintsType ConstraintsType;
    typedef typename ConstraintsType::LocalConstraintsType LocalConstraintsType;
    // walk the grid to apply constraints
    const ConstraintsType& constraints = testSpace_.constraints();
    for (EntityIteratorType entityIterator = testSpace_.gridPart().template begin<0>();
         entityIterator != testSpace_.gridPart().template end<0>();
         ++entityIterator) {
      const EntityType& entity                     = *entityIterator;
      const LocalConstraintsType& localConstraints = constraints.local(entity);
      applyLocalMatrixConstraints(localConstraints, matrix);
      applyLocalVectorConstraints(localConstraints, vector);
    } // walk the grid to apply constraints
  } // void applyConstraints(MatrixType& matrix, VectorType& vector) const

  template <class MatrixType>
  void applyMatrixConstraints(MatrixType& matrix) const
  {
    typedef typename AnsatzFunctionSpaceType::GridPartType GridPartType;
    typedef typename GridPartType::template Codim<0>::IteratorType EntityIteratorType;
    typedef typename GridPartType::template Codim<0>::EntityType EntityType;
    typedef typename AnsatzFunctionSpaceType::ConstraintsType ConstraintsType;
    typedef typename ConstraintsType::LocalConstraintsType LocalConstraintsType;
    // walk the grid to apply constraints
    const ConstraintsType& constraints = testSpace_.constraints();
    for (EntityIteratorType entityIterator = testSpace_.gridPart().template begin<0>();
         entityIterator != testSpace_.gridPart().template end<0>();
         ++entityIterator) {
      const EntityType& entity                     = *entityIterator;
      const LocalConstraintsType& localConstraints = constraints.local(entity);
      applyLocalMatrixConstraints(localConstraints, matrix);
    } // walk the grid to apply constraints
  } // void applyMatrixConstraints(MatrixType& matrix) const

  template <class VectorType>
  void applyVectorConstraints(VectorType& vector) const
  {
    typedef typename AnsatzFunctionSpaceType::GridPartType GridPartType;
    typedef typename GridPartType::template Codim<0>::IteratorType EntityIteratorType;
    typedef typename GridPartType::template Codim<0>::EntityType EntityType;
    typedef typename AnsatzFunctionSpaceType::ConstraintsType ConstraintsType;
    typedef typename ConstraintsType::LocalConstraintsType LocalConstraintsType;
    // walk the grid to apply constraints
    const ConstraintsType& constraints = testSpace_.constraints();
    for (EntityIteratorType entityIterator = testSpace_.gridPart().template begin<0>();
         entityIterator != testSpace_.gridPart().template end<0>();
         ++entityIterator) {
      const EntityType& entity                     = *entityIterator;
      const LocalConstraintsType& localConstraints = constraints.local(entity);
      applyLocalVectorConstraints(localConstraints, vector);
    } // walk the grid to apply constraints
  } // void applyVectorConstraints(VectorType& vector) const

private:
  System(const ThisType&);
  ThisType& operator=(const ThisType&);

  template <class LocalConstraintsType, class MatrixType>
  void applyLocalMatrixConstraints(const LocalConstraintsType& localConstraints, MatrixType& matrix) const
  {
    for (unsigned int i = 0; i < localConstraints.rowDofsSize(); ++i) {
      const unsigned int rowDof = localConstraints.rowDofs(i);
      for (unsigned int j = 0; j < localConstraints.columnDofsSize(); ++j) {
        matrix.set(rowDof, localConstraints.columnDofs(j), localConstraints.localMatrix(i, j));
      }
    }
  } // void applyLocalMatrixConstraints(...)

  template <class LocalConstraintsType, class VectorType>
  void applyLocalVectorConstraints(const LocalConstraintsType& localConstraints, VectorType& vector) const
  {
    for (unsigned int i = 0; i < localConstraints.rowDofsSize(); ++i) {
      vector.set(localConstraints.rowDofs(i), 0.0);
    }
  } // void applyLocalVectorConstraints(...)

  const TestFunctionSpaceType& testSpace_;
  const AnsatzFunctionSpaceType& ansatzSpace_;
  std::vector<LocalMatrixAssemblerApplication*> localMatrixAssemblers_; //! TODO leaks
  std::vector<LocalVectorAssemblerApplication*> localVectorAssemblers_; //! TODO leaks
}; // class System

} // namespace Assembler
} // namespace Discretizations
} // namespace Detailed
} // namespace Dune

#endif // DUNE_DETAILED_DISCRETIZATIONS_ASSEMBLER_SYSTEM_HH
<|endoftext|>


<commit_before>#ifndef SHARDING_HPP
#define SHARDING_HPP

#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <boost/unordered_map.hpp>
//#include <unordered_map>
#include <utility>
#include <math.h>
#include <memory>

#define MB_TO_BYTES 1024*1024

#include "../api/utility.hpp"

typedef boost::unordered_map<int, int> hash_t;

void shard_graph(params* par, char* gfilename){
    /* Open the graph file */
    std::ifstream gfile(gfilename);
    hash_t in_edge_count; // node <-- number of in edges

    int num_edges = 0;

    if(gfile.is_open()){
        std::string eline;
        while(getline(gfile, eline)){
            /* get an edge from the file */
            std::istringstream buff(eline);
            int from, to;

            buff >> from;
            buff >> to;

            if(in_edge_count.find(to) == in_edge_count.end()) { //if the node is encountered for the first time
                in_edge_count.insert(hash_t::value_type(to,1));
            }
            else {
                in_edge_count[to] += 1;
            }
        }

        for(auto it = in_edge_count.begin(); it != in_edge_count.end(); ++it){
            std::cout << it->first << " : " << it->second << std::endl;
            num_edges += it->second;
        }

        std::cout << "Number of nodes = " << in_edge_count.size() << std::endl;
        std::cout << "Number of edges = " << num_edges << std::endl;

        //gfile.close();
    }
    else {
        std::cout << "Unable to open file (#1). Exiting..." << std::endl;
        exit(1); //exit with error
    }

    /* calculate number of shards needed */
    int membudget_b = par->mem_budget * MB_TO_BYTES;
    par->max_num_edges = (int)floor((double)membudget_b / (double)par->edge_mem_cost);
    par->num_shards = (int)ceil((double)num_edges / (double)par->max_num_edges);

    std::cout << "Max number of edges per shard = " << par->max_num_edges << std::endl;
    std::cout << "Number of shards = " << par->num_shards << std::endl;

    /* assign vertices to shards */
    hash_t node_to_shard; // dest_node <-- shard_id
    int shard_index = 0;

    for(auto it = in_edge_count.begin(); it != in_edge_count.end(); ++it){
            int dest_node = (*it).first;
            int shard_edge_count = 0;

            // when we add the that node's edges to that shard, does it cross the max number of edges limit per shard
            if(shard_edge_count + (*it).second > par->max_num_edges){
                shard_index++; // move to the next shard
                shard_edge_count = 0;
            }

            node_to_shard.insert(hash_t::value_type(dest_node, shard_index)); // assign node -> shard[i]
            shard_edge_count+= (*it).second; //add the edge count to shard edge count
    }

    /* cleanning some memory */
    in_edge_count.clear();

    for(int i = 0; i < par->num_shards; ++i){
        std::cout << "Nodes in shard " << i << ":  " << std::endl;
        for(auto it=node_to_shard.begin(); it != node_to_shard.end(); ++it){
            if(it->second == i){
                std::cout << "\t" << it->first << std::endl;
            }
        }
    }

    /* create files for shards */
    std::vector<std::shared_ptr<std::ofstream> > ofs_shards;
    std::vector<std::string> shard_fnames;

    for(int i = 0; i< par->num_shards; ++i){
        std::ostringstream buff;
        buff << i << "_shard_";
        buff << get_fname_from_path(gfilename);

        shard_fnames.push_back(buff.str());

        std::cout << "Shard file created : " << buff.str() << std::endl;

        //std::ofstream tempf(buff.str());
        //ofs_shards.push_back(tempf);
        ofs_shards.push_back(std::make_shared<std::ofstream>(buff.str()));
    }

    /* scan the graph file and start writing to shards */
    gfile.clear(); // clear the state of file stream
    gfile.seekg(0, std::ios::beg); // go to the beginning of the file

    if(gfile.is_open()){
        std::string eline;
        while(getline(gfile, eline)){
            /* get an edge from the file */
            std::istringstream buff(eline);
            int from, to;

            buff >> from;
            buff >> to;

            //TODO it doesn't write to the file (I dont' know why)
            std::cout<< "Writing to shard " << node_to_shard[to] << " dest " << to << std::endl;
            //add the edge to its assigned shard
            (*(ofs_shards[node_to_shard[to]])) << from << " " << to << std::endl;
            //ofs_shards[node_to_shard[to]] << from << " " << to << std::endl;
        }

        gfile.close();
    }
    else {
        std::cout << "Unable to open file (#2). Exiting..." << std::endl;
        exit(1);
    }

    /* close shard files that are opened for writing*/
    for(int i = 0; i< par->num_shards; ++i){
        ofs_shards[i]->close();
        //ofs_shards[i].close();
    }

    /* cleanning some memory */
    ofs_shards.clear();

    /* sorting shard files according to their source files */
    std::cout << "Starting sorting shard files." << std::endl;

    /* read the shard files */
    std::vector<std::ifstream*> ifs_shards;

    for(int i = 0; i< par->num_shards; ++i){
        std::cout<< "Reading shard file : " << shard_fnames[i] << std::endl;

        std::ifstream tempf(shard_fnames[i]);
        ifs_shards.push_back(&tempf);
    }

    /* sort each shard according to their source node and write them to their file  */
    for(int i = 0; i< par->num_shards; ++i){
        std::map<int, std::vector<int> > shard_edge_list; // from --> to1,to2,to3

        //read first
        if(ifs_shards[i]->is_open()){
            std::string eline;
            while(getline(*ifs_shards[i], eline)){
                /* get an edge from the file */
                std::istringstream buff(eline);
                int from, to;

                buff >> from;
                buff >> to;

                if(shard_edge_list.find(from) == shard_edge_list.end()){ // if not in the map
                    std::vector<int> temp_v;
                    temp_v.push_back(to);

                    shard_edge_list.insert(std::make_pair(from,temp_v));
                }
                else {
                    shard_edge_list[from].push_back(to);
                }
            }

            ifs_shards[i]->close();
        }
        else {
            std::cout << "Unable to open file (#3). Exiting..." << std::endl;
            exit(1);
        }

        //write the sorted edges
        std::ofstream ofs_shard(shard_fnames[i]);

        //for each source node
        for(auto it = shard_edge_list.begin(); it != shard_edge_list.end(); ++it){
            //write the adj list to the shard in sorted order
            for(auto it2 = (*it).second.begin(); it2 != (*it).second.end(); ++it2){
                ofs_shard << (*it).first << " " << (*it2) << std::endl;
            }
        }

        ofs_shard.close();
    }

}
#endif
<commit_msg>sharding works now.<commit_after>#ifndef SHARDING_HPP
#define SHARDING_HPP

#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <boost/unordered_map.hpp>
//#include <unordered_map>
#include <utility>
#include <math.h>
#include <memory>

#define MB_TO_BYTES 1024*1024

#include "../api/utility.hpp"

typedef boost::unordered_map<int, int> hash_t;

void shard_graph(params* par, char* gfilename){
    /* Open the graph file */
    std::ifstream gfile(gfilename);
    hash_t in_edge_count; // node <-- number of in edges

    int num_edges = 0;

    if(gfile.is_open()){
        std::string eline;
        while(getline(gfile, eline)){
            /* get an edge from the file */
            std::istringstream buff(eline);
            int from, to;

            buff >> from;
            buff >> to;

            if(in_edge_count.find(to) == in_edge_count.end()) { //if the node is encountered for the first time
                in_edge_count.insert(hash_t::value_type(to,1));
            }
            else {
                in_edge_count[to] += 1;
            }
        }

        for(auto it = in_edge_count.begin(); it != in_edge_count.end(); ++it){
            std::cout << it->first << " : " << it->second << std::endl;
            num_edges += it->second;
        }

        std::cout << "Number of nodes = " << in_edge_count.size() << std::endl;
        std::cout << "Number of edges = " << num_edges << std::endl;

        //gfile.close();
    }
    else {
        std::cout << "Unable to open file (#1). Exiting..." << std::endl;
        exit(1); //exit with error
    }

    /* calculate number of shards needed */
    int membudget_b = par->mem_budget * MB_TO_BYTES;
    par->max_num_edges = (int)floor((double)membudget_b / (double)par->edge_mem_cost);
    par->num_shards = (int)ceil((double)num_edges / (double)par->max_num_edges);

    std::cout << "Max number of edges per shard = " << par->max_num_edges << std::endl;
    std::cout << "Number of shards = " << par->num_shards << std::endl;

    /* assign vertices to shards */
    hash_t node_to_shard; // dest_node <-- shard_id
    int shard_index = 0;

    for(auto it = in_edge_count.begin(); it != in_edge_count.end(); ++it){
            int dest_node = (*it).first;
            int shard_edge_count = 0;

            // when we add the that node's edges to that shard, does it cross the max number of edges limit per shard
            if(shard_edge_count + (*it).second > par->max_num_edges){
                shard_index++; // move to the next shard
                shard_edge_count = 0;
            }

            node_to_shard.insert(hash_t::value_type(dest_node, shard_index)); // assign node -> shard[i]
            shard_edge_count+= (*it).second; //add the edge count to shard edge count
    }

    /* cleanning some memory */
    in_edge_count.clear();

    for(int i = 0; i < par->num_shards; ++i){
        std::cout << "Nodes in shard " << i << ":  " << std::endl;
        for(auto it=node_to_shard.begin(); it != node_to_shard.end(); ++it){
            if(it->second == i){
                std::cout << "\t" << it->first << std::endl;
            }
        }
    }

    /* create files for shards */
    std::vector<std::shared_ptr<std::ofstream> > ofs_shards;
    std::vector<std::string> shard_fnames;

    for(int i = 0; i< par->num_shards; ++i){
        std::ostringstream buff;
        buff << i << "_shard_";
        buff << get_fname_from_path(gfilename);

        shard_fnames.push_back(buff.str());

        std::cout << "Shard file created : " << buff.str() << std::endl;

        ofs_shards.push_back(std::make_shared<std::ofstream>(buff.str()));
    }

    /* scan the graph file and start writing to shards */
    gfile.clear(); // clear the state of file stream
    gfile.seekg(0, std::ios::beg); // go to the beginning of the file

    if(gfile.is_open()){
        std::string eline;
        while(getline(gfile, eline)){
            /* get an edge from the file */
            std::istringstream buff(eline);
            int from, to;

            buff >> from;
            buff >> to;

            //TODO it doesn't write to the file (I dont' know why)
            std::cout<< "Writing to shard " << node_to_shard[to] << " dest " << to << std::endl;
            //add the edge to its assigned shard
            (*(ofs_shards[node_to_shard[to]])) << from << " " << to << std::endl;
        }

        gfile.close();
    }
    else {
        std::cout << "Unable to open file (#2). Exiting..." << std::endl;
        exit(1);
    }

    /* close shard files that are opened for writing*/
    for(int i = 0; i< par->num_shards; ++i){
        ofs_shards[i]->close();
    }

    /* cleanning some memory */
    ofs_shards.clear();

    /* sorting shard files according to their source files */
    std::cout << "Starting sorting shard files." << std::endl;

    /* read the shard files */
    std::vector<std::shared_ptr<std::ifstream> > ifs_shards;

    for(int i = 0; i< par->num_shards; ++i){
        std::cout<< "Reading shard file : " << shard_fnames[i] << std::endl;

        //std::ifstream tempf(shard_fnames[i]);
        //ifs_shards.push_back(&tempf);
        ifs_shards.push_back(std::make_shared<std::ifstream>(shard_fnames[i]));
    }

    /* sort each shard according to their source node and write them to their file  */
    for(int i = 0; i< par->num_shards; ++i){
        std::map<int, std::vector<int> > shard_edge_list; // from --> to1,to2,to3

        //read first
        if(ifs_shards[i]->is_open()){
            std::string eline;
            while(getline(*ifs_shards[i], eline)){
                /* get an edge from the file */
                std::istringstream buff(eline);
                int from, to;

                buff >> from;
                buff >> to;

                if(shard_edge_list.find(from) == shard_edge_list.end()){ // if not in the map
                    std::vector<int> temp_v;
                    temp_v.push_back(to);

                    shard_edge_list.insert(std::make_pair(from,temp_v));
                }
                else {
                    shard_edge_list[from].push_back(to);
                }
            }

            ifs_shards[i]->close();
        }
        else {
            std::cout << "Unable to open file (#3). Exiting..." << std::endl;
            exit(1);
        }

        //write the sorted edges
        std::ofstream ofs_shard(shard_fnames[i]);

        //for each source node
        for(auto it = shard_edge_list.begin(); it != shard_edge_list.end(); ++it){
            //write the adj list to the shard in sorted order
            for(auto it2 = (*it).second.begin(); it2 != (*it).second.end(); ++it2){
                ofs_shard << (*it).first << " " << (*it2) << std::endl;
            }
        }

        ofs_shard.close();
    }

}
#endif
<|endoftext|>


<commit_before>#include "ServerConnection.hpp"
namespace et {
ServerConnection::ServerConnection(
    std::shared_ptr<SocketHandler> _socketHandler, int _port,
    shared_ptr<ServerConnectionHandler> _serverHandler, const string& _key)
    : socketHandler(_socketHandler),
      port(_port),
      serverHandler(_serverHandler),
      stop(false),
      key(_key) {}

ServerConnection::~ServerConnection() {}

void ServerConnection::run() {
  while (!stop) {
    VLOG_EVERY_N(2, 30) << "Listening for connection" << endl;
    int clientSocketFd = socketHandler->listen(port);
    if (clientSocketFd < 0) {
      sleep(1);
      continue;
    }
    VLOG(1) << "SERVER: got client socket fd: " << clientSocketFd << endl;
    clientHandler(clientSocketFd);
  }
}

void ServerConnection::close() {
  stop = true;
  socketHandler->stopListening();
  for (const auto& it : clients) {
    it.second->closeSocket();
  }
  clients.clear();
}

void ServerConnection::clientHandler(int clientSocketFd) {
  int clientId;
  try {
    et::ConnectRequest request =
        socketHandler->readProto<et::ConnectRequest>(clientSocketFd, true);
    int version = request.version();
    if (version != PROTOCOL_VERSION) {
      et::ConnectResponse response;

      std::ostringstream errorStream;
      errorStream << "Mismatched protocol versions.  Client: " << request.version() << " != Server: " << PROTOCOL_VERSION;
      response.set_error(errorStream.str());
      socketHandler->writeProto(clientSocketFd, response, true);
      socketHandler->close(clientSocketFd);
      return;
    }
    clientId = request.clientid();
    if (clientId == -1) {
      clientId = newClient(clientSocketFd);
      shared_ptr<ServerClientConnection> serverClientState =
          getClient(clientId);
      if (serverHandler && !serverHandler->newClient(serverClientState)) {
        // Destroy the new client
        removeClient(serverClientState);
        socketHandler->close(clientSocketFd);
      }
    } else {
      if (!clientExists(clientId)) {
        throw std::runtime_error("Tried to revive an unknown client");
      }
      shared_ptr<ServerClientConnection> serverClientState =
          getClient(clientId);
      serverClientState->recoverClient(clientSocketFd);
    }
  } catch (const runtime_error& err) {
    // Comm failed, close the connection
    LOG(ERROR) << "Error handling new client: " << err.what();
    socketHandler->close(clientSocketFd);
  }
}

int ServerConnection::newClient(int socketFd) {
  int clientId = rand();
  while (clientExists(clientId)) {
    clientId++;
    if (clientId < 0) {
      throw std::runtime_error("Ran out of client ids");
    }
  }
  VLOG(1) << "Created client with id " << clientId << endl;

  et::ConnectResponse response;
  response.set_clientid(clientId);
  socketHandler->writeProto(socketFd, response, true);
  shared_ptr<ServerClientConnection> scc(
      new ServerClientConnection(socketHandler, clientId, socketFd, key));
  clients.insert(std::make_pair(clientId, scc));
  return clientId;
}

bool ServerConnection::removeClient(
    shared_ptr<ServerClientConnection> connection) {
  connection->shutdown();
  return clients.erase(connection->getClientId()) == 1;
}
}
<commit_msg>Fix bug where we checked version on reconnect.<commit_after>#include "ServerConnection.hpp"
namespace et {
ServerConnection::ServerConnection(
    std::shared_ptr<SocketHandler> _socketHandler, int _port,
    shared_ptr<ServerConnectionHandler> _serverHandler, const string& _key)
    : socketHandler(_socketHandler),
      port(_port),
      serverHandler(_serverHandler),
      stop(false),
      key(_key) {}

ServerConnection::~ServerConnection() {}

void ServerConnection::run() {
  while (!stop) {
    VLOG_EVERY_N(2, 30) << "Listening for connection" << endl;
    int clientSocketFd = socketHandler->listen(port);
    if (clientSocketFd < 0) {
      sleep(1);
      continue;
    }
    VLOG(1) << "SERVER: got client socket fd: " << clientSocketFd << endl;
    clientHandler(clientSocketFd);
  }
}

void ServerConnection::close() {
  stop = true;
  socketHandler->stopListening();
  for (const auto& it : clients) {
    it.second->closeSocket();
  }
  clients.clear();
}

void ServerConnection::clientHandler(int clientSocketFd) {
  int clientId;
  try {
    et::ConnectRequest request =
        socketHandler->readProto<et::ConnectRequest>(clientSocketFd, true);
    clientId = request.clientid();
    if (clientId == -1) {
      int version = request.version();
      if (version != PROTOCOL_VERSION) {
        et::ConnectResponse response;

        std::ostringstream errorStream;
        errorStream << "Mismatched protocol versions.  Client: " << request.version() << " != Server: " << PROTOCOL_VERSION;
        response.set_error(errorStream.str());
        socketHandler->writeProto(clientSocketFd, response, true);
        socketHandler->close(clientSocketFd);
        return;
      }
      clientId = newClient(clientSocketFd);
      shared_ptr<ServerClientConnection> serverClientState =
          getClient(clientId);
      if (serverHandler && !serverHandler->newClient(serverClientState)) {
        // Destroy the new client
        removeClient(serverClientState);
        socketHandler->close(clientSocketFd);
      }
    } else {
      if (!clientExists(clientId)) {
        throw std::runtime_error("Tried to revive an unknown client");
      }
      shared_ptr<ServerClientConnection> serverClientState =
          getClient(clientId);
      serverClientState->recoverClient(clientSocketFd);
    }
  } catch (const runtime_error& err) {
    // Comm failed, close the connection
    LOG(ERROR) << "Error handling new client: " << err.what();
    socketHandler->close(clientSocketFd);
  }
}

int ServerConnection::newClient(int socketFd) {
  int clientId = rand();
  while (clientExists(clientId)) {
    clientId++;
    if (clientId < 0) {
      throw std::runtime_error("Ran out of client ids");
    }
  }
  VLOG(1) << "Created client with id " << clientId << endl;

  et::ConnectResponse response;
  response.set_clientid(clientId);
  socketHandler->writeProto(socketFd, response, true);
  shared_ptr<ServerClientConnection> scc(
      new ServerClientConnection(socketHandler, clientId, socketFd, key));
  clients.insert(std::make_pair(clientId, scc));
  return clientId;
}

bool ServerConnection::removeClient(
    shared_ptr<ServerClientConnection> connection) {
  connection->shutdown();
  return clients.erase(connection->getClientId()) == 1;
}
}
<|endoftext|>


<commit_before>#include <thread>
#include <future>
#include <ncurses.h>

#include "../../../src/show_message.hh"
#include "../../../src/split.hh"
#include "../../vick-shell-command/src/shell_command.hh"
#include "../../../src/file_contents.hh"
#include "../../../src/prompt.hh"
#include "../../../src/mode.hh"
#include "compile.hh"

namespace vick {
namespace compile {

static std::string last_cmd;

static int compile(std::string last_cmd, contents& cont) {
    // contents cont(&read_only_mode);
    try {
        shell_command::exec_shell_command(last_cmd + " ; printf "
                                                     "'\n%s\n' "
                                                     "\"$?\"",
                                          // Space required here:
                                          // ~~~~~~~~~~~~~~~^ so that
                                          // ``;;`` won't
                                          // occur by accident
                                          cont);
    } catch (const std::exception&) {
    }
    int ret = std::stoi(cont.cont.back());
    cont.cont.pop_back();
    if (cont.cont.back().size() == 0)
        cont.cont.pop_back();
    return ret;
}

boost::optional<std::shared_ptr<change> >
compile_project(contents& cont, boost::optional<int> force_prompt) {
    if (force_prompt or last_cmd.empty()) {
        attron(COLOR_PAIR(1));
        auto temp = prompt("Compile command: ");
        attroff(COLOR_PAIR(1));
        if (temp)
            last_cmd = *temp;
        else
            return boost::none;
    }

    std::packaged_task<int(std::string, contents&)> tsk(compile);
    auto future = tsk.get_future();

    std::thread thread(std::move(tsk), last_cmd, std::ref(cont));
    thread.join();
    //     ^^^^ TODO: FIXME.  Makes a thread then immediately joins.

    int res = future.get();
    if (res != 0)
        show_message("ERROR! " + std::to_string(res));

    return boost::none;
}
}
}
<commit_msg>Change `size() == 0` into `empty()`<commit_after>#include <thread>
#include <future>
#include <ncurses.h>

#include "../../../src/show_message.hh"
#include "../../../src/split.hh"
#include "../../vick-shell-command/src/shell_command.hh"
#include "../../../src/file_contents.hh"
#include "../../../src/prompt.hh"
#include "../../../src/mode.hh"
#include "compile.hh"

namespace vick {
namespace compile {

static std::string last_cmd;

static int compile(std::string last_cmd, contents& cont) {
    // contents cont(&read_only_mode);
    try {
        shell_command::exec_shell_command(last_cmd + " ; printf "
                                                     "'\n%s\n' "
                                                     "\"$?\"",
                                          // Space required here:
                                          // ~~~~~~~~~~~~~~~^ so that
                                          // ``;;`` won't
                                          // occur by accident
                                          cont);
    } catch (const std::exception&) {
    }
    int ret = std::stoi(cont.cont.back());
    cont.cont.pop_back();
    if (cont.cont.back().empty())
        cont.cont.pop_back();
    return ret;
}

boost::optional<std::shared_ptr<change> >
compile_project(contents& cont, boost::optional<int> force_prompt) {
    if (force_prompt or last_cmd.empty()) {
        attron(COLOR_PAIR(1));
        auto temp = prompt("Compile command: ");
        attroff(COLOR_PAIR(1));
        if (temp)
            last_cmd = *temp;
        else
            return boost::none;
    }

    std::packaged_task<int(std::string, contents&)> tsk(compile);
    auto future = tsk.get_future();

    std::thread thread(std::move(tsk), last_cmd, std::ref(cont));
    thread.join();
    //     ^^^^ TODO: FIXME.  Makes a thread then immediately joins.

    int res = future.get();
    if (res != 0)
        show_message("ERROR! " + std::to_string(res));

    return boost::none;
}
}
}
<|endoftext|>


<commit_before>/*************************************************************************
 *                                                                       *
 * Open Dynamics Engine, Copyright (C) 2001 Russell L. Smith.            *
 *                                                                       *
 * This library is free software; you can redistribute it and/or         *
 * modify it under the terms of the GNU Lesser General Public            *
 * License as published by the Free Software Foundation; either          *
 * version 2.1 of the License, or (at your option) any later version.    *
 *                                                                       *
 * This library is distributed in the hope that it will be useful,       *
 * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU      *
 * Lesser General Public License for more details.                       *
 *                                                                       *
 * You should have received a copy of the GNU Lesser General Public      *
 * License along with this library (see the file LICENSE.TXT); if not,   *
 * write to the Free Software Foundation, Inc., 59 Temple Place,         *
 * Suite 330, Boston, MA 02111-1307 USA.                                 *
 *                                                                       *
 *************************************************************************/

#include <stdio.h>
#include "ode/ode.h"
#include "drawstuff/drawstuff.h"

// select correct drawing functions

#ifdef dDOUBLE
#define dsDrawBox dsDrawBoxD
#define dsDrawSphere dsDrawSphereD
#define dsDrawCylinder dsDrawCylinderD
#define dsDrawCappedCylinder dsDrawCappedCylinderD
#endif

// some constants

#define LENGTH 0.7	// chassis length
#define WIDTH 0.5	// chassis width
#define HEIGHT 0.2	// chassis height
#define RADIUS 0.18	// wheel radius
#define STARTZ 0.5	// starting height of chassis
#define CMASS 1		// chassis mass
#define WMASS 0.2	// wheel mass

// dynamics and collision objects (chassis, 3 wheels, environment)

static dWorldID world;
static dSpaceID space;
static dBodyID body[4];
static dJointID joint[3];	// joint[0] is the front wheel
static dJointID dmotor,smotor;	// front wheel drive & steering motors
static dJointGroupID contactgroup;
static dGeomID ground;
static dGeomID box[1];
static dGeomID sphere[3];
static dGeomID ground_box;

// things that the user controls

static dReal speed=0,steer=0;	// user commands

// this is called by dSpaceCollide when two objects in space are
// potentially colliding.

static void nearCallback (void *data, dGeomID o1, dGeomID o2)
{
  // only collide things with the ground
  int g1 = (o1 == ground || o1 == ground_box);
  int g2 = (o2 == ground || o2 == ground_box);
  if (!(g1 ^ g2)) return;

  dContact contact;
  contact.surface.mode = 0;
  contact.surface.mu = dInfinity;
  if (dCollide (o1,o2,0,&contact.geom,sizeof(dContactGeom))) {
    //    if (o1==ground_box) printf ("foo 1\n");
    //    if (o2==ground_box) printf ("foo 2\n");

    dJointID c = dJointCreateContact (world,contactgroup,&contact);
    dJointAttach (c,dGeomGetBody(o1),dGeomGetBody(o2));
  }
}

// start simulation - set viewpoint

static void start()
{
  static float xyz[3] = {0.8317,-0.9817,0.8000};
  static float hpr[3] = {121.0000,-27.5000,0.0000};
  dsSetViewpoint (xyz,hpr);
}

// called when a key pressed

static void command (int cmd)
{
  switch (cmd) {
  case 'a': case 'A':
    speed += 0.3;
    break;
  case 'z': case 'Z':
    speed -= 0.3;
    break;
  case ',':
    steer -= 0.2;
    break;
  case '.':
    steer += 0.2;
    break;
  case ' ':
    speed = 0;
    steer = 0;
    break;
  }
}

// simulation loop

static void simLoop (int pause)
{
  int i;
  if (!pause) {
    //dJointSetRMotorVel (dmotor,speed);
    //dJointSetRMotorTmax (dmotor,0.1);
    dJointSetHingeVel (joint[2],speed);
    dJointSetHingeTmax (joint[2],0.1);

    dJointSetRMotorVel (smotor,steer);
    dJointSetRMotorTmax (smotor,0.1);

    dSpaceCollide (space,0,&nearCallback);
    dWorldStep (world,0.05);

    // remove all contact joints
    dJointGroupEmpty (contactgroup);
  }

  dsSetColor (0,1,1);
  dsSetTexture (DS_WOOD);
  dReal sides[3] = {LENGTH,WIDTH,HEIGHT};
  dsDrawBox (dBodyGetPosition(body[0]),dBodyGetRotation(body[0]),sides);
  dsSetColor (1,1,1);
  for (i=1; i<=3; i++) dsDrawCylinder (dBodyGetPosition(body[i]),
				       dBodyGetRotation(body[i]),0.02,RADIUS);

  /*
  dVector3 ss;
  dGeomBoxGetLengths (ground_box,ss);
  dsDrawBox (dGeomGetPosition(ground_box),dGeomGetRotation(ground_box),ss);
  */

  printf ("%.10f %.10f %.10f %.10f\n",
	  dJointGetHingeAngle (joint[1]),
	  dJointGetHingeAngle (joint[2]),
	  dJointGetHingeAngleRate (joint[1]),
	  dJointGetHingeAngleRate (joint[2]));
}

int main (int argc, char **argv)
{
  int i;
  dMass m;

  // setup pointers to drawstuff callback functions
  dsFunctions fn;
  fn.version = DS_VERSION;
  fn.start = &start;
  fn.step = &simLoop;
  fn.command = &command;
  fn.stop = 0;
  fn.path_to_textures = "../../drawstuff/textures";

  // create world

  world = dWorldCreate();
  space = dSpaceCreate();
  contactgroup = dJointGroupCreate (1000000);
  dWorldSetGravity (world,0,0,-0.5);
  ground = dCreatePlane (space,0,0,1,0);

  // chassis body
  body[0] = dBodyCreate (world);
  dBodySetPosition (body[0],0,0,STARTZ);
  dMassSetBox (&m,1,LENGTH,WIDTH,HEIGHT);
  dMassAdjust (&m,CMASS);
  dBodySetMass (body[0],&m);
  box[0] = dCreateBox (space,LENGTH,WIDTH,HEIGHT);
  dGeomSetBody (box[0],body[0]);

  // wheel bodies
  for (i=1; i<=3; i++) {
    body[i] = dBodyCreate (world);
    dQuaternion q;
    dQFromAxisAndAngle (q,1,0,0,M_PI*0.5);
    dBodySetQuaternion (body[i],q);
    dMassSetSphere (&m,1,RADIUS);
    dMassAdjust (&m,WMASS);
    dBodySetMass (body[i],&m);
    sphere[i-1] = dCreateSphere (space,RADIUS);
    dGeomSetBody (sphere[i-1],body[i]);
  }
  dBodySetPosition (body[1],0.5*LENGTH,0,STARTZ-HEIGHT*0.5);
  dBodySetPosition (body[2],-0.5*LENGTH, WIDTH*0.5,STARTZ-HEIGHT*0.5);
  dBodySetPosition (body[3],-0.5*LENGTH,-WIDTH*0.5,STARTZ-HEIGHT*0.5);

  // front wheel hinge
  joint[0] = dJointCreateHinge2 (world,0);
  dJointAttach (joint[0],body[0],body[1]);
  const dReal *a = dBodyGetPosition (body[1]);
  dJointSetHinge2Anchor (joint[0],a[0],a[1],a[2]);
  dJointSetHinge2Axis1 (joint[0],0,0,1);
  dJointSetHinge2Axis2 (joint[0],0,1,0);

  // back wheel hinges
  for (i=1; i<3; i++) {
    joint[i] = dJointCreateHinge (world,0);
    dJointAttach (joint[i],body[0],body[i+1]);
    const dReal *a = dBodyGetPosition (body[i+1]);
    dJointSetHingeAnchor (joint[i],a[0],a[1],a[2]);
    dJointSetHingeAxis (joint[i],0,1,0);
  }

  // front wheel motors
  //dmotor = dJointCreateRMotor (world,0);
  //dJointAttach (dmotor,body[1],body[0]);
  //dJointSetRMotorAxis (dmotor,0,1,0);		// motor axis rel to 1st body
  smotor = dJointCreateRMotor (world,0);
  dJointAttach (smotor,body[0],body[1]);
  dJointSetRMotorAxis (smotor,0,0,1);		// motor axis rel to 1st body

  // environment
  /*
  ground_box = dCreateBox (space,2,1.5,1);
  dMatrix3 R;
  dRFromAxisAndAngle (R,0,1,0,-0.15);
  dGeomSetPosition (ground_box,2,0,-0.34);
  dGeomSetRotation (ground_box,R);
  */

  // run simulation
  dsSimulationLoop (argc,argv,352,288,&fn);

  dJointGroupDestroy (contactgroup);
  dSpaceDestroy (space);
  dWorldDestroy (world);

  return 0;
}
<commit_msg>hmmmm.<commit_after>/*************************************************************************
 *                                                                       *
 * Open Dynamics Engine, Copyright (C) 2001 Russell L. Smith.            *
 *                                                                       *
 * This library is free software; you can redistribute it and/or         *
 * modify it under the terms of the GNU Lesser General Public            *
 * License as published by the Free Software Foundation; either          *
 * version 2.1 of the License, or (at your option) any later version.    *
 *                                                                       *
 * This library is distributed in the hope that it will be useful,       *
 * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU      *
 * Lesser General Public License for more details.                       *
 *                                                                       *
 * You should have received a copy of the GNU Lesser General Public      *
 * License along with this library (see the file LICENSE.TXT); if not,   *
 * write to the Free Software Foundation, Inc., 59 Temple Place,         *
 * Suite 330, Boston, MA 02111-1307 USA.                                 *
 *                                                                       *
 *************************************************************************/

#include <stdio.h>
#include "ode/ode.h"
#include "drawstuff/drawstuff.h"

// select correct drawing functions

#ifdef dDOUBLE
#define dsDrawBox dsDrawBoxD
#define dsDrawSphere dsDrawSphereD
#define dsDrawCylinder dsDrawCylinderD
#define dsDrawCappedCylinder dsDrawCappedCylinderD
#endif

// some constants

#define LENGTH 0.7	// chassis length
#define WIDTH 0.5	// chassis width
#define HEIGHT 0.2	// chassis height
#define RADIUS 0.18	// wheel radius
#define STARTZ 0.5	// starting height of chassis
#define CMASS 1		// chassis mass
#define WMASS 0.2	// wheel mass

// dynamics and collision objects (chassis, 3 wheels, environment)

static dWorldID world;
static dSpaceID space;
static dBodyID body[4];
static dJointID joint[3];	// joint[0] is the front wheel
static dJointGroupID contactgroup;
static dGeomID ground;
static dGeomID box[1];
static dGeomID sphere[3];
static dGeomID ground_box;

// things that the user controls

static dReal speed=0,steer=0;	// user commands

// this is called by dSpaceCollide when two objects in space are
// potentially colliding.

static void nearCallback (void *data, dGeomID o1, dGeomID o2)
{
  // only collide things with the ground
  int g1 = (o1 == ground || o1 == ground_box);
  int g2 = (o2 == ground || o2 == ground_box);
  if (!(g1 ^ g2)) return;

  dContact contact;
  contact.surface.mode = 0;
  contact.surface.mu = dInfinity;
  if (dCollide (o1,o2,0,&contact.geom,sizeof(dContactGeom))) {
    //    if (o1==ground_box) printf ("foo 1\n");
    //    if (o2==ground_box) printf ("foo 2\n");

    dJointID c = dJointCreateContact (world,contactgroup,&contact);
    dJointAttach (c,dGeomGetBody(o1),dGeomGetBody(o2));
  }
}

// start simulation - set viewpoint

static void start()
{
  static float xyz[3] = {0.8317,-0.9817,0.8000};
  static float hpr[3] = {121.0000,-27.5000,0.0000};
  dsSetViewpoint (xyz,hpr);
}

// called when a key pressed

static void command (int cmd)
{
  switch (cmd) {
  case 'a': case 'A':
    speed += 0.3;
    break;
  case 'z': case 'Z':
    speed -= 0.3;
    break;
  case ',':
    steer += 0.5;
    break;
  case '.':
    steer -= 0.5;
    break;
  case ' ':
    speed = 0;
    steer = 0;
    break;
  }
}

// simulation loop

static void simLoop (int pause)
{
  int i;
  if (!pause) {
    // motor
    dJointSetHingeParam (joint[2],dParamVel,speed);
    dJointSetHingeParam (joint[2],dParamFMax,0.1);

    // steering
    printf ("%.4f\n",dJointGetHinge2Angle1 (joint[0]));
    dReal v = steer - dJointGetHinge2Angle1 (joint[0]);
    if (v > 0.1) v = 0.1;
    if (v < -0.1) v = -0.1;
    v *= 10.0;
    dJointSetHinge2Param1 (joint[0],dParamVel,v);
    dJointSetHinge2Param1 (joint[0],dParamFMax,0.2);
    dJointSetHinge2Param1 (joint[0],dParamLoStop,-0.75);
    dJointSetHinge2Param1 (joint[0],dParamHiStop,0.75);
    dJointSetHinge2Param1 (joint[0],dParamFudgeFactor,0.1);

    dSpaceCollide (space,0,&nearCallback);
    dWorldStep (world,0.05);

    // remove all contact joints
    dJointGroupEmpty (contactgroup);
  }

  dsSetColor (0,1,1);
  dsSetTexture (DS_WOOD);
  dReal sides[3] = {LENGTH,WIDTH,HEIGHT};
  dsDrawBox (dBodyGetPosition(body[0]),dBodyGetRotation(body[0]),sides);
  dsSetColor (1,1,1);
  for (i=1; i<=3; i++) dsDrawCylinder (dBodyGetPosition(body[i]),
				       dBodyGetRotation(body[i]),0.02,RADIUS);

  /*
  dVector3 ss;
  dGeomBoxGetLengths (ground_box,ss);
  dsDrawBox (dGeomGetPosition(ground_box),dGeomGetRotation(ground_box),ss);
  */

  /*
  printf ("%.10f %.10f %.10f %.10f\n",
	  dJointGetHingeAngle (joint[1]),
	  dJointGetHingeAngle (joint[2]),
	  dJointGetHingeAngleRate (joint[1]),
	  dJointGetHingeAngleRate (joint[2]));
  */
}

int main (int argc, char **argv)
{
  int i;
  dMass m;

  // setup pointers to drawstuff callback functions
  dsFunctions fn;
  fn.version = DS_VERSION;
  fn.start = &start;
  fn.step = &simLoop;
  fn.command = &command;
  fn.stop = 0;
  fn.path_to_textures = "../../drawstuff/textures";

  // create world

  world = dWorldCreate();
  space = dSpaceCreate();
  contactgroup = dJointGroupCreate (1000000);
  dWorldSetGravity (world,0,0,-0.5);
  ground = dCreatePlane (space,0,0,1,0);

  // chassis body
  body[0] = dBodyCreate (world);
  dBodySetPosition (body[0],0,0,STARTZ);
  dMassSetBox (&m,1,LENGTH,WIDTH,HEIGHT);
  dMassAdjust (&m,CMASS);
  dBodySetMass (body[0],&m);
  box[0] = dCreateBox (space,LENGTH,WIDTH,HEIGHT);
  dGeomSetBody (box[0],body[0]);

  // wheel bodies
  for (i=1; i<=3; i++) {
    body[i] = dBodyCreate (world);
    dQuaternion q;
    dQFromAxisAndAngle (q,1,0,0,M_PI*0.5);
    dBodySetQuaternion (body[i],q);
    dMassSetSphere (&m,1,RADIUS);
    dMassAdjust (&m,WMASS);
    dBodySetMass (body[i],&m);
    sphere[i-1] = dCreateSphere (space,RADIUS);
    dGeomSetBody (sphere[i-1],body[i]);
  }
  dBodySetPosition (body[1],0.5*LENGTH,0,STARTZ-HEIGHT*0.5);
  dBodySetPosition (body[2],-0.5*LENGTH, WIDTH*0.5,STARTZ-HEIGHT*0.5);
  dBodySetPosition (body[3],-0.5*LENGTH,-WIDTH*0.5,STARTZ-HEIGHT*0.5);

  // front wheel hinge
  joint[0] = dJointCreateHinge2 (world,0);
  dJointAttach (joint[0],body[0],body[1]);
  const dReal *a = dBodyGetPosition (body[1]);
  dJointSetHinge2Anchor (joint[0],a[0],a[1],a[2]);
  dJointSetHinge2Axis1 (joint[0],0,0,1);
  dJointSetHinge2Axis2 (joint[0],0,1,0);

  // back wheel hinges
  for (i=1; i<3; i++) {
    joint[i] = dJointCreateHinge (world,0);
    dJointAttach (joint[i],body[0],body[i+1]);
    const dReal *a = dBodyGetPosition (body[i+1]);
    dJointSetHingeAnchor (joint[i],a[0],a[1],a[2]);
    dJointSetHingeAxis (joint[i],0,1,0);
  }

  // environment
  /*
  ground_box = dCreateBox (space,2,1.5,1);
  dMatrix3 R;
  dRFromAxisAndAngle (R,0,1,0,-0.15);
  dGeomSetPosition (ground_box,2,0,-0.34);
  dGeomSetRotation (ground_box,R);
  */

  // run simulation
  dsSimulationLoop (argc,argv,352,288,&fn);

  dJointGroupDestroy (contactgroup);
  dSpaceDestroy (space);
  dWorldDestroy (world);

  return 0;
}
<|endoftext|>