132 lines
2.8 KiB
JavaScript
132 lines
2.8 KiB
JavaScript
/*!
|
|
* 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())
|
|
}
|