casualjavascript / blog

A collection of javascript articles stored as Github issues.
https://casualjavascript.com
MIT License
34 stars 1 forks source link

Factorial in C++ #10

Open mateogianolio opened 8 years ago

mateogianolio commented 8 years ago

This post will briefly cover how to write a Node.js addon. Why? If you're dealing with heavy computation algorithms, a C++ implementaion will in most cases be faster than its JavaScript equivalent.

View the full source code for this post.

Algorithm

Here's the factorial algorithm we'll implement (in pseudo-code):

factorial(n):
  if n == 0:
    return 1;
  return n * factorial(n - 1)

binding.gyp

To be able to compile a Node.js addon we have to create a binding.gyp file with our build target:

{
  'targets': [
    {
      'target_name': 'math',
      'sources': ['factorial.cc']
    }
  ]
}

factorial.cc

Create factorial.cc (or name it whatever but make sure it's the same as in binding.gyp). To access Node's v8 engine, include node.h:

#include <node.h>

Implement the algorithm with double precision:

double factorial(double n) {
  if (n == 0)
    return 1;
  return n * factorial(n - 1);
}

Write the binding:

void factorial(const v8::FunctionCallbackInfo<v8::Value>& info) {
  // get first argument with double precision
  double n = info[0]->NumberValue();

  // calculate result
  double result = factorial(n);

  // create a new number containing the result
  v8::Local<v8::Number> Result = v8::Number::New(info.GetIsolate(), result);

  // return result
  info
    .GetReturnValue()
    .Set(Result);
}

Finally, the addon initialization:

void Init(v8::Local<v8::Object> exports) {
  NODE_SET_METHOD(exports, "factorial", factorial);
}

NODE_MODULE(addon, Init)

Building

After completing the above, build your addon with node-gyp (you'll need build-essential):

node-gyp configure build

factorial.js

Create a new file factorial.js. When you've successfully built the addon, it will be located in build/Release/factorial.node. Include it.

var addon = require('build/Release/factorial.node');

Implement the factorial algorithm, this time in JavaScript:

function factorial(n) {
  if (n === 0)
    return 1;
  return n * factorial (n - 1);
}

Let's test if the addon works:

console.log(addon.factorial(10), 'should equal', factorial(10));
// 3628800 should equal 3628800

Success!

That's all for today.