Buffer and Native Arrays

Introduction

Node also supports native arrays and Buffer objects; these are 1 dimensional arrays who's elements are equivalent to the Julia's concept of a native type. These arrays come with the cost of some loss of flexibility because they are of one element type and can not be increased in size, however for that they they gain an efficiency of about 10x speed.

Besides being declared differently than normal arrays, native arrays are used largely in the same way.

var a = new Float64Array(1000);

for(var i = 0;i < a.length;i++) a[i] = i;

An application can gain a large speed advantage if it can can manage around the loss of flexibility. Many applications where Julia is used consist of high speed calculations on increments of a a set size of data and so can meet this criterion. Thus, in version 0.2.1, the datatype mapping support has been extended to include these types as well.

Native Array Mapping

Javascript native arrays are mapped to the following:

Javascript TypeJulia Type
Int8ArrayArray{Int8,1}
Uint8ArrayArray{Uint8,1}
Int16ArrayArray{Int16,1}
Uint16ArrayArray{Uint16,1}
Int32ArrayArray{Int32,1}
Uint32ArrayArray{Uint32,1}
Float32ArrayArray{Float32,1}
Float64ArrayArray{Float64,1}
BufferArray{Uint8,1}

NativeArrays are used whenever possible

The cases above are further extended to include multidimensional arrays. So long as the element type is numeric then NativeArrays will be used as defined below. A Julia array of N dimensions will be mapped to JavaScript Array of N-1 dimensions where the elements of the rightmost dimension will be NativeArrays. The following table gives the element type mapping.

Julia Element TypeJavaScript NativeArray
Float64Float64Array
Float32Float32Array
Int64Float64Array*
UInt64Float64Array*
Int32Int32Array
UInt32Uint32Array
Int16Uint16Array
UInt16Uint16Array
Int8Int8Array
UInt8UIntArray**

The following example illustrates the creation of these arrays

var julia = require('node-julia');

var a = julia.eval('[i for i = 1:8]');
var r = julia.exec('reshape',a,2,2,2);

console.log("Array a: ",a);
console.log("Array r:");
for(var i = 0;i < 2;i++) {
   for(var j = 0;j < 2;j++) {
      console.log('[' + r[i][j][0] + ', ' + r[i][j][1] + ']');
   }
   console.log('');
}

which produces the following output:

Array a:  { '0': 1, '1': 2, '2': 3, '3': 4, '4': 5, '5': 6, '6': 7, '7': 8 }
Array r:
[1, 5]
[3, 7]

[2, 6]
[4, 8]

Arrays of Native Arrays mapped to Julia multidimensional arrays

To facilitate using the output of the mapping above as arguments for Julia functions, JavaScript arrays of dimension N where the element type are NativeArrays are mapped to Julia arrays of dimension N + 1 of the appropriate type. The following illustrates the possibilities

var julia = require('node-julia');

var e1 = new Float64Array(2);
var e2 = new Float64Array(2);
var a = [e1,e2];

e1[0] = e2[1] = 1;
e1[1] = e2[0] = 2;

var aInv = julia.exec('inv',a);
var b = julia.exec('*',a,aInv);

console.log('a times a inverse (should be identity matrix)');
for(var i = 0;i < 2;i++) {
   console.log('[' + b[i][0] + ', ' + b[i][1] + ']');
}

which produces

a times a inverse (should be identity matrix)
[1, 0]
[0, 1]

Element type Int64 mapped to Float64Array*

In JavaScript, there is no Int64Array type due to Number being implicitly a double value. Thus the closest approximation is Float64Array.

The special case of Buffer**

Because Javascript Buffer objects are closely tied to native arrays of Uint8, the Julia type Array{Uint8,1} when it appears as a single result and not as part of a multidimensional array will be returned as a JavaScript Buffer.

Julia Array TypeJavascript Type
Array{Uint8,1}Buffer

This transformation only applies if the dimension of the source array is 1 for example if a buffer of 16 elements is created and returned with the following:

var a = new Buffer(16);

for(var i = 0;i < a.length;i++) a[i] = i;

console.log(julia.exec('identity',a));

this produces the following:

<Buffer 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f>

while if instead the dimensions are changed to 4x4 using the following:

var a = new Buffer(16);

for(var i = 0;i < a.length;i++) a[i] = i;

console.log(julia.exec('reshape',a,4,4));

this produces the following (an array of 4 UInt8Arrays instead of Buffer):

[ { '0': 0, '1': 4, '2': 8, '3': 12 },
  { '0': 1, '1': 5, '2': 9, '3': 13 },
  { '0': 2, '1': 6, '2': 10, '3': 14 },
  { '0': 3, '1': 7, '2': 11, '3': 15 } ]