Skip to content

Instantly share code, notes, and snippets.

@jussi-kalliokoski
Created January 31, 2012 11:13
Show Gist options
  • Save jussi-kalliokoski/1709956 to your computer and use it in GitHub Desktop.
Save jussi-kalliokoski/1709956 to your computer and use it in GitHub Desktop.
Light-weight Vector class for JS
/* JS SHELL */
if (typeof load !== 'undefined') {
load('./vector.js');
/* NODEJS */
} else if (typeof require !== 'undefined') {
Vector = require('./vector.js');
print = function () {
return console.log.apply(console, arguments);
};
/* BROWSER */
} else if (typeof window !== 'undefined' && window.console && window.Vector) {
print = function () {
return console.log.apply(console, arguments);
};
/* UNKNOWN ENVIRONMENT */
} else {
throw "FAILED: Unknown environment.";
}
function printVec (v) {
print('({' + [].map.call(v.buffer, function (v, i) {
return i + ':' + v;
}).join(', ') + '})');
}
var k, x;
for (k in Vector) {
if (Object.hasOwnProperty.call(Vector, k)) {
throw "FAILED: Vector has enumerable properties.";
}
}
x = new Vector(new Vector.FLOAT32([1,2,3,4]));
printVec(x);
printVec(x.add(16));
printVec(x.add(x));
printVec(x.substract(-1));
printVec(x.multiply(3));
printVec(x.pow(2));
printVec(x.sin());
var Vector = (function (types, funcs, k) {
function setValue (obj, name, value) {
Object.defineProperty(obj, name, {
value: value,
enumerable: false,
writable: true,
});
}
function setConst (obj, name, value) {
Object.defineProperty(obj, name, {
value: value,
enumerable: false,
writable: false,
});
}
function forNames(obj, callback) {
var k;
for (k in obj) {
if (Object.prototype.hasOwnProperty.call(obj, k)) {
callback(k, obj[k]);
}
}
}
function Vector (type, length) {
setConst(this, 'buffer', type && type.prototype ? new type(length) : type);
setConst(this, 'length', this.buffer.length);
setConst(this, 'type', this.buffer.constructor);
}
var ops = {
'add': function (a, b) {
return a + b;
},
'substract': function (a, b) {
return a - b;
},
'multiply': function (a, b) {
return a * b;
},
'divide': function (a, b) {
return a / b;
},
'mod': function (a, b) {
return a % b;
},
};
Vector.util = {};
forNames(ops, function (k, op) {
Vector.util[k] = function (a, r, b) {
var i, n;
if (typeof b === 'number') {
for (i=0; i<a.length; i++) {
r.buffer[i] = op(a.buffer[i], b);
}
} else if (b && b.VECTOR) {
for (i=0; i<a.length; i++) {
r.buffer[i] = op(a.buffer[i], b.buffer[i % b.length]);
}
} else {
throw new TypeError('Cannot perform vector operations on ' + (typeof b) + '.');
}
};
});
funcs.forEach(function (k) {
Vector.util[k] = function (a, r, b) {
var op = Math[k],
i, n;
if (typeof b === 'number') {
for (i=0; i<a.length; i++) {
r.buffer[i] = op(a.buffer[i], b);
}
} else if (b && b.VECTOR) {
for (i=0; i<a.length; i++) {
r.buffer[i] = op(a.buffer[i], b.buffer[i % b.length]);
}
} else if (arguments.length === 2) {
for (i=0; i<a.length; i++) {
r.buffer[i] = op(a.buffer[i]);
}
} else {
throw new TypeError('Cannot perform vector operations on ' + (typeof b) + '.');
}
};
});
Vector.prototype = {
VECTOR: true,
buffer: null,
type: null,
length: null,
copy: function () {
return new Vector(this.type, this.length);
},
toString: function () {
return this.buffer.toString().replace(/Array/, 'Vector');
},
};
forNames(Vector.util, function (k) {
Vector.prototype[k] = function () {
var r = this.copy();
Vector.util[k].apply(Vector.util,
[this, r].concat([].slice.call(arguments)));
return r;
};
});
var self = this;
types.forEach(function (type) {
Vector[type.toUpperCase()] = self[type + 'Array'];
});
Vector.UNTYPED = Array;
forNames(Vector, function (k, v) {
setValue(Vector, k, v);
});
self.Vector = Vector;
if (typeof exports !== 'undefined') {
module.exports = Vector;
}
return Vector;
}([
'Uint8',
'Uint16',
'Uint32',
'Int8',
'Int16',
'Int32',
'Float32',
'Float64'
], [
'abs',
'acos',
'asin',
'atan',
'atan2',
'ceil',
'cos',
'exp',
'floor',
'log',
'max',
'min',
'pow',
'round',
'sin',
'sqrt',
'tan'
]));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment