/**
  *  Rank:
  *  Return matrix rank of array using SVD method
  *  Rank of the array is the number of SVD singular values of the array that are greater than threshold(info[3]).
  *
  *  arguments:
  *  info[0]: Buffer(object created by smalloc) represent the numjs.Matrix object to be inverted.
  *           Must be square, i.e. M.rows == M.cols.
  *  info[1]: Number represent the number of rows of the matrix.
  *  info[2]: Number represent the number of columns of the matrix.
  *  info[3]: Optional - Number represent the threshold which SVD values are considered zero.
  *                     If this arg is not given, and S is an array with singular values for M,
  *                     and eps is the epsilon value for datatype of S, then tol is set to S.max() * max(M.shape) * eps
  *
  *  Return value: a Number represent the matrix rank of the given matrix .
*/
void Rank(const Nan::FunctionCallbackInfo<v8::Value>& info){
    using CMd = Eigen::Map <const Eigen::MatrixXd >;
    using Md = Eigen::Map <Eigen::MatrixXd >;

    if (info.Length() < 3) {
        Nan::ThrowTypeError("Wrong number of arguments");
        return;
    }

    if (!info[1]->IsNumber() || !info[2]->IsNumber()) {
        Nan::ThrowTypeError("Wrong arguments");
        return;
    }

    Local<Object> matrixBuffer = info[0].As<Object>();
    if (matrixBuffer->HasIndexedPropertiesInExternalArrayData()) {
        double *refMatrixData = static_cast<double*>(matrixBuffer->GetIndexedPropertiesExternalArrayData());
        size_t rowsMatrix(info[1]->Uint32Value());
        size_t colsMatrix(info[2]->Uint32Value());

        Md inputMat(refMatrixData, rowsMatrix, colsMatrix);
        Eigen::JacobiSVD<Eigen::MatrixXd> svd(inputMat);
        if (info.Length() == 4 && info[3]->IsNumber()){
            svd.setThreshold((float)info[3]->NumberValue());
        }

        v8::Local<v8::Number> num = Nan::New((int)svd.rank());
        info.GetReturnValue().Set(num);
    }
    else{
        Nan::ThrowTypeError("Wrong arguments");
        Local<Boolean> b = Nan::New(false);
        info.GetReturnValue().Set(b);
    }
}
/**
  *  Rank:
  *  Return matrix rank of array using SVD method
  *  Rank of the array is the number of SVD singular values of the array that are greater than threshold(info[3]).
  *
  *  arguments:
  *  info[0]: Buffer(object created by Float64Array) represent the numjs.Matrix object to be inverted.
  *           Must be square, i.e. M.rows == M.cols.
  *  info[1]: Number represent the number of rows of the matrix.
  *  info[2]: Number represent the number of columns of the matrix.
  *  info[3]: Optional - Number represent the threshold which SVD values are considered zero.
  *                     If this arg is not given, and S is an array with singular values for M,
  *                     and eps is the epsilon value for datatype of S, then tol is set to S.max() * max(M.shape) * eps
  *
  *  Return value: a Number represent the matrix rank of the given matrix .
*/
void Rank(const Nan::FunctionCallbackInfo<v8::Value>& info){
    using CMd = Eigen::Map <const Eigen::MatrixXd >;
    using Md = Eigen::Map <Eigen::MatrixXd >;

    if (info.Length() < 3) {
        Nan::ThrowTypeError("Wrong number of arguments");
        return;
    }

    if (!info[1]->IsNumber() || !info[2]->IsNumber()) {
        Nan::ThrowTypeError("Wrong arguments");
        return;
    }

	if (info[0]->IsFloat64Array()) {
		double *refMatrixData = *(Nan::TypedArrayContents<double>(info[0]));
        size_t rowsMatrix(info[1]->Uint32Value());
        size_t colsMatrix(info[2]->Uint32Value());

        Md inputMat(refMatrixData, rowsMatrix, colsMatrix);
        Eigen::JacobiSVD<Eigen::MatrixXd> svd(inputMat);
        if (info.Length() == 4 && info[3]->IsNumber()){
            svd.setThreshold((float)info[3]->NumberValue());
        }

        v8::Local<v8::Number> num = Nan::New((int)svd.rank());
        info.GetReturnValue().Set(num);
    }
    else{
        Nan::ThrowTypeError("Wrong arguments");
        Local<Boolean> b = Nan::New(false);
        info.GetReturnValue().Set(b);
    }
}
void Find(const Nan::FunctionCallbackInfo<v8::Value>& args) {
	Nan::HandleScope scope;

	int vid = 0;
	int pid = 0;
	v8::Local<v8::Function> callback;

	if (args.Length() == 0) {
		return Nan::ThrowTypeError("First argument must be a function");
	}

	if (args.Length() == 3) {
		if (args[0]->IsNumber() && args[1]->IsNumber()) {
			vid = (int) args[0]->NumberValue();
			pid = (int) args[1]->NumberValue();
		}

		// callback
		if(!args[2]->IsFunction()) {
			return Nan::ThrowTypeError("Third argument must be a function");
		}

		callback = args[2].As<v8::Function>();
	}

	if (args.Length() == 2) {
		if (args[0]->IsNumber()) {
			vid = (int) args[0]->NumberValue();
		}

		// callback
		if(!args[1]->IsFunction()) {
			return Nan::ThrowTypeError("Second argument must be a function");
		}

		callback = args[1].As<v8::Function>();
	}

	if (args.Length() == 1) {
		// callback
		if(!args[0]->IsFunction()) {
			return Nan::ThrowTypeError("First argument must be a function");
		}

		callback = args[0].As<v8::Function>();
	}

	ListBaton* baton = new ListBaton();
	strcpy(baton->errorString, "");
	baton->callback = new Nan::Callback(callback);
	baton->vid = vid;
	baton->pid = pid;

	uv_work_t* req = new uv_work_t();
	req->data = baton;
	uv_queue_work(uv_default_loop(), req, EIO_Find, (uv_after_work_cb)EIO_AfterFind);
}
/**
  *  Det:
  *  Compute the determinant of an array.
  *
  *  arguments:
  *  info[0]: Buffer(object created by Float64Array) represent the numjs.Matrix object to be inverted.
  *           Must be square, i.e. M.rows == M.cols.
  *  info[1]: Number represent the number of rows of the matrix.
  *  info[2]: Number represent the number of columns of the matrix.
  *
  *  Return value: a Number represent the determinant of the given matrix.
*/
void Det(const Nan::FunctionCallbackInfo<v8::Value>& info){
    using CMd = Eigen::Map <const Eigen::MatrixXd >;
    using Md = Eigen::Map <Eigen::MatrixXd >;

    if (info.Length() < 3) {
        Nan::ThrowTypeError("Wrong number of arguments");
        return;
    }

    if (!info[1]->IsNumber() || !info[2]->IsNumber()) {
        Nan::ThrowTypeError("Wrong arguments");
        return;
    }

	if (info[0]->IsFloat64Array()) {
		double *refMatrixData = *(Nan::TypedArrayContents<double>(info[0]));
        size_t rowsMatrix(info[1]->Uint32Value());
        size_t colsMatrix(info[2]->Uint32Value());

        Md inputMat(refMatrixData, rowsMatrix, colsMatrix);
        v8::Local<v8::Number> num = Nan::New(inputMat.determinant());
        info.GetReturnValue().Set(num);
    }
    else{
        Nan::ThrowTypeError("Wrong arguments");
        Local<Boolean> b = Nan::New(false);
        info.GetReturnValue().Set(b);
    }
}
void SecureCellSeal::New(const Nan::FunctionCallbackInfo<v8::Value>& args)
{
    if (args.IsConstructCall()) {
        if (args.Length() < 1) {
            ThrowParameterError("Secure Cell (Seal) constructor",
                                "not enough arguments, expected master key");
            args.GetReturnValue().SetUndefined();
            return;
        }
        if (!args[0]->IsUint8Array()) {
            ThrowParameterError("Secure Cell (Seal) constructor",
                                "master key is not a byte buffer, use ByteBuffer or Uint8Array");
            args.GetReturnValue().SetUndefined();
            return;
        }
        if (node::Buffer::Length(args[0]) == 0) {
            ThrowParameterError("Secure Cell (Seal) constructor", "master key is empty");
            args.GetReturnValue().SetUndefined();
            return;
        }
        std::vector<uint8_t> key((uint8_t*)(node::Buffer::Data(args[0])),
                                 (uint8_t*)(node::Buffer::Data(args[0]) + node::Buffer::Length(args[0])));
        SecureCellSeal* obj = new SecureCellSeal(key);
        obj->Wrap(args.This());
        args.GetReturnValue().Set(args.This());
    } else {
        const int argc = 1;
        v8::Local<v8::Value> argv[argc] = {args[0]};
        v8::Local<v8::Function> cons = Nan::New<v8::Function>(constructor);
        args.GetReturnValue().Set(Nan::NewInstance(cons, argc, argv).ToLocalChecked());
    }
}
/**
  *  Eye:
  *  Creates a new nXm matrix with ones on the diagonal
  *  and zeros elsewhere.
  *
  *  arguments:
  *  info[0]: Number n which represents the number of rows in the newly built matrix
  *  info[1]: Number m which represents the number of cols in the newly built matrix
  *  info[2]: Buffer(object created by Float64Array) for return value(eye matrix nXm).
*/
void Eye(const Nan::FunctionCallbackInfo<v8::Value>& info){
    using CMd = Eigen::Map <const Eigen::MatrixXd >;
    using Md = Eigen::Map <Eigen::MatrixXd >;

    if (info.Length() < 3) {
        Nan::ThrowTypeError("Wrong number of arguments");
        return;
    }

    if (!info[0]->IsNumber() || !info[1]->IsNumber()) {
        Nan::ThrowTypeError("Wrong argument given, should be a number");
        return;
    }

    if (info[2]->IsFloat64Array()) {
        size_t rowsMatrix(info[0]->Uint32Value());
        size_t colsMatrix(info[1]->Uint32Value());

        double *refResData = *(Nan::TypedArrayContents<double>(info[2]));
        Md res(refResData, rowsMatrix, colsMatrix);
        res = Md::Identity(rowsMatrix, colsMatrix);

        Local<Boolean> b = Nan::New(true);
        info.GetReturnValue().Set(b);
    }

    else{
        Nan::ThrowTypeError("Wrong arguments2");
        Local<Boolean> b = Nan::New(false);
        info.GetReturnValue().Set(b);
    }
}
Exemple #7
0
void ParseAsync(const Nan::FunctionCallbackInfo<Value> &args) {
  Isolate *isolate = args.GetIsolate();
  int args_length = args.Length();

  if (args_length < 2) {
    isolate->ThrowException(Exception::TypeError(String::NewFromUtf8(isolate, "Wrong number of arguments")));
    return;
  }

  Local<Value> input = args[0];
  if (!ValidateInput(input, isolate)) {
    return;
  }
  if (!args[1]->IsFunction()) {
    isolate->ThrowException(Exception::TypeError(String::NewFromUtf8(isolate, "Second parameter must be a callback")));
    return;
  }

  Nan::Callback *callback = new Nan::Callback(args[1].As<Function>());
  anitomyJs::Worker *worker = new anitomyJs::Worker(callback);

  if (args_length >= 3) {
    Local<Value> options = args[2];
    if (!ValidateOptions(options, isolate) ||
        !worker->GetAnitomy()->SetOptions(options->ToObject(isolate->GetCurrentContext()).ToLocalChecked(), isolate)) {
      return;
    }
  }

  worker->GetAnitomy()->SetInput(input, isolate);
  Nan::AsyncQueueWorker(worker);
  args.GetReturnValue().Set(Nan::Undefined());
}
Exemple #8
0
void ParseSync(const Nan::FunctionCallbackInfo<Value> &args) {
  Isolate *isolate = args.GetIsolate();
  int args_length = args.Length();

  if (args_length < 1) {
    isolate->ThrowException(Exception::TypeError(String::NewFromUtf8(isolate, "Wrong number of arguments")));
    return;
  }

  Local<Value> input = args[0];
  if (!ValidateInput(input, isolate)) {
    return;
  }

  anitomyJs::AnitomyJs anitomy;
  if (args_length >= 2) {
    Local<Value> options = args[1];
    if (!ValidateOptions(options, isolate) ||
        !anitomy.SetOptions(options->ToObject(isolate->GetCurrentContext()).ToLocalChecked(), isolate)) {
      return;
    }
  }

  anitomy.SetInput(input, isolate);
  anitomy.Parse();

  args.GetReturnValue().Set(anitomy.ParsedResult(isolate));
}
/**
  *  MatrixPower:
  *  Raise a square matrix to the (integer) power n.
  *
  *  arguments:
  *  info[0]: Buffer(object created by smalloc) represent the numjs.Matrix object to be "powered".
  *           Must be square, i.e. M.rows == M.cols.
  *  info[1]: Number represent the number of rows of the matrix.
  *  info[2]: Number represent the number of columns of the matrix.
  *  info[3]: Number m represent the exponent. Can be any integer or long integer, positive, negative, or zero.
  *  info[4]: Buffer(object created by smalloc) for return value(M**m).
              If the exponent is positive or zero then the type of the elements is the same as those of M.
              If the exponent is negative the elements are floating-point.
*/
void MatrixPower(const Nan::FunctionCallbackInfo<v8::Value>& info){
    using CMd = Eigen::Map <const Eigen::MatrixXd >;
    using Md = Eigen::Map <Eigen::MatrixXd >;

    if (info.Length() < 5) {
        Nan::ThrowTypeError("Wrong number of arguments");
        return;
    }

    if (!info[1]->IsNumber() || !info[2]->IsNumber() || !info[3]->IsNumber()) {
        Nan::ThrowTypeError("Wrong arguments");
        return;
    }

    Local<Object> matrixBuffer = info[0].As<Object>();
    if (matrixBuffer->HasIndexedPropertiesInExternalArrayData()) {
        double *refMatrixData = static_cast<double*>(matrixBuffer->GetIndexedPropertiesExternalArrayData());
        size_t rowsMatrix(info[1]->Uint32Value());
        size_t colsMatrix(info[2]->Uint32Value());
        double expParam(info[3]->NumberValue());
        Md inputMat(refMatrixData, rowsMatrix, colsMatrix);

        Local<Object> resBuffer = info[4].As<Object>();
        if (resBuffer->HasIndexedPropertiesInExternalArrayData()) {
            double *refResData = static_cast<double*>(resBuffer->GetIndexedPropertiesExternalArrayData());
            Md res(refResData, rowsMatrix, colsMatrix);

            if(expParam == 0){
                res = inputMat.Identity(rowsMatrix, colsMatrix);
            }
            else{
                res = inputMat;
                if(expParam < 0){
                    res = res.inverse();
                }

                for (int i=1; i< abs(expParam); i++)
                {
                    res *= inputMat;
                }
            }

            Local<Boolean> b = Nan::New(true);
            info.GetReturnValue().Set(b);
        }
        else{
            Nan::ThrowTypeError("Wrong arguments2");
            Local<Boolean> b = Nan::New(false);
            info.GetReturnValue().Set(b);
        }
    }
    else{
        Nan::ThrowTypeError("Wrong arguments3");
        Local<Boolean> b = Nan::New(false);
        info.GetReturnValue().Set(b);
    }
}
/**
  *  MatrixPower:
  *  Raise a square matrix to the (integer) power n.
  *
  *  arguments:
  *  info[0]: Buffer(object created by Float64Array) represent the numjs.Matrix object to be "powered".
  *           Must be square, i.e. M.rows == M.cols.
  *  info[1]: Number represent the number of rows of the matrix.
  *  info[2]: Number represent the number of columns of the matrix.
  *  info[3]: Number m represent the exponent. Can be any integer or long integer, positive, negative, or zero.
  *  info[4]: Buffer(object created by Float64Array) for return value(M**m).
              If the exponent is positive or zero then the type of the elements is the same as those of M.
              If the exponent is negative the elements are floating-point.
*/
void MatrixPower(const Nan::FunctionCallbackInfo<v8::Value>& info){
    using CMd = Eigen::Map <const Eigen::MatrixXd >;
    using Md = Eigen::Map <Eigen::MatrixXd >;

    if (info.Length() < 5) {
        Nan::ThrowTypeError("Wrong number of arguments");
        return;
    }

    if (!info[1]->IsNumber() || !info[2]->IsNumber() || !info[3]->IsNumber()) {
        Nan::ThrowTypeError("Wrong arguments");
        return;
    }

    
	if (info[0]->IsFloat64Array()) {
		double *refMatrixData = *(Nan::TypedArrayContents<double>(info[0]));
        size_t rowsMatrix(info[1]->Uint32Value());
        size_t colsMatrix(info[2]->Uint32Value());
        double expParam(info[3]->NumberValue());
        Md inputMat(refMatrixData, rowsMatrix, colsMatrix);

		if (info[4]->IsFloat64Array()) {
			double *refResData = *(Nan::TypedArrayContents<double>(info[4]));
            Md res(refResData, rowsMatrix, colsMatrix);

            if(expParam == 0){
                res = inputMat.Identity(rowsMatrix, colsMatrix);
            }
            else{
                res = inputMat;
                if(expParam < 0){
                    res = res.inverse();
                }

                for (int i=1; i< abs(expParam); i++)
                {
                    res *= inputMat;
                }
            }

            Local<Boolean> b = Nan::New(true);
            info.GetReturnValue().Set(b);
        }
        else{
            Nan::ThrowTypeError("Wrong arguments2");
            Local<Boolean> b = Nan::New(false);
            info.GetReturnValue().Set(b);
        }
    }
    else{
        Nan::ThrowTypeError("Wrong arguments3");
        Local<Boolean> b = Nan::New(false);
        info.GetReturnValue().Set(b);
    }
}
void RegisterRemoved(const Nan::FunctionCallbackInfo<v8::Value>& args) {
	Nan::HandleScope scope;

	v8::Local<v8::Function> callback;

	if (args.Length() == 0) {
		return Nan::ThrowTypeError("First argument must be a function");
	}

	if (args.Length() == 1) {
		// callback
		if(!args[0]->IsFunction()) {
			return Nan::ThrowTypeError("First argument must be a function");
		}

		callback = args[0].As<v8::Function>();
	}

	removedCallback = new Nan::Callback(callback);
	isRemovedRegistered = true;
}
Exemple #12
0
void GetClipDatabase(const Nan::FunctionCallbackInfo<v8::Value>& info) {
  if ((info.Length() < 1) || (info.Length() > 1)) {
    Nan::ThrowTypeError("Wrong number of arguments");
    return;
  }

  if (!info[0]->IsNumber()) {
    Nan::ThrowTypeError("Wrong arguments");
    return;
  }

  int sizeOfData = 0;
  char* clipDatabase = GetClipDatabase(sizeOfData);

  v8::Local<v8::String> v8ClipDatabase = v8::String::New(clipDatabase, sizeOfData);
  v8::Local<v8::Object> obj = Nan::New<v8::Object>();
  obj->Set(Nan::New("msg").ToLocalChecked(), v8ClipDatabase);
  info.GetReturnValue().Set(obj);

  FreeClipDatabase(clipDatabase);
}
void VerifyMail(const Nan::FunctionCallbackInfo<v8::Value>& info) {
	if (info.Length() < 3) {
		Nan::ThrowTypeError("Wrong number of arguments");
		return;
	}
	Nan::Utf8String infile(info[0]->ToString());
	Nan::Utf8String outfile(info[1]->ToString());
	Nan::Utf8String recipfile(info[2]->ToString());
	int ret = verify_mime(*infile, *outfile, *recipfile);
	v8::Local<v8::Number> res = Nan::New(ret);
	info.GetReturnValue().Set(res);
}
void DecryptCMSMail(const Nan::FunctionCallbackInfo<v8::Value>& info) {
	if (info.Length() < 4) {
		Nan::ThrowTypeError("Wrong number of arguments");
		return;
	}
	Nan::Utf8String recipfile(info[0]->ToString());
	Nan::Utf8String pass(info[1]->ToString());
	Nan::Utf8String infile(info[2]->ToString());
	Nan::Utf8String outfile(info[3]->ToString());

	int ret = decrypt_cms(*recipfile, *pass, *infile, *outfile);
	v8::Local<v8::Number> res = Nan::New(ret);
	info.GetReturnValue().Set(res);
}
/**
  *  Triu:
  *  Creates a copy of a given matrix with all elements below the diagonal zeroed
  *
  *  arguments:
  *  info[0]: Buffer(object created by Float64Array) represent the numjs.Matrix object to be converted to lower diagonal matrix
  *  info[1]: Number represent the number of rows of the matrix.
  *  info[2]: Number represent the number of columns of the matrix.
  *  info[3]: Buffer(object created by Float64Array) for return value(M**m).
*/
void Triu(const Nan::FunctionCallbackInfo<v8::Value>& info){
    using CMd = Eigen::Map <const Eigen::MatrixXd >;
    using Md = Eigen::Map <Eigen::MatrixXd >;

    if (info.Length() < 4) {
        Nan::ThrowTypeError("Wrong number of arguments");
        return;
    }

    if (!info[1]->IsNumber() || !info[2]->IsNumber()) {
        Nan::ThrowTypeError("Wrong arguments");
        return;
    }

	if (info[0]->IsFloat64Array()) {
		double *refMatrixData = *(Nan::TypedArrayContents<double>(info[0]));
        size_t rowsMatrix(info[1]->Uint32Value());
        size_t colsMatrix(info[2]->Uint32Value());
        Md inputMat(refMatrixData, rowsMatrix, colsMatrix);

		if (info[3]->IsFloat64Array()) {
			double *refResData = *(Nan::TypedArrayContents<double>(info[3]));
            Md res(refResData, rowsMatrix, colsMatrix);
            for (int i = 0; i < rowsMatrix; i++) {
                for (int j = 0; j < colsMatrix; j++) {
                    if (j < i) {
                        res(i, j) = 0;
                    } else {
                        res(i, j) = inputMat(i, j);
                    }
                }
            }

            Local<Boolean> b = Nan::New(true);
            info.GetReturnValue().Set(b);
        }

        else{
            Nan::ThrowTypeError("Wrong argument - output matrix data should be float64array");
            Local<Boolean> b = Nan::New(false);
            info.GetReturnValue().Set(b);
        }
    }
    else{
        Nan::ThrowTypeError("Wrong argument - input matrix data should be float64array");
        Local<Boolean> b = Nan::New(false);
        info.GetReturnValue().Set(b);
    }
}
void Add(const Nan::FunctionCallbackInfo<v8::Value>& info) {
    if (info.Length() < 2) {
        Nan::ThrowTypeError("Wrong number of arguments");
        return;
    }

    if (!info[0]->IsNumber() || !info[1]->IsNumber()) {
        Nan::ThrowTypeError("Wrong arguments");
        return;
    }

    double arg0 = info[0]->NumberValue();
    double arg1 = info[1]->NumberValue();
    v8::Local<v8::Number> num = Nan::New(arg0 + arg1);

    info.GetReturnValue().Set(num);
}
void unsquashfs(const Nan::FunctionCallbackInfo<v8::Value>& info) {
  if (info.Length() < 2) {
  Nan::ThrowTypeError("Wrong number of arguments");
  return;
}

 if (!info[0]->IsString() || !info[1]->IsString()) {
   Nan::ThrowTypeError("Wrong arguments");
   return;
 }

  std::string file = std::string(*(v8::String::Utf8Value) info[0]->ToString());
  std::string dest = std::string(*(v8::String::Utf8Value) info[1]->ToString());

  int err = toDir_unsquashfs((char*)file.c_str(), (char*)dest.c_str());

  info.GetReturnValue().Set(Nan::New(err));
}
/**
  *  Inverse:
  *  Compute the (multiplicative) inverse of a matrix.
  *  Given a square matrix a, return the matrix ainv satisfying dot(a, ainv) = dot(ainv, a)
  *
  *  arguments:
  *  info[0]: Buffer(object created by Float64Array) represent the numjs.Matrix object to be inverted.
  *           Must be square, i.e. M.rows == M.cols.
  *  info[1]: Number represent the number of rows of the matrix.
  *  info[2]: Number represent the number of columns of the matrix.
  *  info[3]: Buffer(object created by Float64Array) for return value, inverse of the given matrix.
*/
void Inverse(const Nan::FunctionCallbackInfo<v8::Value>& info){
    using CMd = Eigen::Map <const Eigen::MatrixXd >;
    using Md = Eigen::Map <Eigen::MatrixXd >;

    if (info.Length() < 4) {
        Nan::ThrowTypeError("Wrong number of arguments");
        return;
    }

    if (!info[1]->IsNumber() || !info[2]->IsNumber()) {
        Nan::ThrowTypeError("Wrong arguments");
        return;
    }

	if (info[0]->IsFloat64Array()) {
		double *refMatrixData = *(Nan::TypedArrayContents<double>(info[0]));
        size_t rowsMatrix(info[1]->Uint32Value());
        size_t colsMatrix(info[2]->Uint32Value());

        Md inputMat(refMatrixData, rowsMatrix, colsMatrix);

		if (info[3]->IsFloat64Array()) {
			double *refResData = *(Nan::TypedArrayContents<double>(info[3]));
            Md res(refResData, rowsMatrix, colsMatrix);
            res = inputMat.inverse();
            Local<Boolean> b = Nan::New(true);
            info.GetReturnValue().Set(b);
        }
        else{
            Nan::ThrowTypeError("Wrong arguments (4th arg)");
            Local<Boolean> b = Nan::New(false);
            info.GetReturnValue().Set(b);
        }
    }
    else{
        Nan::ThrowTypeError("Wrong arguments (1st arg)");
        Local<Boolean> b = Nan::New(false);
        info.GetReturnValue().Set(b);
    }
}
inline void asyncForTiles(const Nan::FunctionCallbackInfo<v8::Value> &info,
                          ParameterParser argsToParams,
                          ServiceMemFn service,
                          bool requires_multiple_coordinates)
{
    auto params = argsToParams(info, requires_multiple_coordinates);
    if (!params)
        return;

    auto pluginParams = argumentsToPluginParameters(info);

    BOOST_ASSERT(params->IsValid());

    if (!info[info.Length() - 1]->IsFunction())
        return Nan::ThrowTypeError("last argument must be a callback function");

    auto *const self = Nan::ObjectWrap::Unwrap<Engine>(info.Holder());
    using ParamPtr = decltype(params);

    struct Worker final : Nan::AsyncWorker
    {
        using Base = Nan::AsyncWorker;

        Worker(std::shared_ptr<osrm::OSRM> osrm_,
               ParamPtr params_,
               ServiceMemFn service,
               Nan::Callback *callback,
               PluginParameters pluginParams_)
            : Base(callback), osrm{std::move(osrm_)}, service{std::move(service)},
              params{std::move(params_)}, pluginParams{std::move(pluginParams_)}
        {
        }

        void Execute() override try
        {
            const auto status = ((*osrm).*(service))(*params, result);
            ParseResult(status, result);
        }
        catch (const std::exception &e)
        {
            SetErrorMessage(e.what());
        }

        void HandleOKCallback() override
        {
            Nan::HandleScope scope;

            const constexpr auto argc = 2u;
            v8::Local<v8::Value> argv[argc] = {Nan::Null(), render(result)};

            callback->Call(argc, argv);
        }

        // Keeps the OSRM object alive even after shutdown until we're done with callback
        std::shared_ptr<osrm::OSRM> osrm;
        ServiceMemFn service;
        const ParamPtr params;
        const PluginParameters pluginParams;

        std::string result;
    };

    auto *callback = new Nan::Callback{info[info.Length() - 1].As<v8::Function>()};
    Nan::AsyncQueueWorker(
        new Worker{self->this_, std::move(params), service, callback, std::move(pluginParams)});
}
/**
  *  Dot:
  *  Dot product of two arrays.
  *  For 2-D arrays it is equivalent to matrix multiplication, and for 1-D arrays to inner product of vectors
  * (without complex conjugation).
  *
  *  arguments:
  *  info[0]: Number represent the number of rows of the left matrix.
  *  info[1]: Number represent the number of columns of the left matrix.
  *  info[2]: Buffer(object created by Float64Array) represent the left numjs.Matrix object .
  *  info[3]: Number represent the number of rows of the right matrix.
  *  info[4]: Number represent the number of columns of the right matrix.
  *  info[5]: Buffer(object created by Float64Array) represent the right numjs.Matrix object .
  *  info[6]: Buffer(object created by Float64Array) for return value, which is the dot product of
  *           left matrix and right matrix.
*/
void Dot(const Nan::FunctionCallbackInfo<v8::Value>& info){
    using CMd = Eigen::Map <const Eigen::MatrixXd >;
    using Md = Eigen::Map <Eigen::MatrixXd >;

	if (info.Length() < 7) {
		Nan::ThrowTypeError("Wrong number of arguments");
		return;
	}
    if (!info[0]->IsUint32() || !info[1]->IsUint32() ||
    	!info[3]->IsUint32() || !info[4]->IsUint32()) {
    	Nan::ThrowTypeError("Wrong arguments");
        return;
    }

	if (info[2]->IsNumber()) {
	    double leftParam(info[2]->NumberValue());

	    if(!info[5]->IsNumber()){          
			if (info[5]->IsFloat64Array()) {
				double *refRightData = *(Nan::TypedArrayContents<double>(info[5]));
                size_t rowsRight(info[3]->Uint32Value());
                size_t colsRight(info[4]->Uint32Value());
                CMd rightMat(refRightData, rowsRight, colsRight);

				if (info[6]->IsFloat64Array()) {
					double *refResData = *(Nan::TypedArrayContents<double>(info[6]));
                    Md res(refResData, rowsRight, colsRight);
                    res = leftParam * rightMat;

                    Local<Boolean> b = Nan::New(true);
                    info.GetReturnValue().Set(b);
                }
            }
        }

    }
	else{
		if (info[2]->IsFloat64Array()) {
			double *refLeftData = *(Nan::TypedArrayContents<double>(info[2])); 
	        size_t rowsLeft(info[0]->Uint32Value());
            size_t colsLeft(info[1]->Uint32Value());
            CMd leftMat(refLeftData, rowsLeft, colsLeft);

            if(info[5]->IsNumber()){
                double rightParam(info[5]->NumberValue());
                
				if (info[6]->IsFloat64Array()) {
					double *refResData = *(Nan::TypedArrayContents<double>(info[6]));
                    Md res(refResData, rowsLeft, colsLeft);
                    res = leftMat * rightParam;
                    Local<Boolean> b = Nan::New(true);
                    info.GetReturnValue().Set(b);
                }
            }
            else{
				if (info[5]->IsFloat64Array()) {
					double *refRightData = *(Nan::TypedArrayContents<double>(info[5]));
                	size_t rowsRight(info[3]->Uint32Value());
                    size_t colsRight(info[4]->Uint32Value());
                    CMd rightMat(refRightData, rowsRight, colsRight);

					if (info[6]->IsFloat64Array()) {
						double *refResData = *(Nan::TypedArrayContents<double>(info[6]));
                        Md res(refResData, rowsLeft, colsRight);
                         res = leftMat * rightMat;
                        Local<Boolean> b = Nan::New(true);
                        info.GetReturnValue().Set(b);
                    }
                }
            }
	    }
	    else{
	        Nan::ThrowTypeError("Wrong type of the first argument");
            return;
	    }

	    Local<Boolean> b = Nan::New(false);
        info.GetReturnValue().Set(b);
	}
}
/**
  *  Dot:
  *  Dot product of two arrays.
  *  For 2-D arrays it is equivalent to matrix multiplication, and for 1-D arrays to inner product of vectors
  * (without complex conjugation).
  *
  *  arguments:
  *  info[0]: Number represent the number of rows of the left matrix.
  *  info[1]: Number represent the number of columns of the left matrix.
  *  info[2]: Buffer(object created by smalloc) represent the left numjs.Matrix object .
  *  info[3]: Number represent the number of rows of the right matrix.
  *  info[4]: Number represent the number of columns of the right matrix.
  *  info[5]: Buffer(object created by smalloc) represent the right numjs.Matrix object .
  *  info[6]: Buffer(object created by smalloc) for return value, which is the dot product of
  *           left matrix and right matrix.
*/
void Dot(const Nan::FunctionCallbackInfo<v8::Value>& info){
    using CMd = Eigen::Map <const Eigen::MatrixXd >;
    using Md = Eigen::Map <Eigen::MatrixXd >;

	if (info.Length() < 7) {
		Nan::ThrowTypeError("Wrong number of arguments");
		return;
	}

    if (!info[0]->IsUint32() || !info[1]->IsUint32() ||
    	!info[3]->IsUint32() || !info[4]->IsUint32()) {
    	Nan::ThrowTypeError("Wrong arguments");
        return;
    }

	if (info[2]->IsNumber()) {
	    double leftParam(info[2]->NumberValue());

	    if(!info[5]->IsNumber()){
            Local<Object> rightBuffer = info[5].As<Object>();

            if (rightBuffer->HasIndexedPropertiesInExternalArrayData()) {
                double *refRightData = static_cast<double*>(rightBuffer->GetIndexedPropertiesExternalArrayData());
                size_t rowsRight(info[3]->Uint32Value());
                size_t colsRight(info[4]->Uint32Value());
                CMd rightMat(refRightData, rowsRight, colsRight);

                Local<Object> resBuffer = info[6].As<Object>();
                if (resBuffer->HasIndexedPropertiesInExternalArrayData()) {
                    double *refResData = static_cast<double*>(resBuffer->GetIndexedPropertiesExternalArrayData());
                    Md res(refResData, rowsRight, colsRight);
                    res = leftParam * rightMat;

                    Local<Boolean> b = Nan::New(true);
                    info.GetReturnValue().Set(b);
                }
            }
        }
    }
	else{
	    Local<Object> leftBuffer = info[2].As<Object>();
	    if (leftBuffer->HasIndexedPropertiesInExternalArrayData()) {
	        double *refLeftData = static_cast<double*>(leftBuffer->GetIndexedPropertiesExternalArrayData());
	        size_t rowsLeft(info[0]->Uint32Value());
            size_t colsLeft(info[1]->Uint32Value());
            CMd leftMat(refLeftData, rowsLeft, colsLeft);

            if(info[5]->IsNumber()){
                double rightParam(info[5]->NumberValue());
                Local<Object> resBuffer = info[6].As<Object>();
                if (resBuffer->HasIndexedPropertiesInExternalArrayData()) {
                    double *refResData = static_cast<double*>(resBuffer->GetIndexedPropertiesExternalArrayData());
                    Md res(refResData, rowsLeft, colsLeft);
                    res = leftMat * rightParam;
                    Local<Boolean> b = Nan::New(true);
                    info.GetReturnValue().Set(b);
                }
            }
            else{
                Local<Object> rightBuffer = info[5].As<Object>();
                if (rightBuffer->HasIndexedPropertiesInExternalArrayData()) {
                    double *refRightData = static_cast<double*>(rightBuffer->GetIndexedPropertiesExternalArrayData());
                	size_t rowsRight(info[3]->Uint32Value());
                    size_t colsRight(info[4]->Uint32Value());
                    CMd rightMat(refRightData, rowsRight, colsRight);

                    Local<Object> resBuffer = info[6].As<Object>();
                    if (resBuffer->HasIndexedPropertiesInExternalArrayData()) {
                        double *refResData = static_cast<double*>(resBuffer->GetIndexedPropertiesExternalArrayData());
                        Md res(refResData, rowsLeft, colsRight);
                         res = leftMat * rightMat;
                        Local<Boolean> b = Nan::New(true);
                        info.GetReturnValue().Set(b);
                    }
                }
            }
	    }
	    else{
	        Nan::ThrowTypeError("Wrong type of the first argument");
            return;
	    }

	    Local<Boolean> b = Nan::New(false);
        info.GetReturnValue().Set(b);
	}
}
void SecureCellSeal::encrypt(const Nan::FunctionCallbackInfo<v8::Value>& args)
{
    themis_status_t status = THEMIS_FAIL;
    SecureCellSeal* obj = Nan::ObjectWrap::Unwrap<SecureCellSeal>(args.This());
    if (args.Length() < 1) {
        ThrowParameterError("Secure Cell (Seal) failed to encrypt",
                            "not enough arguments, expected message");
        args.GetReturnValue().SetUndefined();
        return;
    }
    if (!args[0]->IsUint8Array()) {
        ThrowParameterError("Secure Cell (Seal) failed to encrypt",
                            "message is not a byte buffer, use ByteBuffer or Uint8Array");
        args.GetReturnValue().SetUndefined();
        return;
    }
    if (node::Buffer::Length(args[0]) == 0) {
        ThrowParameterError("Secure Cell (Seal) failed to encrypt", "message is empty");
        args.GetReturnValue().SetUndefined();
        return;
    }
    size_t length = 0;
    const uint8_t* context = NULL;
    size_t context_length = 0;
    if (args.Length() == 2) {
        if (!args[1]->IsUint8Array()) {
            ThrowParameterError("Secure Cell (Seal) failed to encrypt",
                                "context is not a byte buffer, use ByteBuffer or Uint8Array");
            args.GetReturnValue().SetUndefined();
            return;
        }
        context = (const uint8_t*)(node::Buffer::Data(args[1]));
        context_length = node::Buffer::Length(args[1]);
    }
    status = themis_secure_cell_encrypt_seal(&(obj->key_)[0],
                                             obj->key_.size(),
                                             context,
                                             context_length,
                                             (const uint8_t*)(node::Buffer::Data(args[0])),
                                             node::Buffer::Length(args[0]),
                                             NULL,
                                             &length);
    if (status != THEMIS_BUFFER_TOO_SMALL) {
        ThrowError("Secure Cell (Seal) failed to encrypt", status);
        args.GetReturnValue().SetUndefined();
        return;
    }
    uint8_t* data = (uint8_t*)(malloc(length));
    status = themis_secure_cell_encrypt_seal(&(obj->key_)[0],
                                             obj->key_.size(),
                                             context,
                                             context_length,
                                             (const uint8_t*)(node::Buffer::Data(args[0])),
                                             node::Buffer::Length(args[0]),
                                             data,
                                             &length);
    if (status != THEMIS_SUCCESS) {
        ThrowError("Secure Cell (Seal) failed to encrypt", status);
        free(data);
        args.GetReturnValue().SetUndefined();
        return;
    }
    args.GetReturnValue().Set(Nan::NewBuffer((char*)(data), length).ToLocalChecked());
}
/**
  *  SVD:
  *  Singular Value Decomposition.
  *  Factors the matrix a as u * np.diag(s) * v, where u and v are unitary and s is a 1-d array of a‘s singular values.
  *
  *  arguments:
  *  info[0]: Buffer(object created by Float64Array) represent the numjs.Matrix object to be inverted.
  *           Must be square, i.e. M.rows == M.cols.
  *  info[1]: Number represent the number of rows of the matrix.
  *  info[2]: Number represent the number of columns of the matrix.
  *  info[3]: full_matrices(bool, optional): If True (default), u and v have the shapes (M, M) and (N, N), respectively.
  *           Otherwise, the shapes are (M, K) and (K, N), respectively, where K = min(M, N).
  *  info[4]: compute_uv (bool, optional): Whether or not to compute u and v in addition to s. True by default.
  *  info[5]: outU - Unitary matrices. The actual shape depends on the value of full_matrices.
  *                  Only returned when compute_uv is True.
  *  info[6]: outS - The singular values for every matrix, sorted in descending order.
  *  info[7]: outV - Unitary matrices. The actual shape depends on the value of full_matrices.
  *                  Only returned when compute_uv is True.
*/
void SVD(const Nan::FunctionCallbackInfo<v8::Value>& info){
    using CMd = Eigen::Map <const Eigen::MatrixXd >;
    using Md = Eigen::Map <Eigen::MatrixXd >;

    if (info.Length() < 8) {
        Nan::ThrowTypeError("Wrong number of arguments");
        return;
    }

    if (!info[1]->IsNumber() || !info[2]->IsNumber()) {
        Nan::ThrowTypeError("Wrong arguments");
        return;
    }

	if (info[0]->IsFloat64Array()) {
		double *refMatrixData = *(Nan::TypedArrayContents<double>(info[0]));
        int rowsMatrix(info[1]->Uint32Value());
        int colsMatrix(info[2]->Uint32Value());

        Md inputMat(refMatrixData, rowsMatrix, colsMatrix);

        bool isFullMatrices = info[3]->BooleanValue();
        bool isComputeUV = info[4]->BooleanValue();
        int k = min(rowsMatrix,colsMatrix);

        if(isComputeUV){
            if (info[5]->IsFloat64Array() && info[6]->IsFloat64Array() && info[7]->IsFloat64Array()) {

                double *refResU = *(Nan::TypedArrayContents<double>(info[5]));
                double *refResS = *(Nan::TypedArrayContents<double>(info[6]));
                double *refResV = *(Nan::TypedArrayContents<double>(info[7]));

                if(isFullMatrices){
                    Eigen::JacobiSVD<Eigen::MatrixXd> svd(inputMat, Eigen::ComputeFullU | Eigen::ComputeFullV);

                    Md resU(refResU, rowsMatrix, rowsMatrix);
                    Md resV(refResV, colsMatrix, colsMatrix);

                    resU = svd.matrixU();
                    resV = svd.matrixV();

                    std::memcpy(refResS, svd.singularValues().data(), k * sizeof(double));

                    Local<Boolean> b = Nan::New(true);
                    info.GetReturnValue().Set(b);
                }
                else{
                    Eigen::JacobiSVD<Eigen::MatrixXd> svd(inputMat, Eigen::ComputeThinU | Eigen::ComputeThinV);

                    Md resU(refResU, rowsMatrix, k);
                    Md resV(refResV, k, colsMatrix);

                    resU = svd.matrixU();
                    resV = svd.matrixV();

                    std::memcpy(refResS, svd.singularValues().data(), k * sizeof(double));

                    Local<Boolean> b = Nan::New(true);
                    info.GetReturnValue().Set(b);
                }
            }
        }
        else{
            if(info[6]->IsFloat64Array()){
                double *refResS = *(Nan::TypedArrayContents<double>(info[6]));
                Eigen::JacobiSVD<Eigen::MatrixXd> svd(inputMat);
                std::memcpy(refResS, svd.singularValues().data(), k * sizeof(double));

                Local<Boolean> b = Nan::New(true);
                info.GetReturnValue().Set(b);
            }
        }
    }
    else{
        Nan::ThrowTypeError("Wrong arguments");
        Local<Boolean> b = Nan::New(false);
        info.GetReturnValue().Set(b);
    }
}