vector.js 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. /*!
  2. * lunr.Vector
  3. * Copyright (C) @YEAR Oliver Nightingale
  4. */
  5. /**
  6. * lunr.Vectors implement vector related operations for
  7. * a series of elements.
  8. *
  9. * @constructor
  10. */
  11. lunr.Vector = function () {
  12. this._magnitude = null
  13. this.list = undefined
  14. this.length = 0
  15. }
  16. /**
  17. * lunr.Vector.Node is a simple struct for each node
  18. * in a lunr.Vector.
  19. *
  20. * @private
  21. * @param {Number} The index of the node in the vector.
  22. * @param {Object} The data at this node in the vector.
  23. * @param {lunr.Vector.Node} The node directly after this node in the vector.
  24. * @constructor
  25. * @memberOf Vector
  26. */
  27. lunr.Vector.Node = function (idx, val, next) {
  28. this.idx = idx
  29. this.val = val
  30. this.next = next
  31. }
  32. /**
  33. * Inserts a new value at a position in a vector.
  34. *
  35. * @param {Number} The index at which to insert a value.
  36. * @param {Object} The object to insert in the vector.
  37. * @memberOf Vector.
  38. */
  39. lunr.Vector.prototype.insert = function (idx, val) {
  40. this._magnitude = undefined;
  41. var list = this.list
  42. if (!list) {
  43. this.list = new lunr.Vector.Node (idx, val, list)
  44. return this.length++
  45. }
  46. if (idx < list.idx) {
  47. this.list = new lunr.Vector.Node (idx, val, list)
  48. return this.length++
  49. }
  50. var prev = list,
  51. next = list.next
  52. while (next != undefined) {
  53. if (idx < next.idx) {
  54. prev.next = new lunr.Vector.Node (idx, val, next)
  55. return this.length++
  56. }
  57. prev = next, next = next.next
  58. }
  59. prev.next = new lunr.Vector.Node (idx, val, next)
  60. return this.length++
  61. }
  62. /**
  63. * Calculates the magnitude of this vector.
  64. *
  65. * @returns {Number}
  66. * @memberOf Vector
  67. */
  68. lunr.Vector.prototype.magnitude = function () {
  69. if (this._magnitude) return this._magnitude
  70. var node = this.list,
  71. sumOfSquares = 0,
  72. val
  73. while (node) {
  74. val = node.val
  75. sumOfSquares += val * val
  76. node = node.next
  77. }
  78. return this._magnitude = Math.sqrt(sumOfSquares)
  79. }
  80. /**
  81. * Calculates the dot product of this vector and another vector.
  82. *
  83. * @param {lunr.Vector} otherVector The vector to compute the dot product with.
  84. * @returns {Number}
  85. * @memberOf Vector
  86. */
  87. lunr.Vector.prototype.dot = function (otherVector) {
  88. var node = this.list,
  89. otherNode = otherVector.list,
  90. dotProduct = 0
  91. while (node && otherNode) {
  92. if (node.idx < otherNode.idx) {
  93. node = node.next
  94. } else if (node.idx > otherNode.idx) {
  95. otherNode = otherNode.next
  96. } else {
  97. dotProduct += node.val * otherNode.val
  98. node = node.next
  99. otherNode = otherNode.next
  100. }
  101. }
  102. return dotProduct
  103. }
  104. /**
  105. * Calculates the cosine similarity between this vector and another
  106. * vector.
  107. *
  108. * @param {lunr.Vector} otherVector The other vector to calculate the
  109. * similarity with.
  110. * @returns {Number}
  111. * @memberOf Vector
  112. */
  113. lunr.Vector.prototype.similarity = function (otherVector) {
  114. return this.dot(otherVector) / (this.magnitude() * otherVector.magnitude())
  115. }