<commit_before>#pragma once
#include <v8.h>
#include <uv.h>
#include <node.h>

#include <functional>
#include <memory>
//#include <iostream>

#include "file.h"
#include "group.h"
#include "H5DSpublic.h"

namespace NodeHDF5 {

    class H5ds {
    public:
static void Initialize (Handle<Object> target) {

        // append this function to the target object
        target->Set(String::NewFromUtf8(v8::Isolate::GetCurrent(), "setScale"), FunctionTemplate::New(v8::Isolate::GetCurrent(), H5ds::set_scale)->GetFunction());
        target->Set(String::NewFromUtf8(v8::Isolate::GetCurrent(), "attachScale"), FunctionTemplate::New(v8::Isolate::GetCurrent(), H5ds::attach_scale)->GetFunction());
        target->Set(String::NewFromUtf8(v8::Isolate::GetCurrent(), "detachScale"), FunctionTemplate::New(v8::Isolate::GetCurrent(), H5ds::detach_scale)->GetFunction());
        target->Set(String::NewFromUtf8(v8::Isolate::GetCurrent(), "isAttached"), FunctionTemplate::New(v8::Isolate::GetCurrent(), H5ds::is_attached)->GetFunction());
        target->Set(String::NewFromUtf8(v8::Isolate::GetCurrent(), "isScale"), FunctionTemplate::New(v8::Isolate::GetCurrent(), H5ds::is_scale)->GetFunction());
        target->Set(String::NewFromUtf8(v8::Isolate::GetCurrent(), "iterateScale"), FunctionTemplate::New(v8::Isolate::GetCurrent(), H5ds::iterate_scales)->GetFunction());
        target->Set(String::NewFromUtf8(v8::Isolate::GetCurrent(), "setLabel"), FunctionTemplate::New(v8::Isolate::GetCurrent(), H5ds::set_label)->GetFunction());
        target->Set(String::NewFromUtf8(v8::Isolate::GetCurrent(), "getLabel"), FunctionTemplate::New(v8::Isolate::GetCurrent(), H5ds::get_label)->GetFunction());
        target->Set(String::NewFromUtf8(v8::Isolate::GetCurrent(), "getScaleName"), FunctionTemplate::New(v8::Isolate::GetCurrent(), H5ds::get_scale_name)->GetFunction());
        target->Set(String::NewFromUtf8(v8::Isolate::GetCurrent(), "getNumberOfScales"), FunctionTemplate::New(v8::Isolate::GetCurrent(), H5ds::get_num_scales)->GetFunction());

    }

static void set_scale (const v8::FunctionCallbackInfo<Value>& args)
{
    // fail out if arguments are not correct
    if (args.Length() != 3 || !args[0]->IsUint32() || !args[1]->IsString() || !args[2]->IsString()) {

        v8::Isolate::GetCurrent()->ThrowException(v8::Exception::SyntaxError(String::NewFromUtf8(v8::Isolate::GetCurrent(), "expected group id, dataset name, name")));
        args.GetReturnValue().SetUndefined();
        return;

    }

    String::Utf8Value dset_name (args[1]->ToString());
    String::Utf8Value dim_scale_name (args[2]->ToString());
    hid_t did=H5Dopen(args[0]->ToInt32()->Value(), *dset_name, H5P_DEFAULT);
    herr_t err=H5DSset_scale(did, *dim_scale_name);
    if(err<0){
        H5Dclose(did);
        v8::Isolate::GetCurrent()->ThrowException(v8::Exception::SyntaxError(String::NewFromUtf8(v8::Isolate::GetCurrent(), "failed setting dimension scale")));
        args.GetReturnValue().SetUndefined();
        return;

    }
    H5Dclose(did);
    args.GetReturnValue().SetUndefined();
}

static void attach_scale (const v8::FunctionCallbackInfo<Value>& args)
{
    // fail out if arguments are not correct
    if (args.Length() != 4 || !args[0]->IsInt32() || !args[1]->IsString() || !args[2]->IsString() || !args[3]->IsInt32()) {

        v8::Isolate::GetCurrent()->ThrowException(v8::Exception::SyntaxError(String::NewFromUtf8(v8::Isolate::GetCurrent(), "expected group id, dataset name, name, index")));
        args.GetReturnValue().SetUndefined();
        return;

    }

    String::Utf8Value dset_name (args[1]->ToString());
    String::Utf8Value dim_scale_name (args[2]->ToString());
    hid_t did=H5Dopen(args[0]->ToInt32()->Value(), *dset_name, H5P_DEFAULT);
    hid_t dsid=H5Dopen(args[0]->ToInt32()->Value(), *dim_scale_name, H5P_DEFAULT);
    herr_t err=H5DSattach_scale(did, dsid, args[3]->ToInt32()->Value());
    if(err<0){
        H5Dclose(dsid);
        H5Dclose(did);
        v8::Isolate::GetCurrent()->ThrowException(v8::Exception::SyntaxError(String::NewFromUtf8(v8::Isolate::GetCurrent(), "failed attaching dimension scale")));
        args.GetReturnValue().SetUndefined();
        return;

    }
    H5Dclose(dsid);
    H5Dclose(did);
    args.GetReturnValue().SetUndefined();
}

static void detach_scale (const v8::FunctionCallbackInfo<Value>& args)
{
    // fail out if arguments are not correct
    if (args.Length() != 4 || !args[0]->IsInt32() || !args[1]->IsString() || !args[2]->IsString() || !args[3]->IsInt32()) {

        v8::Isolate::GetCurrent()->ThrowException(v8::Exception::SyntaxError(String::NewFromUtf8(v8::Isolate::GetCurrent(), "expected group id, dataset name, name, index")));
        args.GetReturnValue().SetUndefined();
        return;

    }

    String::Utf8Value dset_name (args[1]->ToString());
    String::Utf8Value dim_scale_name (args[2]->ToString());
    hid_t did=H5Dopen(args[0]->ToInt32()->Value(), *dset_name, H5P_DEFAULT);
    hid_t dsid=H5Dopen(args[0]->ToInt32()->Value(), *dim_scale_name, H5P_DEFAULT);
    herr_t err=H5DSdetach_scale(did, dsid, args[3]->ToInt32()->Value());
    if(err<0){
        H5Dclose(dsid);
        H5Dclose(did);
        v8::Isolate::GetCurrent()->ThrowException(v8::Exception::SyntaxError(String::NewFromUtf8(v8::Isolate::GetCurrent(), "failed attaching dimension scale")));
        args.GetReturnValue().SetUndefined();
        return;

    }
    H5Dclose(dsid);
    H5Dclose(did);
    args.GetReturnValue().SetUndefined();
}

static void is_attached (const v8::FunctionCallbackInfo<Value>& args)
{
    // fail out if arguments are not correct
    if (args.Length() != 4 || !args[0]->IsInt32() || !args[1]->IsString() || !args[2]->IsString() || !args[3]->IsInt32()) {

        v8::Isolate::GetCurrent()->ThrowException(v8::Exception::SyntaxError(String::NewFromUtf8(v8::Isolate::GetCurrent(), "expected group id, dataset name, name, index")));
        args.GetReturnValue().SetUndefined();
        return;

    }

    String::Utf8Value dset_name (args[1]->ToString());
    String::Utf8Value dim_scale_name (args[2]->ToString());
    hid_t did=H5Dopen(args[0]->ToInt32()->Value(), *dset_name, H5P_DEFAULT);
    hid_t dsid=H5Dopen(args[0]->ToInt32()->Value(), *dim_scale_name, H5P_DEFAULT);
    htri_t status=H5DSis_attached(did, dsid, args[3]->ToInt32()->Value());
    args.GetReturnValue().Set((status) ? true : false);
    H5Dclose(dsid);
    H5Dclose(did);
}

static void is_scale (const v8::FunctionCallbackInfo<Value>& args)
{
    // fail out if arguments are not correct
    if (args.Length() != 2 || !args[0]->IsInt32() || !args[1]->IsString()) {

        v8::Isolate::GetCurrent()->ThrowException(v8::Exception::SyntaxError(String::NewFromUtf8(v8::Isolate::GetCurrent(), "expected group id, dataset name")));
        args.GetReturnValue().SetUndefined();
        return;

    }

    String::Utf8Value dset_name (args[1]->ToString());
    hid_t did=H5Dopen(args[0]->ToInt32()->Value(), *dset_name, H5P_DEFAULT);
    htri_t status=H5DSis_scale(did);
    args.GetReturnValue().Set((status) ? true : false);
    H5Dclose(did);
}

static void iterate_scales (const v8::FunctionCallbackInfo<Value>& args)
{

    String::Utf8Value dset_name (args[1]->ToString());
    int rank;
    H5LTget_dataset_ndims (args[0]->ToInt32()->Value(), *dset_name, &rank);
    hid_t did=H5Dopen(args[0]->ToInt32()->Value(), *dset_name, H5P_DEFAULT);
    int idx=args[2]->ToInt32()->Value();
        v8::Persistent<v8::Function> callback;
        const unsigned argc = 2;
        callback.Reset(v8::Isolate::GetCurrent(), args[3].As<Function>());
        std::function<herr_t(hid_t did, unsigned int dim, hid_t dsid, void *visitor_data)> f=[&](hid_t did, unsigned int dim, hid_t dsid, void *visitor_data){
        v8::Local<v8::Value> argv[2] = { v8::Int32::New(v8::Isolate::GetCurrent(), dim),v8:: String::NewFromUtf8(v8::Isolate::GetCurrent(), "success") };
        v8::Local<v8::Function>::New(v8::Isolate::GetCurrent(), callback)->Call(v8::Isolate::GetCurrent()->GetCurrentContext()->Global(), argc, argv);
            return (herr_t)0;
        };
        v8::Local<v8::Function> func=v8::Local<v8::Function>::New(v8::Isolate::GetCurrent(), callback);
    herr_t err=H5DSiterate_scales( did, (unsigned int)rank, &idx, [](hid_t did, unsigned int dim, hid_t dsid, void *visitor_data) -> herr_t {
        v8::Local<v8::Value> argv[2] = { v8::Int32::New(v8::Isolate::GetCurrent(), dim),v8:: String::NewFromUtf8(v8::Isolate::GetCurrent(), "success") };
        ((v8::Local<v8::Function>*)visitor_data)[0]->Call(v8::Isolate::GetCurrent()->GetCurrentContext()->Global(), argc, argv);
        return (herr_t)0;
    }, &func);
    if(err<0){
        H5Dclose(did);
        v8::Isolate::GetCurrent()->ThrowException(v8::Exception::SyntaxError(String::NewFromUtf8(v8::Isolate::GetCurrent(), "failed iterating through  scale indices")));
        args.GetReturnValue().SetUndefined();
        return;

    }
//        callback.Reset();
    H5Dclose(did);
        args.GetReturnValue().SetUndefined();
}

static void set_label (const v8::FunctionCallbackInfo<Value>& args)
{
    // fail out if arguments are not correct
    if (args.Length() != 4 || !args[0]->IsInt32() || !args[1]->IsString() || !args[2]->IsInt32() || !args[3]->IsString()) {

        v8::Isolate::GetCurrent()->ThrowException(v8::Exception::SyntaxError(String::NewFromUtf8(v8::Isolate::GetCurrent(), "expected group id, scale name, index, label")));
        args.GetReturnValue().SetUndefined();
        return;

    }

    String::Utf8Value dset_name (args[1]->ToString());
    hid_t did=H5Dopen(args[0]->ToInt32()->Value(), *dset_name, H5P_DEFAULT);
    std::string label(*String::Utf8Value(args[3]->ToString()));
    /*herr_t err=*/H5DSset_label(did, args[2]->ToInt32()->Value(), (char*)label.c_str());
    H5Dclose(did);
    args.GetReturnValue().SetUndefined();
}

static void get_label (const v8::FunctionCallbackInfo<Value>& args)
{

    // fail out if arguments are not correct
    if (args.Length() != 3 || !args[0]->IsInt32() || !args[1]->IsString() || !args[2]->IsInt32()) {

        v8::Isolate::GetCurrent()->ThrowException(v8::Exception::SyntaxError(String::NewFromUtf8(v8::Isolate::GetCurrent(), "expected group id, scale name, index")));
        args.GetReturnValue().SetUndefined();
        return;

    }

    String::Utf8Value dset_name (args[1]->ToString());
    hid_t did=H5Dopen(args[0]->ToInt32()->Value(), *dset_name, H5P_DEFAULT);
    size_t size=0;
    size=H5DSget_label(did, args[2]->ToInt32()->Value(), NULL, size);
    std::string name(size+1, '\0');
    size=H5DSget_label(did, args[2]->ToInt32()->Value(), (char*)name.c_str(), size+1);
    args.GetReturnValue().Set(v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), name.c_str()));
    H5Dclose(did);
}

static void get_scale_name (const v8::FunctionCallbackInfo<Value>& args)
{
    // fail out if arguments are not correct
    if (args.Length() != 2 || !args[0]->IsInt32() || !args[1]->IsString()) {

        v8::Isolate::GetCurrent()->ThrowException(v8::Exception::SyntaxError(String::NewFromUtf8(v8::Isolate::GetCurrent(), "expected group id, scale name")));
        args.GetReturnValue().SetUndefined();
        return;

    }

    String::Utf8Value dset_name (args[1]->ToString());
    hid_t did=H5Dopen(args[0]->ToInt32()->Value(), *dset_name, H5P_DEFAULT);
    size_t size=0;
    size=H5DSget_scale_name(did, NULL, size);
    std::string name(size+1, '\0');
    size=H5DSget_scale_name(did, (char*)name.c_str(), size+1);
    args.GetReturnValue().Set(v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), name.c_str()));
    H5Dclose(did);
}

static void get_num_scales (const v8::FunctionCallbackInfo<Value>& args)
{

    // fail out if arguments are not correct
    if (args.Length() != 3 || !args[0]->IsInt32() || !args[1]->IsString() || !args[2]->IsInt32()) {

        v8::Isolate::GetCurrent()->ThrowException(v8::Exception::SyntaxError(String::NewFromUtf8(v8::Isolate::GetCurrent(), "expected group id, dataset name, index")));
        args.GetReturnValue().SetUndefined();
        return;

    }

    String::Utf8Value dset_name (args[1]->ToString());
    hid_t did=H5Dopen(args[0]->ToInt32()->Value(), *dset_name, H5P_DEFAULT);
    int num=H5DSget_num_scales(did, args[2]->ToInt32()->Value());
    args.GetReturnValue().Set(v8::Uint32::New(v8::Isolate::GetCurrent(), num));
    H5Dclose(did);
}

    };
}<commit_msg>fixed build error on windows with VS2013.  This should not effect clang and gcc builds<commit_after>#pragma once
#include <v8.h>
#include <uv.h>
#include <node.h>

#include <functional>
#include <memory>
//#include <iostream>

#include "file.h"
#include "group.h"
#include "H5DSpublic.h"

namespace NodeHDF5 {

    class H5ds {
    public:
static void Initialize (Handle<Object> target) {

        // append this function to the target object
        target->Set(String::NewFromUtf8(v8::Isolate::GetCurrent(), "setScale"), FunctionTemplate::New(v8::Isolate::GetCurrent(), H5ds::set_scale)->GetFunction());
        target->Set(String::NewFromUtf8(v8::Isolate::GetCurrent(), "attachScale"), FunctionTemplate::New(v8::Isolate::GetCurrent(), H5ds::attach_scale)->GetFunction());
        target->Set(String::NewFromUtf8(v8::Isolate::GetCurrent(), "detachScale"), FunctionTemplate::New(v8::Isolate::GetCurrent(), H5ds::detach_scale)->GetFunction());
        target->Set(String::NewFromUtf8(v8::Isolate::GetCurrent(), "isAttached"), FunctionTemplate::New(v8::Isolate::GetCurrent(), H5ds::is_attached)->GetFunction());
        target->Set(String::NewFromUtf8(v8::Isolate::GetCurrent(), "isScale"), FunctionTemplate::New(v8::Isolate::GetCurrent(), H5ds::is_scale)->GetFunction());
        target->Set(String::NewFromUtf8(v8::Isolate::GetCurrent(), "iterateScale"), FunctionTemplate::New(v8::Isolate::GetCurrent(), H5ds::iterate_scales)->GetFunction());
        target->Set(String::NewFromUtf8(v8::Isolate::GetCurrent(), "setLabel"), FunctionTemplate::New(v8::Isolate::GetCurrent(), H5ds::set_label)->GetFunction());
        target->Set(String::NewFromUtf8(v8::Isolate::GetCurrent(), "getLabel"), FunctionTemplate::New(v8::Isolate::GetCurrent(), H5ds::get_label)->GetFunction());
        target->Set(String::NewFromUtf8(v8::Isolate::GetCurrent(), "getScaleName"), FunctionTemplate::New(v8::Isolate::GetCurrent(), H5ds::get_scale_name)->GetFunction());
        target->Set(String::NewFromUtf8(v8::Isolate::GetCurrent(), "getNumberOfScales"), FunctionTemplate::New(v8::Isolate::GetCurrent(), H5ds::get_num_scales)->GetFunction());

    }

static void set_scale (const v8::FunctionCallbackInfo<Value>& args)
{
    // fail out if arguments are not correct
    if (args.Length() != 3 || !args[0]->IsUint32() || !args[1]->IsString() || !args[2]->IsString()) {

        v8::Isolate::GetCurrent()->ThrowException(v8::Exception::SyntaxError(String::NewFromUtf8(v8::Isolate::GetCurrent(), "expected group id, dataset name, name")));
        args.GetReturnValue().SetUndefined();
        return;

    }

    String::Utf8Value dset_name (args[1]->ToString());
    String::Utf8Value dim_scale_name (args[2]->ToString());
    hid_t did=H5Dopen(args[0]->ToInt32()->Value(), *dset_name, H5P_DEFAULT);
    herr_t err=H5DSset_scale(did, *dim_scale_name);
    if(err<0){
        H5Dclose(did);
        v8::Isolate::GetCurrent()->ThrowException(v8::Exception::SyntaxError(String::NewFromUtf8(v8::Isolate::GetCurrent(), "failed setting dimension scale")));
        args.GetReturnValue().SetUndefined();
        return;

    }
    H5Dclose(did);
    args.GetReturnValue().SetUndefined();
}

static void attach_scale (const v8::FunctionCallbackInfo<Value>& args)
{
    // fail out if arguments are not correct
    if (args.Length() != 4 || !args[0]->IsInt32() || !args[1]->IsString() || !args[2]->IsString() || !args[3]->IsInt32()) {

        v8::Isolate::GetCurrent()->ThrowException(v8::Exception::SyntaxError(String::NewFromUtf8(v8::Isolate::GetCurrent(), "expected group id, dataset name, name, index")));
        args.GetReturnValue().SetUndefined();
        return;

    }

    String::Utf8Value dset_name (args[1]->ToString());
    String::Utf8Value dim_scale_name (args[2]->ToString());
    hid_t did=H5Dopen(args[0]->ToInt32()->Value(), *dset_name, H5P_DEFAULT);
    hid_t dsid=H5Dopen(args[0]->ToInt32()->Value(), *dim_scale_name, H5P_DEFAULT);
    herr_t err=H5DSattach_scale(did, dsid, args[3]->ToInt32()->Value());
    if(err<0){
        H5Dclose(dsid);
        H5Dclose(did);
        v8::Isolate::GetCurrent()->ThrowException(v8::Exception::SyntaxError(String::NewFromUtf8(v8::Isolate::GetCurrent(), "failed attaching dimension scale")));
        args.GetReturnValue().SetUndefined();
        return;

    }
    H5Dclose(dsid);
    H5Dclose(did);
    args.GetReturnValue().SetUndefined();
}

static void detach_scale (const v8::FunctionCallbackInfo<Value>& args)
{
    // fail out if arguments are not correct
    if (args.Length() != 4 || !args[0]->IsInt32() || !args[1]->IsString() || !args[2]->IsString() || !args[3]->IsInt32()) {

        v8::Isolate::GetCurrent()->ThrowException(v8::Exception::SyntaxError(String::NewFromUtf8(v8::Isolate::GetCurrent(), "expected group id, dataset name, name, index")));
        args.GetReturnValue().SetUndefined();
        return;

    }

    String::Utf8Value dset_name (args[1]->ToString());
    String::Utf8Value dim_scale_name (args[2]->ToString());
    hid_t did=H5Dopen(args[0]->ToInt32()->Value(), *dset_name, H5P_DEFAULT);
    hid_t dsid=H5Dopen(args[0]->ToInt32()->Value(), *dim_scale_name, H5P_DEFAULT);
    herr_t err=H5DSdetach_scale(did, dsid, args[3]->ToInt32()->Value());
    if(err<0){
        H5Dclose(dsid);
        H5Dclose(did);
        v8::Isolate::GetCurrent()->ThrowException(v8::Exception::SyntaxError(String::NewFromUtf8(v8::Isolate::GetCurrent(), "failed attaching dimension scale")));
        args.GetReturnValue().SetUndefined();
        return;

    }
    H5Dclose(dsid);
    H5Dclose(did);
    args.GetReturnValue().SetUndefined();
}

static void is_attached (const v8::FunctionCallbackInfo<Value>& args)
{
    // fail out if arguments are not correct
    if (args.Length() != 4 || !args[0]->IsInt32() || !args[1]->IsString() || !args[2]->IsString() || !args[3]->IsInt32()) {

        v8::Isolate::GetCurrent()->ThrowException(v8::Exception::SyntaxError(String::NewFromUtf8(v8::Isolate::GetCurrent(), "expected group id, dataset name, name, index")));
        args.GetReturnValue().SetUndefined();
        return;

    }

    String::Utf8Value dset_name (args[1]->ToString());
    String::Utf8Value dim_scale_name (args[2]->ToString());
    hid_t did=H5Dopen(args[0]->ToInt32()->Value(), *dset_name, H5P_DEFAULT);
    hid_t dsid=H5Dopen(args[0]->ToInt32()->Value(), *dim_scale_name, H5P_DEFAULT);
    htri_t status=H5DSis_attached(did, dsid, args[3]->ToInt32()->Value());
    args.GetReturnValue().Set((status) ? true : false);
    H5Dclose(dsid);
    H5Dclose(did);
}

static void is_scale (const v8::FunctionCallbackInfo<Value>& args)
{
    // fail out if arguments are not correct
    if (args.Length() != 2 || !args[0]->IsInt32() || !args[1]->IsString()) {

        v8::Isolate::GetCurrent()->ThrowException(v8::Exception::SyntaxError(String::NewFromUtf8(v8::Isolate::GetCurrent(), "expected group id, dataset name")));
        args.GetReturnValue().SetUndefined();
        return;

    }

    String::Utf8Value dset_name (args[1]->ToString());
    hid_t did=H5Dopen(args[0]->ToInt32()->Value(), *dset_name, H5P_DEFAULT);
    htri_t status=H5DSis_scale(did);
    args.GetReturnValue().Set((status) ? true : false);
    H5Dclose(did);
}

static void iterate_scales (const v8::FunctionCallbackInfo<Value>& args)
{

    String::Utf8Value dset_name (args[1]->ToString());
    int rank;
    H5LTget_dataset_ndims (args[0]->ToInt32()->Value(), *dset_name, &rank);
    hid_t did=H5Dopen(args[0]->ToInt32()->Value(), *dset_name, H5P_DEFAULT);
    int idx=args[2]->ToInt32()->Value();
        v8::Persistent<v8::Function> callback;
        const unsigned argc = 2;
        callback.Reset(v8::Isolate::GetCurrent(), args[3].As<Function>());
        std::function<herr_t(hid_t did, unsigned int dim, hid_t dsid, void *visitor_data)> f=[&](hid_t did, unsigned int dim, hid_t dsid, void *visitor_data){
        v8::Local<v8::Value> argv[2] = { v8::Int32::New(v8::Isolate::GetCurrent(), dim),v8:: String::NewFromUtf8(v8::Isolate::GetCurrent(), "success") };
        v8::Local<v8::Function>::New(v8::Isolate::GetCurrent(), callback)->Call(v8::Isolate::GetCurrent()->GetCurrentContext()->Global(), argc, argv);
            return (herr_t)0;
        };
        v8::Local<v8::Function> func=v8::Local<v8::Function>::New(v8::Isolate::GetCurrent(), callback);
    herr_t err=H5DSiterate_scales( did, (unsigned int)rank, &idx, [](hid_t did, unsigned int dim, hid_t dsid, void *visitor_data) -> herr_t {
        v8::Local<v8::Value> argv[2] = { v8::Int32::New(v8::Isolate::GetCurrent(), dim),v8:: String::NewFromUtf8(v8::Isolate::GetCurrent(), "success") };
        ((v8::Local<v8::Function>*)visitor_data)[0]->Call(v8::Isolate::GetCurrent()->GetCurrentContext()->Global(), 3, argv);
        return (herr_t)0;
    }, &func);
    if(err<0){
        H5Dclose(did);
        v8::Isolate::GetCurrent()->ThrowException(v8::Exception::SyntaxError(String::NewFromUtf8(v8::Isolate::GetCurrent(), "failed iterating through  scale indices")));
        args.GetReturnValue().SetUndefined();
        return;

    }
//        callback.Reset();
    H5Dclose(did);
        args.GetReturnValue().SetUndefined();
}

static void set_label (const v8::FunctionCallbackInfo<Value>& args)
{
    // fail out if arguments are not correct
    if (args.Length() != 4 || !args[0]->IsInt32() || !args[1]->IsString() || !args[2]->IsInt32() || !args[3]->IsString()) {

        v8::Isolate::GetCurrent()->ThrowException(v8::Exception::SyntaxError(String::NewFromUtf8(v8::Isolate::GetCurrent(), "expected group id, scale name, index, label")));
        args.GetReturnValue().SetUndefined();
        return;

    }

    String::Utf8Value dset_name (args[1]->ToString());
    hid_t did=H5Dopen(args[0]->ToInt32()->Value(), *dset_name, H5P_DEFAULT);
    std::string label(*String::Utf8Value(args[3]->ToString()));
    /*herr_t err=*/H5DSset_label(did, args[2]->ToInt32()->Value(), (char*)label.c_str());
    H5Dclose(did);
    args.GetReturnValue().SetUndefined();
}

static void get_label (const v8::FunctionCallbackInfo<Value>& args)
{

    // fail out if arguments are not correct
    if (args.Length() != 3 || !args[0]->IsInt32() || !args[1]->IsString() || !args[2]->IsInt32()) {

        v8::Isolate::GetCurrent()->ThrowException(v8::Exception::SyntaxError(String::NewFromUtf8(v8::Isolate::GetCurrent(), "expected group id, scale name, index")));
        args.GetReturnValue().SetUndefined();
        return;

    }

    String::Utf8Value dset_name (args[1]->ToString());
    hid_t did=H5Dopen(args[0]->ToInt32()->Value(), *dset_name, H5P_DEFAULT);
    size_t size=0;
    size=H5DSget_label(did, args[2]->ToInt32()->Value(), NULL, size);
    std::string name(size+1, '\0');
    size=H5DSget_label(did, args[2]->ToInt32()->Value(), (char*)name.c_str(), size+1);
    args.GetReturnValue().Set(v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), name.c_str()));
    H5Dclose(did);
}

static void get_scale_name (const v8::FunctionCallbackInfo<Value>& args)
{
    // fail out if arguments are not correct
    if (args.Length() != 2 || !args[0]->IsInt32() || !args[1]->IsString()) {

        v8::Isolate::GetCurrent()->ThrowException(v8::Exception::SyntaxError(String::NewFromUtf8(v8::Isolate::GetCurrent(), "expected group id, scale name")));
        args.GetReturnValue().SetUndefined();
        return;

    }

    String::Utf8Value dset_name (args[1]->ToString());
    hid_t did=H5Dopen(args[0]->ToInt32()->Value(), *dset_name, H5P_DEFAULT);
    size_t size=0;
    size=H5DSget_scale_name(did, NULL, size);
    std::string name(size+1, '\0');
    size=H5DSget_scale_name(did, (char*)name.c_str(), size+1);
    args.GetReturnValue().Set(v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), name.c_str()));
    H5Dclose(did);
}

static void get_num_scales (const v8::FunctionCallbackInfo<Value>& args)
{

    // fail out if arguments are not correct
    if (args.Length() != 3 || !args[0]->IsInt32() || !args[1]->IsString() || !args[2]->IsInt32()) {

        v8::Isolate::GetCurrent()->ThrowException(v8::Exception::SyntaxError(String::NewFromUtf8(v8::Isolate::GetCurrent(), "expected group id, dataset name, index")));
        args.GetReturnValue().SetUndefined();
        return;

    }

    String::Utf8Value dset_name (args[1]->ToString());
    hid_t did=H5Dopen(args[0]->ToInt32()->Value(), *dset_name, H5P_DEFAULT);
    int num=H5DSget_num_scales(did, args[2]->ToInt32()->Value());
    args.GetReturnValue().Set(v8::Uint32::New(v8::Isolate::GetCurrent(), num));
    H5Dclose(did);
}

    };
}<|endoftext|>


<commit_before>#include "gridmap.hpp"
#include "../utils/utils.hpp"
#include "../visnav/visgraph.hpp"
#include <vector>

typedef std::vector<unsigned int> Comp;

static std::vector<Comp*> comps(const GridMap&);
static Polygon poly(const GridMap&, const Comp*);
static void adduniq(std::vector<Point>&, const Point&);
Polygon giftwrap(double, const std::vector<Point>&);
static unsigned int mincwangle(double, const std::vector<Point>&, unsigned int,
	unsigned int);
static unsigned int minx(const std::vector<Point>&);

int main(int argc, char *argv[]) {
	GridMap map(stdin);

	std::vector<Comp*> cs = comps(map);

	std::vector<Polygon> ps;
	for (unsigned int i = 0; i < cs.size(); i++)
		ps.push_back(poly(map, cs[i]));

	while (cs.size() > 0) {
		delete cs.back();
		cs.pop_back();
	}

	VisGraph vg(ps);
	vg.output(stdout);

	return 0;
}

static std::vector<Comp*> comps(const GridMap &map) {
	Djset *forest = new Djset[map.size()];

	for (unsigned int l = 0; l < map.size(); l++) {
		if (map.passable(l))
			continue;

		unsigned int x = map.x(l), y = map.y(l);
		if (x < map.width() - 1 && !map.passable(map.right(l)))
			forest[l].join(forest[map.right(l)]);

		// split map in half to ensure outter boundry is a polygon
		if (y < map.height() - 1 && y != map.height() / 2 &&
				!map.passable(map.down(l)))
			forest[l].join(forest[map.down(l)]);
	}

	std::vector<Comp*> cs;
	for (unsigned int l = 0; l < map.size(); l++) {
		if (map.passable(l))
			continue;

		Djset *s = forest[l].find();
		if (!s->aux) {
			cs.push_back(new Comp());
			s->aux = cs[cs.size() - 1];
		}
		((Comp*) s->aux)->push_back(l);
	}

	delete[] forest;

	return cs;
}

#include <cassert>

static Polygon poly(const GridMap &map, const Comp *c) {
	std::vector<Point> pts;
	double w = 1.0 / map.width();
	double h = 1.0 / map.height();

	for (unsigned int i = 0; i < c->size(); i++) {
		assert (!map.passable(c->at(i)));
		unsigned int x = map.x(c->at(i));
		unsigned int y = map.y(c->at(i));
		adduniq(pts, Point(x * w, y * h));
		adduniq(pts, Point((x + 1) * w, y * h));
		adduniq(pts, Point((x + 1) * w, (y + 1) * h));
		adduniq(pts, Point(x * w, (y + 1) * h));
	}

	return giftwrap(w > h ? w : h, pts);
}

static void adduniq(std::vector<Point> &pts, const Point &p) {
	for (unsigned int i = 0; i < pts.size(); i++) {
		if (pts[i].x == p.x && pts[i].y == p.y)
			return;
	}
	pts.push_back(p);
}

Polygon giftwrap(double d, const std::vector<Point> &pts) {
	std::vector<Point> hull;
	unsigned int min = minx(pts);

	unsigned int cur = min, prev = pts.size();
	do {
		unsigned int next = mincwangle(d, pts, prev, cur);

		for (unsigned int i = 0; i < hull.size(); i++)
			assert(hull[i] != pts[next]);

		hull.push_back(pts[next]);
		prev = cur;
		cur = next;
	} while (cur != min);

	return Polygon(hull);
}

static unsigned int mincwangle(double d, const std::vector<Point> &pts,
		unsigned int prev, unsigned int cur) {
	double mint = std::numeric_limits<double>::infinity();
	unsigned int mini = 0;
	double mind = -1;

	for (unsigned int i = 0; i < pts.size(); i++) {
		double dist = Point::distance(pts[cur], pts[i]);
		if (i == prev || i == cur || dist > d * 1.01)
			continue;

		Point prevpt(pts[cur].x, pts[cur].y - 0.1);
		if (prev < pts.size())
			prevpt = pts[prev];

		double t = Point::cwangle(prevpt, pts[cur], pts[i]);
		if (t < mint) {
			mind = dist;
			mint = t;
			mini = i;
		}
	}

	return mini;
}

static unsigned int minx(const std::vector<Point> &pts) {
	unsigned int min = pts.size();
	for (unsigned int i = 0; i < pts.size(); i++) {
		if (min >= pts.size() || pts[i].x < pts[min].x)
			min = i;
	}
	return min;
}<commit_msg>gridnav: when converting to polys, only split when connected to component 0. This is sufficient to make the boundary a polygon without splitting all polygons that cross the center line.<commit_after>#include "gridmap.hpp"
#include "../utils/utils.hpp"
#include "../visnav/visgraph.hpp"
#include <vector>

typedef std::vector<unsigned int> Comp;

static std::vector<Comp*> comps(const GridMap&);
static Polygon poly(const GridMap&, const Comp*);
static void adduniq(std::vector<Point>&, const Point&);
Polygon giftwrap(double, const std::vector<Point>&);
static unsigned int mincwangle(double, const std::vector<Point>&, unsigned int,
	unsigned int);
static unsigned int minx(const std::vector<Point>&);

int main(int argc, char *argv[]) {
	GridMap map(stdin);

	std::vector<Comp*> cs = comps(map);

	std::vector<Polygon> ps;
	for (unsigned int i = 0; i < cs.size(); i++)
		ps.push_back(poly(map, cs[i]));

	while (cs.size() > 0) {
		delete cs.back();
		cs.pop_back();
	}

	VisGraph vg(ps);
	vg.output(stdout);

	return 0;
}

static std::vector<Comp*> comps(const GridMap &map) {
	Djset *forest = new Djset[map.size()];

	for (unsigned int l = 0; l < map.size(); l++) {
		if (map.passable(l))
			continue;

		unsigned int x = map.x(l), y = map.y(l);
		if (x < map.width() - 1 && !map.passable(map.right(l)))
			forest[l].join(forest[map.right(l)]);

		// split map in half to ensure outter boundry is a polygon
		if (y < map.height() - 1 && !map.passable(map.down(l)) &&
 			(y != map.height() / 2 || forest[l].find() != forest[0].find()))
			forest[l].join(forest[map.down(l)]);
	}

	std::vector<Comp*> cs;
	for (unsigned int l = 0; l < map.size(); l++) {
		if (map.passable(l))
			continue;

		Djset *s = forest[l].find();
		if (!s->aux) {
			cs.push_back(new Comp());
			s->aux = cs[cs.size() - 1];
		}
		((Comp*) s->aux)->push_back(l);
	}

	delete[] forest;

	return cs;
}

#include <cassert>

static Polygon poly(const GridMap &map, const Comp *c) {
	std::vector<Point> pts;
	double w = 1.0 / map.width();
	double h = 1.0 / map.height();

	for (unsigned int i = 0; i < c->size(); i++) {
		assert (!map.passable(c->at(i)));
		unsigned int x = map.x(c->at(i));
		unsigned int y = map.y(c->at(i));
		adduniq(pts, Point(x * w, y * h));
		adduniq(pts, Point((x + 1) * w, y * h));
		adduniq(pts, Point((x + 1) * w, (y + 1) * h));
		adduniq(pts, Point(x * w, (y + 1) * h));
	}

	return giftwrap(w > h ? w : h, pts);
}

static void adduniq(std::vector<Point> &pts, const Point &p) {
	for (unsigned int i = 0; i < pts.size(); i++) {
		if (pts[i].x == p.x && pts[i].y == p.y)
			return;
	}
	pts.push_back(p);
}

Polygon giftwrap(double d, const std::vector<Point> &pts) {
	std::vector<Point> hull;
	unsigned int min = minx(pts);

	unsigned int cur = min, prev = pts.size();
	do {
		unsigned int next = mincwangle(d, pts, prev, cur);

		for (unsigned int i = 0; i < hull.size(); i++)
			assert(hull[i] != pts[next]);

		hull.push_back(pts[next]);
		prev = cur;
		cur = next;
	} while (cur != min);

	return Polygon(hull);
}

static unsigned int mincwangle(double d, const std::vector<Point> &pts,
		unsigned int prev, unsigned int cur) {
	double mint = std::numeric_limits<double>::infinity();
	unsigned int mini = 0;
	double mind = -1;

	for (unsigned int i = 0; i < pts.size(); i++) {
		double dist = Point::distance(pts[cur], pts[i]);
		if (i == prev || i == cur || dist > d * 1.01)
			continue;

		Point prevpt(pts[cur].x, pts[cur].y - 0.1);
		if (prev < pts.size())
			prevpt = pts[prev];

		double t = Point::cwangle(prevpt, pts[cur], pts[i]);
		if (t < mint) {
			mind = dist;
			mint = t;
			mini = i;
		}
	}

	return mini;
}

static unsigned int minx(const std::vector<Point> &pts) {
	unsigned int min = pts.size();
	for (unsigned int i = 0; i < pts.size(); i++) {
		if (min >= pts.size() || pts[i].x < pts[min].x)
			min = i;
	}
	return min;
}<|endoftext|>


<commit_before>/*
 * Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include <stdexcept>
#include "instanceNormalizationPlugin.h"

using namespace nvinfer1;
using nvinfer1::plugin::InstanceNormalizationPlugin;
using nvinfer1::plugin::InstanceNormalizationPluginCreator;

#define CHECK_CUDA(call)                                                                                \
    do                                                                                \
    {                                                                                \
        cudaError_t status = call;                                                                                \
        if (status != cudaSuccess)                                                                                \
        {                                                                                \
            return status;                                                                                \
        }                                                                                \
    } while (0)

#define CHECK_CUDNN(call)                                                                                \
    do                                                                                \
    {                                                                                \
        cudnnStatus_t status = call;                                                                                \
        if (status != CUDNN_STATUS_SUCCESS)                                                                            \
        {                                                                                \
            return status;                                                                                \
        }                                                                                \
    } while (0)

inline bool is_CHW(nvinfer1::Dims const& dims)
{
    return (dims.nbDims == 3 && dims.type[0] == nvinfer1::DimensionType::kCHANNEL
        && dims.type[1] == nvinfer1::DimensionType::kSPATIAL && dims.type[2] == nvinfer1::DimensionType::kSPATIAL);
}

// This is derived from: https://fgiesen.wordpress.com/2012/03/28/half-to-float-done-quic/
inline float half_to_float_fast(unsigned short value)
{
    union F32
    {
        unsigned int u;
        float f;
    };
    static const F32 magic = {(254 - 15) << 23};
    static const F32 was_infnan = {(127 + 16) << 23};
    F32 result;
    result.u = (value & 0x7fff) << 13; // exponent/mantissa bits
    result.f *= magic.f;               // exponent adjust
    if (result.f >= was_infnan.f)
    { // make sure Inf/NaN survive
        result.u |= 255 << 23;
    }
    result.u |= (value & 0x8000) << 16; // sign bit
    return result.f;
}

cudnnStatus_t convert_trt2cudnn_dtype(nvinfer1::DataType trt_dtype, cudnnDataType_t* cudnn_dtype)
{
    switch (trt_dtype)
    {
    case nvinfer1::DataType::kFLOAT: *cudnn_dtype = CUDNN_DATA_FLOAT; break;
    case nvinfer1::DataType::kHALF: *cudnn_dtype = CUDNN_DATA_HALF; break;
    default: return CUDNN_STATUS_BAD_PARAM;
    }
    return CUDNN_STATUS_SUCCESS;
}

namespace {
    constexpr const char* INSTANCE_PLUGIN_VERSION{"001"};
    constexpr const char* INSTANCE_PLUGIN_NAME{"InstanceNormalization_TRT"};
}

PluginFieldCollection InstanceNormalizationPluginCreator::mFC{};
std::vector<PluginField> InstanceNormalizationPluginCreator::mPluginAttributes;

InstanceNormalizationPlugin::InstanceNormalizationPlugin(
    float epsilon, const std::vector<float>& scale, const std::vector<float>& bias)
    : _epsilon(epsilon)
    , _nchan(scale.size())
    , _h_scale(scale)
    , _h_bias(bias)
    , _initialized(false)
{
    ASSERT(scale.size() == bias.size());
}

InstanceNormalizationPlugin::InstanceNormalizationPlugin(
    float epsilon, nvinfer1::Weights const& scale, nvinfer1::Weights const& bias)
    : _epsilon(epsilon)
    , _nchan(scale.count)
    , _initialized(false)
{
    ASSERT(scale.count == bias.count);
    if (scale.type == nvinfer1::DataType::kFLOAT)
    {
        _h_scale.assign((float*) scale.values, (float*) scale.values + scale.count);
    }
    else if (scale.type == nvinfer1::DataType::kHALF)
    {
        _h_scale.reserve(_nchan);
        for (int c = 0; c < _nchan; ++c)
        {
            unsigned short value = ((unsigned short*) scale.values)[c];
            _h_scale.push_back(half_to_float_fast(value));
        }
    }
    else
    {
        throw std::runtime_error("Unsupported scale dtype");
    }
    if (bias.type == nvinfer1::DataType::kFLOAT)
    {
        _h_bias.assign((float*) bias.values, (float*) bias.values + bias.count);
    }
    else if (bias.type == nvinfer1::DataType::kHALF)
    {
        _h_bias.reserve(_nchan);
        for (int c = 0; c < _nchan; ++c)
        {
            unsigned short value = ((unsigned short*) bias.values)[c];
            _h_bias.push_back(half_to_float_fast(value));
        }
    }
    else
    {
        throw std::runtime_error("Unsupported bias dtype");
    }
}

InstanceNormalizationPlugin::InstanceNormalizationPlugin(void const* serialData, size_t serialLength) : _initialized(false)
{
    deserialize_value(&serialData, &serialLength, &_epsilon);
    deserialize_value(&serialData, &serialLength, &_nchan);
    deserialize_value(&serialData, &serialLength, &_h_scale);
    deserialize_value(&serialData, &serialLength, &_h_bias);
}

InstanceNormalizationPlugin::~InstanceNormalizationPlugin()
{
    terminate();
}

// InstanceNormalizationPlugin returns one output.
int InstanceNormalizationPlugin::getNbOutputs() const
{
    return 1;
}

DimsExprs InstanceNormalizationPlugin::getOutputDimensions(
    int outputIndex, const nvinfer1::DimsExprs* inputs, int nbInputs, nvinfer1::IExprBuilder& exprBuilder)
{
    nvinfer1::DimsExprs output(inputs[0]);
    return output;
}

int InstanceNormalizationPlugin::initialize()
{
    _initialized = true;
    return 0;
}

void InstanceNormalizationPlugin::terminate()
{
    if (!_initialized)
    {
        return;
    }
    cudnnDestroyTensorDescriptor(_y_desc);
    cudnnDestroyTensorDescriptor(_x_desc);
    cudnnDestroyTensorDescriptor(_b_desc);
    cudaFree(_d_bias);
    cudaFree(_d_scale);
    cudnnDestroy(_cudnn_handle);
    _initialized = false;
}

size_t InstanceNormalizationPlugin::getWorkspaceSize(const nvinfer1::PluginTensorDesc* inputs, int nbInputs, const nvinfer1::PluginTensorDesc* outputs, int nbOutputs) const
{
    return 0;
}

int InstanceNormalizationPlugin::enqueue(const nvinfer1::PluginTensorDesc* inputDesc,
    const nvinfer1::PluginTensorDesc* outputDesc, const void* const* inputs, void* const* outputs, void* workspace,
    cudaStream_t stream)
{
    nvinfer1::Dims input_dims = inputDesc[0].dims;
    int n = input_dims.d[0];
    int c = input_dims.d[1];
    int h = input_dims.d[2];
    int w = input_dims.d[3];
    size_t nchan_bytes = c * sizeof(float);

    // Note: We repeat the data for each batch entry so that we can do the full
    //       computation in a single CUDNN call in enqueue().
    CHECK_CUDA(cudaMalloc((void**) &_d_scale, n * nchan_bytes));
    CHECK_CUDA(cudaMalloc((void**) &_d_bias, n * nchan_bytes));
    for (int i = 0; i < n; ++i)
    {
        CHECK_CUDA(cudaMemcpy(_d_scale + i * c, _h_scale.data(), nchan_bytes, cudaMemcpyHostToDevice));
        CHECK_CUDA(cudaMemcpy(_d_bias + i * c, _h_bias.data(), nchan_bytes, cudaMemcpyHostToDevice));
    }
    CHECK_CUDNN(cudnnCreate(&_cudnn_handle));
    CHECK_CUDNN(cudnnCreateTensorDescriptor(&_b_desc));
    CHECK_CUDNN(cudnnCreateTensorDescriptor(&_x_desc));
    CHECK_CUDNN(cudnnCreateTensorDescriptor(&_y_desc));

    CHECK_CUDNN(cudnnSetTensor4dDescriptor(_b_desc, CUDNN_TENSOR_NCHW, CUDNN_DATA_FLOAT, 1, n * c, 1, 1));
    cudnnDataType_t cudnn_dtype;
    CHECK_CUDNN(convert_trt2cudnn_dtype(inputDesc[0].type, &cudnn_dtype));
    CHECK_CUDNN(cudnnSetTensor4dDescriptor(_x_desc, CUDNN_TENSOR_NCHW, cudnn_dtype, 1, n * c, h, w));
    CHECK_CUDNN(cudnnSetTensor4dDescriptor(_y_desc, CUDNN_TENSOR_NCHW, cudnn_dtype, 1, n * c, h, w));
    float alpha = 1;
    float beta = 0;
    void const* x_ptr = inputs[0];
    void* y_ptr = outputs[0];
    CHECK_CUDNN(cudnnSetStream(_cudnn_handle, stream));
    // Note: Use of CUDNN_BATCHNORM_SPATIAL_PERSISTENT can cause numerical
    //       overflows (NaNs) for fp32 data in some circumstances. The lower-
    //       performance CUDNN_BATCHNORM_SPATIAL should be used if this is not
    //       acceptable.
    CHECK_CUDNN(cudnnBatchNormalizationForwardTraining(_cudnn_handle, CUDNN_BATCHNORM_SPATIAL_PERSISTENT, &alpha, &beta,
        _x_desc, x_ptr, _y_desc, y_ptr, _b_desc, _d_scale, _d_bias, 1., nullptr, nullptr, _epsilon, nullptr, nullptr));
    return 0;
}

size_t InstanceNormalizationPlugin::getSerializationSize() const
{
    return (serialized_size(_epsilon) +
            serialized_size(_nchan) +
            serialized_size(_h_scale) +
            serialized_size(_h_bias));
}

void InstanceNormalizationPlugin::serialize(void *buffer) const
{
    serialize_value(&buffer, _epsilon);
    serialize_value(&buffer, _nchan);
    serialize_value(&buffer, _h_scale);
    serialize_value(&buffer, _h_bias);
}

bool InstanceNormalizationPlugin::supportsFormatCombination(
    int pos, const nvinfer1::PluginTensorDesc* inOut, int nbInputs, int nbOutputs)
{
    ASSERT(inOut && pos < (nbInputs + nbOutputs));
    return ((inOut[pos].type == nvinfer1::DataType::kFLOAT || inOut[pos].type == nvinfer1::DataType::kHALF)
        && inOut[pos].format == nvinfer1::PluginFormat::kNCHW);
}

const char* InstanceNormalizationPlugin::getPluginType() const
{
    return INSTANCE_PLUGIN_NAME;
}

const char* InstanceNormalizationPlugin::getPluginVersion() const
{
    return INSTANCE_PLUGIN_VERSION;
}

void InstanceNormalizationPlugin::destroy()
{
    delete this;
}

IPluginV2DynamicExt* InstanceNormalizationPlugin::clone() const
{
    return new InstanceNormalizationPlugin{_epsilon, _h_scale, _h_bias};
}

// Set plugin namespace
void InstanceNormalizationPlugin::setPluginNamespace(const char* pluginNamespace)
{
    mPluginNamespace = pluginNamespace;
}

const char* InstanceNormalizationPlugin::getPluginNamespace() const
{
    return mPluginNamespace;
}

nvinfer1::DataType InstanceNormalizationPlugin::getOutputDataType(
    int index, const nvinfer1::DataType* inputTypes, int nbInputs) const
{
    ASSERT(inputTypes && nbInputs > 0 && index == 0);
    return inputTypes[0];
}

// Attach the plugin object to an execution context and grant the plugin the access to some context resource.
void InstanceNormalizationPlugin::attachToContext(cudnnContext* cudnnContext, cublasContext* cublasContext, IGpuAllocator* gpuAllocator)
{
}

// Detach the plugin object from its execution context.
void InstanceNormalizationPlugin::detachFromContext() {}

void InstanceNormalizationPlugin::configurePlugin(const nvinfer1::DynamicPluginTensorDesc* in, int nbInputs,
    const nvinfer1::DynamicPluginTensorDesc* out, int nbOutputs)
{
    for (int i = 0; i < nbInputs; i++)
    {
      for (int j = 0; j < in[0].desc.dims.nbDims; j++)
      {
        // Do not support dynamic dimensions
        ASSERT(in[0].desc.dims.d[j] != -1);
      }
    }
}

// InstanceNormalizationPluginCreator methods
InstanceNormalizationPluginCreator::InstanceNormalizationPluginCreator()
{
    mPluginAttributes.emplace_back(PluginField("epsilon", nullptr, PluginFieldType::kFLOAT32, 1));
    mPluginAttributes.emplace_back(PluginField("scales", nullptr, PluginFieldType::kFLOAT32, 1));
    mPluginAttributes.emplace_back(PluginField("bias", nullptr, PluginFieldType::kFLOAT32, 1));

    mFC.nbFields = mPluginAttributes.size();
    mFC.fields = mPluginAttributes.data();
}

const char* InstanceNormalizationPluginCreator::getPluginName() const
{
    return INSTANCE_PLUGIN_NAME;
}

const char* InstanceNormalizationPluginCreator::getPluginVersion() const
{
    return INSTANCE_PLUGIN_VERSION;
}

const PluginFieldCollection* InstanceNormalizationPluginCreator::getFieldNames()
{
    return &mFC;
}

IPluginV2DynamicExt* InstanceNormalizationPluginCreator::createPlugin(const char* name, const nvinfer1::PluginFieldCollection* fc)
{
    std::vector<float> scaleValues;
    std::vector<float> biasValues;
    float epsilon {};
    const PluginField* fields = fc->fields;
    for (int i = 0; i < fc->nbFields; ++i)
    {
        const char* attrName = fields[i].name;
        if (!strcmp(attrName, "epsilon"))
        {
            ASSERT(fields[i].type == PluginFieldType::kFLOAT32);
            epsilon= *(static_cast<const float*>(fields[i].data));
        }
        else if (!strcmp(attrName, "scales"))
        {
            ASSERT(fields[i].type == PluginFieldType::kFLOAT32);
            int size = fields[i].length;
            scaleValues.reserve(size);
            const auto* w = static_cast<const float*>(fields[i].data);
            for (int j = 0; j < size; j++)
            {
                scaleValues.push_back(*w);
                w++;
            }
        }
        else if (!strcmp(attrName, "bias"))
        {
            ASSERT(fields[i].type == PluginFieldType::kFLOAT32);
            int size = fields[i].length;
            biasValues.reserve(size);
            const auto* w = static_cast<const float*>(fields[i].data);
            for (int j = 0; j < size; j++)
            {
                biasValues.push_back(*w);
                w++;
            }
        }
    }

    Weights scaleWeights{DataType::kFLOAT, scaleValues.data(), (int64_t) scaleValues.size()};
    Weights biasWeights{DataType::kFLOAT, biasValues.data(), (int64_t) biasValues.size()};

    InstanceNormalizationPlugin* obj = new InstanceNormalizationPlugin(epsilon, scaleWeights, biasWeights);
    obj->setPluginNamespace(mNamespace.c_str());
    return obj;
}

IPluginV2DynamicExt* InstanceNormalizationPluginCreator::deserializePlugin(const char* name, const void* serialData, size_t serialLength)
{
    InstanceNormalizationPlugin* obj = new InstanceNormalizationPlugin{serialData, serialLength};
    obj->setPluginNamespace(mNamespace.c_str());
    return obj;
}
<commit_msg>Fix memory leaks in instanceNormalizationPlugin #296<commit_after>/*
 * Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include <stdexcept>
#include "instanceNormalizationPlugin.h"

using namespace nvinfer1;
using nvinfer1::plugin::InstanceNormalizationPlugin;
using nvinfer1::plugin::InstanceNormalizationPluginCreator;

#define CHECK_CUDA(call)                                                                                \
    do                                                                                \
    {                                                                                \
        cudaError_t status = call;                                                                                \
        if (status != cudaSuccess)                                                                                \
        {                                                                                \
            return status;                                                                                \
        }                                                                                \
    } while (0)

#define CHECK_CUDNN(call)                                                                                \
    do                                                                                \
    {                                                                                \
        cudnnStatus_t status = call;                                                                                \
        if (status != CUDNN_STATUS_SUCCESS)                                                                            \
        {                                                                                \
            return status;                                                                                \
        }                                                                                \
    } while (0)

inline bool is_CHW(nvinfer1::Dims const& dims)
{
    return (dims.nbDims == 3 && dims.type[0] == nvinfer1::DimensionType::kCHANNEL
        && dims.type[1] == nvinfer1::DimensionType::kSPATIAL && dims.type[2] == nvinfer1::DimensionType::kSPATIAL);
}

// This is derived from: https://fgiesen.wordpress.com/2012/03/28/half-to-float-done-quic/
inline float half_to_float_fast(unsigned short value)
{
    union F32
    {
        unsigned int u;
        float f;
    };
    static const F32 magic = {(254 - 15) << 23};
    static const F32 was_infnan = {(127 + 16) << 23};
    F32 result;
    result.u = (value & 0x7fff) << 13; // exponent/mantissa bits
    result.f *= magic.f;               // exponent adjust
    if (result.f >= was_infnan.f)
    { // make sure Inf/NaN survive
        result.u |= 255 << 23;
    }
    result.u |= (value & 0x8000) << 16; // sign bit
    return result.f;
}

cudnnStatus_t convert_trt2cudnn_dtype(nvinfer1::DataType trt_dtype, cudnnDataType_t* cudnn_dtype)
{
    switch (trt_dtype)
    {
    case nvinfer1::DataType::kFLOAT: *cudnn_dtype = CUDNN_DATA_FLOAT; break;
    case nvinfer1::DataType::kHALF: *cudnn_dtype = CUDNN_DATA_HALF; break;
    default: return CUDNN_STATUS_BAD_PARAM;
    }
    return CUDNN_STATUS_SUCCESS;
}

namespace {
    constexpr const char* INSTANCE_PLUGIN_VERSION{"001"};
    constexpr const char* INSTANCE_PLUGIN_NAME{"InstanceNormalization_TRT"};
}

PluginFieldCollection InstanceNormalizationPluginCreator::mFC{};
std::vector<PluginField> InstanceNormalizationPluginCreator::mPluginAttributes;

InstanceNormalizationPlugin::InstanceNormalizationPlugin(
    float epsilon, const std::vector<float>& scale, const std::vector<float>& bias)
    : _epsilon(epsilon)
    , _nchan(scale.size())
    , _h_scale(scale)
    , _h_bias(bias)
    , _initialized(false)
{
    ASSERT(scale.size() == bias.size());
}

InstanceNormalizationPlugin::InstanceNormalizationPlugin(
    float epsilon, nvinfer1::Weights const& scale, nvinfer1::Weights const& bias)
    : _epsilon(epsilon)
    , _nchan(scale.count)
    , _initialized(false)
{
    ASSERT(scale.count == bias.count);
    if (scale.type == nvinfer1::DataType::kFLOAT)
    {
        _h_scale.assign((float*) scale.values, (float*) scale.values + scale.count);
    }
    else if (scale.type == nvinfer1::DataType::kHALF)
    {
        _h_scale.reserve(_nchan);
        for (int c = 0; c < _nchan; ++c)
        {
            unsigned short value = ((unsigned short*) scale.values)[c];
            _h_scale.push_back(half_to_float_fast(value));
        }
    }
    else
    {
        throw std::runtime_error("Unsupported scale dtype");
    }
    if (bias.type == nvinfer1::DataType::kFLOAT)
    {
        _h_bias.assign((float*) bias.values, (float*) bias.values + bias.count);
    }
    else if (bias.type == nvinfer1::DataType::kHALF)
    {
        _h_bias.reserve(_nchan);
        for (int c = 0; c < _nchan; ++c)
        {
            unsigned short value = ((unsigned short*) bias.values)[c];
            _h_bias.push_back(half_to_float_fast(value));
        }
    }
    else
    {
        throw std::runtime_error("Unsupported bias dtype");
    }
}

InstanceNormalizationPlugin::InstanceNormalizationPlugin(void const* serialData, size_t serialLength) : _initialized(false)
{
    deserialize_value(&serialData, &serialLength, &_epsilon);
    deserialize_value(&serialData, &serialLength, &_nchan);
    deserialize_value(&serialData, &serialLength, &_h_scale);
    deserialize_value(&serialData, &serialLength, &_h_bias);
}

InstanceNormalizationPlugin::~InstanceNormalizationPlugin()
{
    terminate();
}

// InstanceNormalizationPlugin returns one output.
int InstanceNormalizationPlugin::getNbOutputs() const
{
    return 1;
}

DimsExprs InstanceNormalizationPlugin::getOutputDimensions(
    int outputIndex, const nvinfer1::DimsExprs* inputs, int nbInputs, nvinfer1::IExprBuilder& exprBuilder)
{
    nvinfer1::DimsExprs output(inputs[0]);
    return output;
}

int InstanceNormalizationPlugin::initialize()
{
    _initialized = true;
    CHECK_CUDNN(cudnnCreate(&_cudnn_handle));
    CHECK_CUDNN(cudnnCreateTensorDescriptor(&_b_desc));
    CHECK_CUDNN(cudnnCreateTensorDescriptor(&_x_desc));
    CHECK_CUDNN(cudnnCreateTensorDescriptor(&_y_desc));
    return 0;
}

void InstanceNormalizationPlugin::terminate()
{
    if (!_initialized)
    {
        return;
    }
    cudnnDestroyTensorDescriptor(_y_desc);
    cudnnDestroyTensorDescriptor(_x_desc);
    cudnnDestroyTensorDescriptor(_b_desc);
    cudnnDestroy(_cudnn_handle);
    _initialized = false;
}

size_t InstanceNormalizationPlugin::getWorkspaceSize(const nvinfer1::PluginTensorDesc* inputs, int nbInputs, const nvinfer1::PluginTensorDesc* outputs, int nbOutputs) const
{
    return 0;
}

int InstanceNormalizationPlugin::enqueue(const nvinfer1::PluginTensorDesc* inputDesc,
    const nvinfer1::PluginTensorDesc* outputDesc, const void* const* inputs, void* const* outputs, void* workspace,
    cudaStream_t stream)
{
    nvinfer1::Dims input_dims = inputDesc[0].dims;
    int n = input_dims.d[0];
    int c = input_dims.d[1];
    int h = input_dims.d[2];
    int w = input_dims.d[3];
    size_t nchan_bytes = c * sizeof(float);

    // Note: We repeat the data for each batch entry so that we can do the full
    //       computation in a single CUDNN call in enqueue().
    CHECK_CUDA(cudaMalloc((void**) &_d_scale, n * nchan_bytes));
    CHECK_CUDA(cudaMalloc((void**) &_d_bias, n * nchan_bytes));
    for (int i = 0; i < n; ++i)
    {
        CHECK_CUDA(cudaMemcpy(_d_scale + i * c, _h_scale.data(), nchan_bytes, cudaMemcpyHostToDevice));
        CHECK_CUDA(cudaMemcpy(_d_bias + i * c, _h_bias.data(), nchan_bytes, cudaMemcpyHostToDevice));
    }

    CHECK_CUDNN(cudnnSetTensor4dDescriptor(_b_desc, CUDNN_TENSOR_NCHW, CUDNN_DATA_FLOAT, 1, n * c, 1, 1));
    cudnnDataType_t cudnn_dtype;
    CHECK_CUDNN(convert_trt2cudnn_dtype(inputDesc[0].type, &cudnn_dtype));
    CHECK_CUDNN(cudnnSetTensor4dDescriptor(_x_desc, CUDNN_TENSOR_NCHW, cudnn_dtype, 1, n * c, h, w));
    CHECK_CUDNN(cudnnSetTensor4dDescriptor(_y_desc, CUDNN_TENSOR_NCHW, cudnn_dtype, 1, n * c, h, w));
    float alpha = 1;
    float beta = 0;
    void const* x_ptr = inputs[0];
    void* y_ptr = outputs[0];
    CHECK_CUDNN(cudnnSetStream(_cudnn_handle, stream));
    // Note: Use of CUDNN_BATCHNORM_SPATIAL_PERSISTENT can cause numerical
    //       overflows (NaNs) for fp32 data in some circumstances. The lower-
    //       performance CUDNN_BATCHNORM_SPATIAL should be used if this is not
    //       acceptable.
    CHECK_CUDNN(cudnnBatchNormalizationForwardTraining(_cudnn_handle, CUDNN_BATCHNORM_SPATIAL_PERSISTENT, &alpha, &beta,
        _x_desc, x_ptr, _y_desc, y_ptr, _b_desc, _d_scale, _d_bias, 1., nullptr, nullptr, _epsilon, nullptr, nullptr));
    cudaFree(_d_bias);
    cudaFree(_d_scale);
    return 0;
}

size_t InstanceNormalizationPlugin::getSerializationSize() const
{
    return (serialized_size(_epsilon) +
            serialized_size(_nchan) +
            serialized_size(_h_scale) +
            serialized_size(_h_bias));
}

void InstanceNormalizationPlugin::serialize(void *buffer) const
{
    serialize_value(&buffer, _epsilon);
    serialize_value(&buffer, _nchan);
    serialize_value(&buffer, _h_scale);
    serialize_value(&buffer, _h_bias);
}

bool InstanceNormalizationPlugin::supportsFormatCombination(
    int pos, const nvinfer1::PluginTensorDesc* inOut, int nbInputs, int nbOutputs)
{
    ASSERT(inOut && pos < (nbInputs + nbOutputs));
    return ((inOut[pos].type == nvinfer1::DataType::kFLOAT || inOut[pos].type == nvinfer1::DataType::kHALF)
        && inOut[pos].format == nvinfer1::PluginFormat::kNCHW);
}

const char* InstanceNormalizationPlugin::getPluginType() const
{
    return INSTANCE_PLUGIN_NAME;
}

const char* InstanceNormalizationPlugin::getPluginVersion() const
{
    return INSTANCE_PLUGIN_VERSION;
}

void InstanceNormalizationPlugin::destroy()
{
    delete this;
}

IPluginV2DynamicExt* InstanceNormalizationPlugin::clone() const
{
    return new InstanceNormalizationPlugin{_epsilon, _h_scale, _h_bias};
}

// Set plugin namespace
void InstanceNormalizationPlugin::setPluginNamespace(const char* pluginNamespace)
{
    mPluginNamespace = pluginNamespace;
}

const char* InstanceNormalizationPlugin::getPluginNamespace() const
{
    return mPluginNamespace;
}

nvinfer1::DataType InstanceNormalizationPlugin::getOutputDataType(
    int index, const nvinfer1::DataType* inputTypes, int nbInputs) const
{
    ASSERT(inputTypes && nbInputs > 0 && index == 0);
    return inputTypes[0];
}

// Attach the plugin object to an execution context and grant the plugin the access to some context resource.
void InstanceNormalizationPlugin::attachToContext(cudnnContext* cudnnContext, cublasContext* cublasContext, IGpuAllocator* gpuAllocator)
{
}

// Detach the plugin object from its execution context.
void InstanceNormalizationPlugin::detachFromContext() {}

void InstanceNormalizationPlugin::configurePlugin(const nvinfer1::DynamicPluginTensorDesc* in, int nbInputs,
    const nvinfer1::DynamicPluginTensorDesc* out, int nbOutputs)
{
    for (int i = 0; i < nbInputs; i++)
    {
      for (int j = 0; j < in[0].desc.dims.nbDims; j++)
      {
        // Do not support dynamic dimensions
        ASSERT(in[0].desc.dims.d[j] != -1);
      }
    }
}

// InstanceNormalizationPluginCreator methods
InstanceNormalizationPluginCreator::InstanceNormalizationPluginCreator()
{
    mPluginAttributes.emplace_back(PluginField("epsilon", nullptr, PluginFieldType::kFLOAT32, 1));
    mPluginAttributes.emplace_back(PluginField("scales", nullptr, PluginFieldType::kFLOAT32, 1));
    mPluginAttributes.emplace_back(PluginField("bias", nullptr, PluginFieldType::kFLOAT32, 1));

    mFC.nbFields = mPluginAttributes.size();
    mFC.fields = mPluginAttributes.data();
}

const char* InstanceNormalizationPluginCreator::getPluginName() const
{
    return INSTANCE_PLUGIN_NAME;
}

const char* InstanceNormalizationPluginCreator::getPluginVersion() const
{
    return INSTANCE_PLUGIN_VERSION;
}

const PluginFieldCollection* InstanceNormalizationPluginCreator::getFieldNames()
{
    return &mFC;
}

IPluginV2DynamicExt* InstanceNormalizationPluginCreator::createPlugin(const char* name, const nvinfer1::PluginFieldCollection* fc)
{
    std::vector<float> scaleValues;
    std::vector<float> biasValues;
    float epsilon {};
    const PluginField* fields = fc->fields;
    for (int i = 0; i < fc->nbFields; ++i)
    {
        const char* attrName = fields[i].name;
        if (!strcmp(attrName, "epsilon"))
        {
            ASSERT(fields[i].type == PluginFieldType::kFLOAT32);
            epsilon= *(static_cast<const float*>(fields[i].data));
        }
        else if (!strcmp(attrName, "scales"))
        {
            ASSERT(fields[i].type == PluginFieldType::kFLOAT32);
            int size = fields[i].length;
            scaleValues.reserve(size);
            const auto* w = static_cast<const float*>(fields[i].data);
            for (int j = 0; j < size; j++)
            {
                scaleValues.push_back(*w);
                w++;
            }
        }
        else if (!strcmp(attrName, "bias"))
        {
            ASSERT(fields[i].type == PluginFieldType::kFLOAT32);
            int size = fields[i].length;
            biasValues.reserve(size);
            const auto* w = static_cast<const float*>(fields[i].data);
            for (int j = 0; j < size; j++)
            {
                biasValues.push_back(*w);
                w++;
            }
        }
    }

    Weights scaleWeights{DataType::kFLOAT, scaleValues.data(), (int64_t) scaleValues.size()};
    Weights biasWeights{DataType::kFLOAT, biasValues.data(), (int64_t) biasValues.size()};

    InstanceNormalizationPlugin* obj = new InstanceNormalizationPlugin(epsilon, scaleWeights, biasWeights);
    obj->setPluginNamespace(mNamespace.c_str());
    return obj;
}

IPluginV2DynamicExt* InstanceNormalizationPluginCreator::deserializePlugin(const char* name, const void* serialData, size_t serialLength)
{
    InstanceNormalizationPlugin* obj = new InstanceNormalizationPlugin{serialData, serialLength};
    obj->setPluginNamespace(mNamespace.c_str());
    return obj;
}
<|endoftext|>


<commit_before>// $Id: snapShotManager.C,v 1.2 2001/03/11 23:16:37 amoll Exp $

#include <BALL/KERNEL/PTE.h>
#include <BALL/MOLMEC/COMMON/snapShotManager.h>

#include <iostream>

using namespace std;

namespace BALL
{

	// Definition of class-specific options and default values
	const char *SnapShotManager::Option::FLUSH_TO_DISK_FREQUENCY
		= "flush_to_disk_frequency";

	const unsigned int SnapShotManager::Default::FLUSH_TO_DISK_FREQUENCY = 10;

	SnapShotManager::SnapShotManager()
		throw()
		: options(),
			system_ptr_(0),
			force_field_ptr_(0),
			snapshot_buffer_(0),
			trajectory_file_ptr_(0),
			flush_to_disk_frequency_(0),
			valid_(false)
	{
		options.setDefaultInteger(SnapShotManager::Option::FLUSH_TO_DISK_FREQUENCY,
				SnapShotManager::Default::FLUSH_TO_DISK_FREQUENCY);
	}

	// The constructor of the SnapshotManager.
	// It expects a valid system, a force field, and a filename  of a
	// snapshot file along with a boolean that indicates if an existing file
	// shall be overwritten.  If the file does not exist yet, it will be
	// created and a header consisting of the system and some internal
	// information will be written to it.  It the file is already existent
	// and overwrite is set to false, the header will read in and compared
	// with the given system. They must match.  Subsequent snapshots will
	// then be appended to the file.
	SnapShotManager::SnapShotManager
		(System* my_system, const ForceField* my_forcefield,
		 TrajectoryFile* file, bool /* overwrite */)
		throw()
		: options(),
			system_ptr_(my_system),
			force_field_ptr_(my_forcefield),
			snapshot_buffer_(0),
			trajectory_file_ptr_(file),
			flush_to_disk_frequency_(0),
			buffer_counter_(0),
			valid_(false)
	{
		options.setDefaultInteger(SnapShotManager::Option::FLUSH_TO_DISK_FREQUENCY,
				SnapShotManager::Default::FLUSH_TO_DISK_FREQUENCY);

		// call the setup method
		valid_ = setup();
	}

	// The constructor of the SnapshotManager.
	// It expects a valid system and force field, a filename  of a snapshot
	// file along with a boolean that indicates if an existing file shall be
	// overwritten, and the options.  If the file does not exist yet, it will
	// be created and a header consisting of the system and some internal
	// information will be written to it.  It the file is already existent
	// and overwrite is set to false, the header will read in and compared
	// with the given system. They must match. Subsequent snapshots will be
	// appended to the file.
	SnapShotManager::SnapShotManager
		(System* my_system, const ForceField* my_forcefield,
		 const Options& my_options, TrajectoryFile* file,
		 bool /* overwrite */)
		throw()
		: options(my_options),
			system_ptr_(my_system),
			force_field_ptr_(my_forcefield),
			snapshot_buffer_(0),
			trajectory_file_ptr_(file),
			flush_to_disk_frequency_(0),
			buffer_counter_(0),
			valid_(false)
	{
		// simply call the setup method
		valid_ = setup();
	}

	// The copy constructor of the SnapShotManager
	// All data will be copied. But the copy will flush snapshots to the same
	// file as the original instance and it will use the same system and
	// force field!
	// NOTE, that this copy constructor DOES NOT copy the system and force
	// field but only the pointers!
	SnapShotManager::SnapShotManager (const SnapShotManager& manager)
		throw()
		: options(manager.options),
			system_ptr_(manager.system_ptr_),
			force_field_ptr_(manager.force_field_ptr_),
			snapshot_buffer_(manager.snapshot_buffer_),
			trajectory_file_ptr_(manager.trajectory_file_ptr_),
			flush_to_disk_frequency_(manager.flush_to_disk_frequency_),
			buffer_counter_(0),
			valid_(manager.valid_)
	{
	}

	// The destructor of SnapShotManager
	SnapShotManager::~SnapShotManager()
		throw()
	{
		// clear() handles open files, so the destructor does not handle them
		clear();

		valid_ = false;
	}

	const SnapShotManager& SnapShotManager::operator =
		(const SnapShotManager& manager)
		throw()
	{
		options = manager.options;
		system_ptr_ = manager.system_ptr_;
		force_field_ptr_ = manager.force_field_ptr_;
		snapshot_buffer_ = manager.snapshot_buffer_;
		trajectory_file_ptr_ = manager.trajectory_file_ptr_;
		flush_to_disk_frequency_ = manager.flush_to_disk_frequency_;
		buffer_counter_ = manager.buffer_counter_;
		valid_ = manager.valid_;

		return *this;
	}

	void SnapShotManager::clear()
		throw()
	{
		// BAUSTELLE
		flushToDisk();

		// now bring the instance to initial state
		options.clear();
		system_ptr_ = 0;
		force_field_ptr_ = 0;
		snapshot_buffer_.clear();
		trajectory_file_ptr_ = 0;
		flush_to_disk_frequency_ =
			options.getInteger(SnapShotManager::Option::FLUSH_TO_DISK_FREQUENCY);
		buffer_counter_ = 0;
		valid_ = false;
	}

	bool SnapShotManager::isValid() const
		throw()
	{
		return valid_;
	}

	// The setup method does the actual preparations
	bool SnapShotManager::setup(System* my_system,
			const ForceField* my_forcefield, TrajectoryFile* my_snapshot_file)
		throw()
	{
		setSystem(my_system);
		setForceField(my_forcefield);
		setTrajectoryFile(my_snapshot_file);
		return setup();
	}

	// The setup method does the actual preparations
	bool SnapShotManager::setup()
		throw()
	{

		// first test for existence of system and force field
		if (system_ptr_ == 0 || !system_ptr_->isValid())
		{
			Log.error() << "SnapShotManager::setup(): No/invalid system." << endl;
			return false;
		}
		if (force_field_ptr_ == 0 || !force_field_ptr_->isValid())
		{
			Log.error() << "SnapShotManager::setup(): No/invald force field." << endl;
			return false;
		}

		// now check that the force field is assigned to the system
		if (force_field_ptr_->getSystem() != system_ptr_)
		{
			Log.error() << "SnapShotManager::setup(): Systems do not match." << endl;
			return false;
		}

		// first get the options
		flush_to_disk_frequency_ =
			options.getInteger(SnapShotManager::Option::FLUSH_TO_DISK_FREQUENCY);

		// if there was already snapshot data, clear it.
		// clear() does too much... Should I rewrite setup()? Or do I believe,
		// that setup is called only(!) in a constructor?
		snapshot_buffer_.clear();
		// snapshot_buffer_.resize(flush_to_disk_frequency_);

		return true;

	}	// end of SnapShotManager::setup

	// This method calculates the current kinetic energy of the system
	// (only selected atoms are considered)
	double SnapShotManager::calculateKineticEnergy_()
	{
		// First define some local variables
		double sq_velocity;
		double sum, result;

		AtomVector::Iterator atom_it;
		AtomVector selected_atoms;

		sum = 0.0;
		selected_atoms = force_field_ptr_->getAtoms();

		// The current temperature (calculated as instantaneous kinetic energy)
		// If we use a periodic boundary box, then we use the molecules' centres of
		// gravity, otherwise we iterate directly over the individual atoms of the system

		atom_it = selected_atoms.begin();

		if (force_field_ptr_->periodic_boundary.isEnabled() == true)
		{
			float molecule_mass = 0;
			float mass;

			int no_of_molecules = 0;

			Molecule *old, *current;
			Vector3 centre_velocity;

			centre_velocity.x = centre_velocity.y = centre_velocity.z = 0;

			// Get the molecule of the first atom in the system
			old = (*atom_it)->getMolecule();

			// Iterate over all atoms in the system and determine for every
			// molecule the velocity of its centre of mass
			// This velocity contributes to the overall temperature
			AtomVector::Iterator end_it = selected_atoms.end();

			while (atom_it != end_it)
			{
				// determine the molecule of the current atom
				current = (*atom_it)->getMolecule();

				if (current != old)
				{
					// This atom belongs to an other molecule than the
					// previous atom -> all atoms of the previous
					// molecule have been visited
					centre_velocity /= molecule_mass;
					sq_velocity = centre_velocity * centre_velocity;
					sum += molecule_mass * sq_velocity;

					no_of_molecules++;

					// reset some values for the new molecule
					molecule_mass = 0;
					centre_velocity.x = centre_velocity.y = centre_velocity.z = 0;

					// the new molecule is now the old one
					old = current;
				}

				// add the atom's velocity to the total velocity
				// of the current molecule
				mass = (*atom_it)->getElement().getAtomicWeight();
				molecule_mass += mass;
				centre_velocity += mass * (*atom_it)->getVelocity();

				// go on to the next atom
				++atom_it;
			}

			// The last molecule must be added as this is not done in the while-loop
			if (molecule_mass == 0)
			{
				// A strange molecule. Let the centre_velocity as it is
			}
			else
			{
				centre_velocity /= molecule_mass;
			}

			sq_velocity = centre_velocity * centre_velocity;
			sum += molecule_mass * sq_velocity;
			no_of_molecules++;

			// 0.01 scales Da*A^2/ps^2 to kJ/mol
			result = 0.5 * sum * 0.01;

		}
		else
		{
			// Iterate over all atoms and calculate \sum m_i \cdot v_i^2
			for (atom_it = selected_atoms.begin(); atom_it != selected_atoms.end(); ++atom_it)
			{
				sq_velocity = (*atom_it)->getVelocity() * (*atom_it)->getVelocity();
				sum += (*atom_it)->getElement().getAtomicWeight() * sq_velocity;
			}

			// 0.01 scales Da*A^2/ps^2 to kJ/mol
			result = 0.5 * sum * 0.01;
		}

		return result;

	}	// end of 'calculateKineticEnergy'

	void SnapShotManager::setSystem(System* my_system)
		throw()
	{
		system_ptr_ = my_system;
	}

	System* SnapShotManager::getSystem() const
		throw()
	{
		return system_ptr_;
	}

	void SnapShotManager::setForceField(const ForceField* my_ff)
		throw()
	{
		force_field_ptr_ = my_ff;
	}

	const ForceField* SnapShotManager::getForceField() const
		throw()
	{
		return force_field_ptr_;
	}

	void SnapShotManager::setTrajectoryFile(TrajectoryFile* my_file)
		throw()
	{
		trajectory_file_ptr_ = my_file;
	}

	TrajectoryFile* SnapShotManager::getTrajectoryFile() const
		throw()
	{
		return trajectory_file_ptr_;
	}

	void SnapShotManager::setFlushToDiskFrequency(Size number)
		throw()
	{
		flush_to_disk_frequency_ = number;
	}

	Size SnapShotManager::getFlushToDiskFrequency() const
		throw()
	{
		return flush_to_disk_frequency_;
	}

	// The following is not true at the moment...
	// This method takes a snapshot of the system's current state and stores
	// it in memory. If no memory is available or a maximum number of
	// snapshots has been taken, all snapshots so far are saved to disk The
	// first snapshot taken (and with no other previous snapshots in a file)
	// has index 1.
	void SnapShotManager::takeSnapShot()
		throw()
	{
		// create a new Snapshot-Object
		SnapShot snapshot;

		// store all current positions, forces, velocities in the
		// snapshot object
		snapshot.takeSnapShot(*system_ptr_);

		// store the potential energies
		// snapshot_ptr->potential_energy_ = force_field_ptr_->getEnergy();
		snapshot.setPotentialEnergy(force_field_ptr_->getEnergy());

		// store the kinetic energy of all selected atoms in the system
		// the current value must be calculated as it is not provided by
		// the force field
		snapshot.setKineticEnergy(calculateKineticEnergy_());

		// One more snapshot. Add it to the current list of snapshots
		snapshot_buffer_.push_back(snapshot);
		// snapshot_buffer_[buffer_counter_] = snapshot;
		buffer_counter_++;

		// We could! use pushback() and size() to determine when to flush the
		// buffers, but this is faster.
		if (buffer_counter_ >= flush_to_disk_frequency_)
		{
			// write all snapshots to disk in order to prevent memory overflow
			flushToDisk();
			snapshot_buffer_.clear();
			// BAUSTELLE is that REALLY necessary?
			// snapshot_buffer_.resize(flush_to_disk_frequency_);
			buffer_counter_ = 0;
		}
	}	// end of SnapShotManager::takeSnapShot()

	void SnapShotManager::applySnapShot(const SnapShot& snapshot)
		throw()
	{
		snapshot.applySnapShot(*system_ptr_);
	}

	// This method writes all snapshots in memory to the snapshot file on disk
	void SnapShotManager::flushToDisk()
		throw()
	{
		// if no snapshots are in main memory, then there is nothing to do
		if (snapshot_buffer_.size() == 0)
		{
			Log.info() << "SnapShotManager::flushToDisk(): "
				<< "nothing to do." << endl;
			return;
		}

		trajectory_file_ptr_->flushToDisk(snapshot_buffer_);

	}	// end of SnapShotManager::flushToDisk()

}
<commit_msg>added: apply*<commit_after>// $Id: snapShotManager.C,v 1.3 2001/03/21 18:15:34 anker Exp $

#include <BALL/KERNEL/PTE.h>
#include <BALL/MOLMEC/COMMON/snapShotManager.h>

#include <iostream>

using namespace std;

namespace BALL
{

	// Definition of class-specific options and default values
	const char *SnapShotManager::Option::FLUSH_TO_DISK_FREQUENCY
		= "flush_to_disk_frequency";

	const unsigned int SnapShotManager::Default::FLUSH_TO_DISK_FREQUENCY = 10;

	SnapShotManager::SnapShotManager()
		throw()
		: options(),
			system_ptr_(0),
			force_field_ptr_(0),
			snapshot_buffer_(0),
			trajectory_file_ptr_(0),
			flush_to_disk_frequency_(0),
			valid_(false)
	{
		options.setDefaultInteger(SnapShotManager::Option::FLUSH_TO_DISK_FREQUENCY,
				SnapShotManager::Default::FLUSH_TO_DISK_FREQUENCY);
	}

	// The constructor of the SnapshotManager.
	// It expects a valid system, a force field, and a filename  of a
	// snapshot file along with a boolean that indicates if an existing file
	// shall be overwritten.  If the file does not exist yet, it will be
	// created and a header consisting of the system and some internal
	// information will be written to it.  It the file is already existent
	// and overwrite is set to false, the header will read in and compared
	// with the given system. They must match.  Subsequent snapshots will
	// then be appended to the file.
	SnapShotManager::SnapShotManager
		(System* my_system, const ForceField* my_forcefield,
		 TrajectoryFile* file, bool /* overwrite */)
		throw()
		: options(),
			system_ptr_(my_system),
			force_field_ptr_(my_forcefield),
			snapshot_buffer_(0),
			trajectory_file_ptr_(file),
			flush_to_disk_frequency_(0),
			buffer_counter_(0),
			valid_(false)
	{
		options.setDefaultInteger(SnapShotManager::Option::FLUSH_TO_DISK_FREQUENCY,
				SnapShotManager::Default::FLUSH_TO_DISK_FREQUENCY);

		// call the setup method
		valid_ = setup();
	}

	// The constructor of the SnapshotManager.
	// It expects a valid system and force field, a filename  of a snapshot
	// file along with a boolean that indicates if an existing file shall be
	// overwritten, and the options.  If the file does not exist yet, it will
	// be created and a header consisting of the system and some internal
	// information will be written to it.  It the file is already existent
	// and overwrite is set to false, the header will read in and compared
	// with the given system. They must match. Subsequent snapshots will be
	// appended to the file.
	SnapShotManager::SnapShotManager
		(System* my_system, const ForceField* my_forcefield,
		 const Options& my_options, TrajectoryFile* file,
		 bool /* overwrite */)
		throw()
		: options(my_options),
			system_ptr_(my_system),
			force_field_ptr_(my_forcefield),
			snapshot_buffer_(0),
			trajectory_file_ptr_(file),
			flush_to_disk_frequency_(0),
			buffer_counter_(0),
			valid_(false)
	{
		// simply call the setup method
		valid_ = setup();
	}

	// The copy constructor of the SnapShotManager
	// All data will be copied. But the copy will flush snapshots to the same
	// file as the original instance and it will use the same system and
	// force field!
	// NOTE, that this copy constructor DOES NOT copy the system and force
	// field but only the pointers!
	SnapShotManager::SnapShotManager (const SnapShotManager& manager)
		throw()
		: options(manager.options),
			system_ptr_(manager.system_ptr_),
			force_field_ptr_(manager.force_field_ptr_),
			snapshot_buffer_(manager.snapshot_buffer_),
			trajectory_file_ptr_(manager.trajectory_file_ptr_),
			flush_to_disk_frequency_(manager.flush_to_disk_frequency_),
			buffer_counter_(0),
			valid_(manager.valid_)
	{
	}

	// The destructor of SnapShotManager
	SnapShotManager::~SnapShotManager()
		throw()
	{
		// clear() handles open files, so the destructor does not handle them
		clear();

		valid_ = false;
	}

	const SnapShotManager& SnapShotManager::operator =
		(const SnapShotManager& manager)
		throw()
	{
		options = manager.options;
		system_ptr_ = manager.system_ptr_;
		force_field_ptr_ = manager.force_field_ptr_;
		snapshot_buffer_ = manager.snapshot_buffer_;
		trajectory_file_ptr_ = manager.trajectory_file_ptr_;
		flush_to_disk_frequency_ = manager.flush_to_disk_frequency_;
		buffer_counter_ = manager.buffer_counter_;
		valid_ = manager.valid_;

		return *this;
	}

	void SnapShotManager::clear()
		throw()
	{
		// BAUSTELLE
		flushToDisk();

		// now bring the instance to initial state
		options.clear();
		system_ptr_ = 0;
		force_field_ptr_ = 0;
		snapshot_buffer_.clear();
		trajectory_file_ptr_ = 0;
		flush_to_disk_frequency_ =
			options.getInteger(SnapShotManager::Option::FLUSH_TO_DISK_FREQUENCY);
		buffer_counter_ = 0;
		valid_ = false;
	}

	bool SnapShotManager::isValid() const
		throw()
	{
		return valid_;
	}

	// The setup method does the actual preparations
	bool SnapShotManager::setup(System* my_system,
			const ForceField* my_forcefield, TrajectoryFile* my_snapshot_file)
		throw()
	{
		setSystem(my_system);
		setForceField(my_forcefield);
		setTrajectoryFile(my_snapshot_file);
		return setup();
	}

	// The setup method does the actual preparations
	bool SnapShotManager::setup()
		throw()
	{

		// first test for existence of system and force field
		if (system_ptr_ == 0 || !system_ptr_->isValid())
		{
			Log.error() << "SnapShotManager::setup(): No/invalid system." << endl;
			return false;
		}
		if (force_field_ptr_ == 0 || !force_field_ptr_->isValid())
		{
			Log.error() << "SnapShotManager::setup(): No/invald force field." << endl;
			return false;
		}

		// now check that the force field is assigned to the system
		if (force_field_ptr_->getSystem() != system_ptr_)
		{
			Log.error() << "SnapShotManager::setup(): Systems do not match." << endl;
			return false;
		}

		// first get the options
		flush_to_disk_frequency_ =
			options.getInteger(SnapShotManager::Option::FLUSH_TO_DISK_FREQUENCY);

		// if there was already snapshot data, clear it.
		// clear() does too much... Should I rewrite setup()? Or do I believe,
		// that setup is called only(!) in a constructor?
		snapshot_buffer_.clear();
		// snapshot_buffer_.resize(flush_to_disk_frequency_);

		return true;

	}	// end of SnapShotManager::setup

	// This method calculates the current kinetic energy of the system
	// (only selected atoms are considered)
	double SnapShotManager::calculateKineticEnergy_()
	{
		// First define some local variables
		double sq_velocity;
		double sum, result;

		AtomVector::Iterator atom_it;
		AtomVector selected_atoms;

		sum = 0.0;
		selected_atoms = force_field_ptr_->getAtoms();

		// The current temperature (calculated as instantaneous kinetic energy)
		// If we use a periodic boundary box, then we use the molecules' centres of
		// gravity, otherwise we iterate directly over the individual atoms of the system

		atom_it = selected_atoms.begin();

		if (force_field_ptr_->periodic_boundary.isEnabled() == true)
		{
			float molecule_mass = 0;
			float mass;

			int no_of_molecules = 0;

			Molecule *old, *current;
			Vector3 centre_velocity;

			centre_velocity.x = centre_velocity.y = centre_velocity.z = 0;

			// Get the molecule of the first atom in the system
			old = (*atom_it)->getMolecule();

			// Iterate over all atoms in the system and determine for every
			// molecule the velocity of its centre of mass
			// This velocity contributes to the overall temperature
			AtomVector::Iterator end_it = selected_atoms.end();

			while (atom_it != end_it)
			{
				// determine the molecule of the current atom
				current = (*atom_it)->getMolecule();

				if (current != old)
				{
					// This atom belongs to an other molecule than the
					// previous atom -> all atoms of the previous
					// molecule have been visited
					centre_velocity /= molecule_mass;
					sq_velocity = centre_velocity * centre_velocity;
					sum += molecule_mass * sq_velocity;

					no_of_molecules++;

					// reset some values for the new molecule
					molecule_mass = 0;
					centre_velocity.x = centre_velocity.y = centre_velocity.z = 0;

					// the new molecule is now the old one
					old = current;
				}

				// add the atom's velocity to the total velocity
				// of the current molecule
				mass = (*atom_it)->getElement().getAtomicWeight();
				molecule_mass += mass;
				centre_velocity += mass * (*atom_it)->getVelocity();

				// go on to the next atom
				++atom_it;
			}

			// The last molecule must be added as this is not done in the while-loop
			if (molecule_mass == 0)
			{
				// A strange molecule. Let the centre_velocity as it is
			}
			else
			{
				centre_velocity /= molecule_mass;
			}

			sq_velocity = centre_velocity * centre_velocity;
			sum += molecule_mass * sq_velocity;
			no_of_molecules++;

			// 0.01 scales Da*A^2/ps^2 to kJ/mol
			result = 0.5 * sum * 0.01;

		}
		else
		{
			// Iterate over all atoms and calculate \sum m_i \cdot v_i^2
			for (atom_it = selected_atoms.begin(); atom_it != selected_atoms.end(); ++atom_it)
			{
				sq_velocity = (*atom_it)->getVelocity() * (*atom_it)->getVelocity();
				sum += (*atom_it)->getElement().getAtomicWeight() * sq_velocity;
			}

			// 0.01 scales Da*A^2/ps^2 to kJ/mol
			result = 0.5 * sum * 0.01;
		}

		return result;

	}	// end of 'calculateKineticEnergy'

	void SnapShotManager::setSystem(System* my_system)
		throw()
	{
		system_ptr_ = my_system;
	}

	System* SnapShotManager::getSystem() const
		throw()
	{
		return system_ptr_;
	}

	void SnapShotManager::setForceField(const ForceField* my_ff)
		throw()
	{
		force_field_ptr_ = my_ff;
	}

	const ForceField* SnapShotManager::getForceField() const
		throw()
	{
		return force_field_ptr_;
	}

	void SnapShotManager::setTrajectoryFile(TrajectoryFile* my_file)
		throw()
	{
		trajectory_file_ptr_ = my_file;
	}

	TrajectoryFile* SnapShotManager::getTrajectoryFile() const
		throw()
	{
		return trajectory_file_ptr_;
	}

	void SnapShotManager::setFlushToDiskFrequency(Size number)
		throw()
	{
		flush_to_disk_frequency_ = number;
	}

	Size SnapShotManager::getFlushToDiskFrequency() const
		throw()
	{
		return flush_to_disk_frequency_;
	}

	// The following is not true at the moment...
	// This method takes a snapshot of the system's current state and stores
	// it in memory. If no memory is available or a maximum number of
	// snapshots has been taken, all snapshots so far are saved to disk The
	// first snapshot taken (and with no other previous snapshots in a file)
	// has index 1.
	void SnapShotManager::takeSnapShot()
		throw()
	{
		// create a new Snapshot-Object
		SnapShot snapshot;

		// store all current positions, forces, velocities in the
		// snapshot object
		snapshot.takeSnapShot(*system_ptr_);

		// store the potential energies
		// snapshot_ptr->potential_energy_ = force_field_ptr_->getEnergy();
		snapshot.setPotentialEnergy(force_field_ptr_->getEnergy());

		// store the kinetic energy of all selected atoms in the system
		// the current value must be calculated as it is not provided by
		// the force field
		snapshot.setKineticEnergy(calculateKineticEnergy_());

		// One more snapshot. Add it to the current list of snapshots
		snapshot_buffer_.push_back(snapshot);
		// snapshot_buffer_[buffer_counter_] = snapshot;
		buffer_counter_++;

		// We could! use pushback() and size() to determine when to flush the
		// buffers, but this is faster.
		if (buffer_counter_ >= flush_to_disk_frequency_)
		{
			// write all snapshots to disk in order to prevent memory overflow
			flushToDisk();
			snapshot_buffer_.clear();
			// BAUSTELLE is that REALLY necessary?
			// snapshot_buffer_.resize(flush_to_disk_frequency_);
			buffer_counter_ = 0;
		}
	}	// end of SnapShotManager::takeSnapShot()

	bool SnapShotManager::applySnapShot(Size number)
		throw()
	{
		SnapShot buffer;

		if (number > trajectory_file_ptr_->getNumberOfSnapShots())
		{
			Log.error() << "SnapShotManager::applySnapShot(): "
				<< "requested SnapShot number " << number
				<< " while the file only contains "
				<< trajectory_file_ptr_->getNumberOfSnapShots()
				<< " SnapShots" << endl;
			return false;
		}

		// We have to avoid seek() so we need to reopen and read from the
		// beginning
		trajectory_file_ptr_->reopen();
		for  (Size count = 0; count < number; ++count)
		{
			if (!trajectory_file_ptr_->read(buffer))
			{
				Log.error() << "SnapShotManager::applySnapShot(): "
					<< "error reading from the TrajectoryFile" << endl;
				return false;
			}
		}
		// now apply the last snapshot we read
		buffer.applySnapShot(*system_ptr_);
		return true;
	}

	bool SnapShotManager::applyFirstSnapShot()
		throw()
	{
		SnapShot buffer;

		// BAUSTELLE:
		// We should check for file validity here

		trajectory_file_ptr_->reopen();
		return applyNextSnapShot();
	}

	bool SnapShotManager::applyNextSnapShot()
		throw()
	{
		SnapShot buffer;

		if (trajectory_file_ptr_->read(buffer))
		{
			buffer.applySnapShot(*system_ptr_);
			return true;
		}
		else
		{
			Log.error() << "SnapShotManager::applyNextSnapShot() "
				<< "error reading from the TrajectoryFile" << endl;
			return false;
		}
	}

	bool SnapShotManager::applyLastSnapShot()
		throw()
	{
		Size count = 0;
		SnapShot buffer;

		while (trajectory_file_ptr_->read(buffer))
		{
			count++;
		}

		if (count == trajectory_file_ptr_->getNumberOfSnapShots())
		{
			buffer.applySnapShot(*system_ptr_);
		}
		else
		{
			Log.error() << "SnapShotManager::applyLastSnapShot(): "
				<< "read " << count
				<< " SnapShots while TrajectoryFile claims to have "
				<< trajectory_file_ptr_->getNumberOfSnapShots()
				<< " SnapShots" << endl;
			return false;
		}
	}

	// This method writes all snapshots in memory to the snapshot file on disk
	void SnapShotManager::flushToDisk()
		throw()
	{
		// if no snapshots are in main memory, then there is nothing to do
		if (snapshot_buffer_.size() == 0)
		{
			Log.info() << "SnapShotManager::flushToDisk(): "
				<< "nothing to do." << endl;
			return;
		}

		trajectory_file_ptr_->flushToDisk(snapshot_buffer_);

	}	// end of SnapShotManager::flushToDisk()

}
<|endoftext|>


<commit_before>/*
 * main.cpp
 *
 *  Created on: Apr 7, 2016
 *      Author: padolph
 */

#include "gtest/gtest.h"
#include <stdlib.h>
#include <iostream>
#include <unistd.h>

using namespace std;

namespace netflix { namespace msl {
extern int g_exBacktraceDepth;   // defined in Exception.cpp
}}

int main(int argc, char **argv)
{
  ::testing::InitGoogleTest(&argc, argv);
  int c;
  opterr = 0;
  while ((c = getopt (argc, argv, "d:")) != -1) {
      switch (c) {
          case 'd':
              netflix::msl::g_exBacktraceDepth = atoi(optarg)+1;
              break;
          default:
              std::cout << "bad command line args" << endl;
              break;
      }
  }
  return RUN_ALL_TESTS();
}
<commit_msg>Clean up openssl at end of test main.<commit_after>/*
 * main.cpp
 *
 *  Created on: Apr 7, 2016
 *      Author: padolph
 */

#include "gtest/gtest.h"
#include <stdlib.h>
#include <iostream>
#include <unistd.h>

using namespace std;

namespace netflix { namespace msl {
extern int g_exBacktraceDepth;   // defined in Exception.cpp
}}

int main(int argc, char **argv)
{
  ::testing::InitGoogleTest(&argc, argv);
  int c;
  opterr = 0;
  while ((c = getopt (argc, argv, "d:")) != -1) {
      switch (c) {
          case 'd':
              netflix::msl::g_exBacktraceDepth = atoi(optarg)+1;
              break;
          default:
              std::cout << "bad command line args" << endl;
              break;
      }
  }
  return RUN_ALL_TESTS();
  netflix::msl::crypto::shutdownOpenSsl();
}
<|endoftext|>


<commit_before>/*

Copyright (c) 2013, Project OSRM, Dennis Luxen, others
All rights reserved.

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

*/

#include "UUID.h"

#include "OSRMException.h"
#include "../typedefs.h"

#include <boost/uuid/uuid_generators.hpp> // generators
#include <boost/uuid/uuid_io.hpp>         // streaming operators etc.

#include <cstring>

#include <algorithm>
#include <iostream>
#include <string>

#define HAS64BITS 0
#define MD5PREPARE "0942f9ef6f5912b4fbeae8249dd4df4b"
#define MD5RTREE "40c04fc573a4cea3832d0587908807c9"
#define MD5GRAPH "9f3a0e84509ff908655bbe2464d852b7"
#define MD5OBJECTS "7135d52fa59aa3f2babbb8f307d8dde3"

UUID::UUID() : magic_number(1297240911)
{
    md5_prepare[32] = md5_tree[32] = md5_graph[32] = md5_objects[32] = '\0';

    boost::uuids::name_generator gen(named_uuid);
    std::string temp_string(__DATE__);
    temp_string += __TIME__;

    std::copy(MD5PREPARE, MD5PREPARE + strlen(MD5PREPARE), md5_prepare);
    temp_string += md5_prepare;
    std::copy(MD5RTREE, MD5RTREE + 32, md5_tree);
    temp_string += md5_tree;
    std::copy(MD5GRAPH, MD5GRAPH + 32, md5_graph);
    temp_string += md5_graph;
    std::copy(MD5OBJECTS, MD5OBJECTS + 32, md5_objects);
    temp_string += md5_objects;

    named_uuid = gen(temp_string);
    has_64_bits = HAS64BITS;
}

UUID::~UUID() {}

const boost::uuids::uuid &UUID::GetUUID() const { return named_uuid; }

bool UUID::IsMagicNumberOK() const { return 1297240911 == magic_number; }

bool UUID::TestGraphUtil(const UUID &other) const
{
    if (!other.IsMagicNumberOK())
    {
        throw OSRMException("hsgr input file misses magic number. Check or reprocess the file");
    }
    return std::equal(md5_graph, md5_graph + 32, other.md5_graph);
}

bool UUID::TestPrepare(const UUID &other) const
{
    if (!other.IsMagicNumberOK())
    {
        throw OSRMException("osrm input file misses magic number. Check or reprocess the file");
    }
    return std::equal(md5_prepare, md5_prepare + 32, other.md5_prepare);
}

bool UUID::TestRTree(const UUID &other) const
{
    if (!other.IsMagicNumberOK())
    {
        throw OSRMException("r-tree input file misses magic number. Check or reprocess the file");
    }
    return std::equal(md5_tree, md5_tree + 32, other.md5_tree);
}

bool UUID::TestQueryObjects(const UUID &other) const
{
    if (!other.IsMagicNumberOK())
    {
        throw OSRMException("missing magic number. Check or reprocess the file");
    }
    return std::equal(md5_objects, md5_objects + 32, other.md5_objects);
}
<commit_msg>remove accidentially added file<commit_after><|endoftext|>