/*! * lunr.Vector * Copyright (C) @YEAR Oliver Nightingale */ /** * lunr.Vectors implement vector related operations for * a series of elements. * * @constructor */ lunr.Vector = function () { this._magnitude = null this.list = undefined this.length = 0 } /** * lunr.Vector.Node is a simple struct for each node * in a lunr.Vector. * * @private * @param {Number} The index of the node in the vector. * @param {Object} The data at this node in the vector. * @param {lunr.Vector.Node} The node directly after this node in the vector. * @constructor * @memberOf Vector */ lunr.Vector.Node = function (idx, val, next) { this.idx = idx this.val = val this.next = next } /** * Inserts a new value at a position in a vector. * * @param {Number} The index at which to insert a value. * @param {Object} The object to insert in the vector. * @memberOf Vector. */ lunr.Vector.prototype.insert = function (idx, val) { this._magnitude = undefined; var list = this.list if (!list) { this.list = new lunr.Vector.Node (idx, val, list) return this.length++ } if (idx < list.idx) { this.list = new lunr.Vector.Node (idx, val, list) return this.length++ } var prev = list, next = list.next while (next != undefined) { if (idx < next.idx) { prev.next = new lunr.Vector.Node (idx, val, next) return this.length++ } prev = next, next = next.next } prev.next = new lunr.Vector.Node (idx, val, next) return this.length++ } /** * Calculates the magnitude of this vector. * * @returns {Number} * @memberOf Vector */ lunr.Vector.prototype.magnitude = function () { if (this._magnitude) return this._magnitude var node = this.list, sumOfSquares = 0, val while (node) { val = node.val sumOfSquares += val * val node = node.next } return this._magnitude = Math.sqrt(sumOfSquares) } /** * Calculates the dot product of this vector and another vector. * * @param {lunr.Vector} otherVector The vector to compute the dot product with. * @returns {Number} * @memberOf Vector */ lunr.Vector.prototype.dot = function (otherVector) { var node = this.list, otherNode = otherVector.list, dotProduct = 0 while (node && otherNode) { if (node.idx < otherNode.idx) { node = node.next } else if (node.idx > otherNode.idx) { otherNode = otherNode.next } else { dotProduct += node.val * otherNode.val node = node.next otherNode = otherNode.next } } return dotProduct } /** * Calculates the cosine similarity between this vector and another * vector. * * @param {lunr.Vector} otherVector The other vector to calculate the * similarity with. * @returns {Number} * @memberOf Vector */ lunr.Vector.prototype.similarity = function (otherVector) { return this.dot(otherVector) / (this.magnitude() * otherVector.magnitude()) }